Enable finding notifications for Pub/Sub

This page explains how to enable Security Command Center API notifications.

Notifications send findings and finding updates to a Pub/Sub topic within minutes. Security Command Center API notifications include all of the finding information that is displayed by Security Command Center in the Google Cloud console.

You can connect Security Command Center notifications in Pub/Sub directly to Cloud Run functions actions. For example functions that can help with response, enrichment, and remediation, see the Security Command Center open-source repository of Cloud Run functions code. The repository contains solutions to help you take automated actions on security findings.

Alternatively, you can export findings to BigQuery, or you can set up Continuous Exports for Pub/Sub in the Google Cloud console.

Before you begin

  1. To get the permissions that you need to set up and configure Security Command Center API notifications, ask your administrator to grant you the following IAM roles:

    • Security Center Admin (roles/securitycenter.admin) on the organization or project where Security Command Center is activated
    • Project IAM Admin (roles/resourcemanager.projectIamAdmin) on the project where you will create your Pub/Sub topic

    For more information about granting roles, see Manage access to projects, folders, and organizations.

    You might also be able to get the required permissions through custom roles or other predefined roles.

  2. Enable the Security Command Center API:

    gcloud services enable securitycenter.googleapis.com

Data residency and notifications

If data residency is enabled for Security Command Center, the configurations that define continuous exports to Pub/Sub—notificationConfig resources—are subject to data residency control and are stored in your Security Command Center location.

To export findings in a Security Command Center location to Pub/Sub, you must configure the continuous export in the same Security Command Center location as the findings.

Because the filters that are used in continuous exports can contain data that is subject to residency controls, make sure you specify the correct location before you create them. Security Command Center does not restrict which location you create exports in.

Continuous exports are stored only in the location in which they are created and cannot be viewed or edited in other locations.

After you create a continuous export, you can't change its location. To change the location, you need to delete the continuous export and recreate it in the new location.

To retrieve a continuous export by using API calls, you need to specify the location in the full resource name of the notificationConfig. For example:

GET https://securitycenter.googleapis.com/v2/{name=organizations/123/locations/eu/notificationConfigs/my-pubsub-export-01}

Similarly, to retrieve a continuous export by using the gcloud CLI, you need to specify the location either in the full resource name of the configuration or by using the --locations flag. For example:

gcloud scc notifications describe myContinuousExport organizations/123 \
    --location=locations/us

Set up a Pub/Sub topic

In this task, you create and subscribe to the Pub/Sub topic that you want to send notifications to.

Step 1: Set up Pub/Sub

To set up and subscribe to a Pub/Sub topic, do the following:

  1. Go to the Google Cloud console.

    Go to the Google Cloud console

  2. Select the project where you enabled the Security Command Center API.

  3. Click Activate Cloud Shell.

  4. Optional: To create a new Pub/Sub topic, run the following command:

    gcloud pubsub topics create TOPIC_ID
    

    Replace TOPIC_ID with a topic name.

  5. Create a subscription to the topic:

    gcloud pubsub subscriptions create SUBSCRIPTION_ID --topic=TOPIC_ID
    

    Replace the following:

    • SUBSCRIPTION_ID: the subscription ID
    • TOPIC_ID: the topic ID

To learn more about setting up Pub/Sub, see Managing topics and subscriptions.

Step 2: Grant role on Pub/Sub topic

To create a NotificationConfig, you need the Pub/Sub Admin role (roles/pubsub.admin) on the Pub/Sub topic for which you created a subscription.

To grant this role, do the following:

  1. Go to the Google Cloud console.

    Go to the Google Cloud console

  2. Select the project for which you enabled the Security Command Center API.

  3. Click Activate Cloud Shell.

  4. Grant the required role to your Google Account on the Pub/Sub topic:

    gcloud pubsub topics add-iam-policy-binding \
        projects/PUBSUB_PROJECT/topics/TOPIC_ID \
        --member="user:GOOGLE_ACCOUNT" \
        --role="roles/pubsub.admin"
    

    Replace the following:

    • PUBSUB_PROJECT: the Google Cloud project that contains your Pub/Sub topic
    • TOPIC_ID: the topic ID
    • GOOGLE_ACCOUNT: the email address for your Google Account

Create a NotificationConfig

Before you create a NotificationConfig, note that each organization can have a limited number of NotificationConfig files. For more information, see Quotas and limits.

The NotificationConfig includes a filter field that limits notifications to useful events. This field accepts all of the filters that are available in the Security Command Center API findings.list method.

When you create a NotificationConfig, you specify a parent for the NotificationConfig from the Google Cloud resource hierarchy, either an organization, a folder, or a project. If you need to retrieve, update, or delete the NotificationConfig later, you need to include the numerical ID of the parent organization, folder, or project when you reference it.

To create the NotificationConfig using the language or platform of your choice:

gcloud

gcloud scc notifications create NOTIFICATION_NAME \
--PARENT=PARENT_ID \
--location=LOCATION
--description="NOTIFICATION_DESCRIPTION" \
--pubsub-topic=PUBSUB_TOPIC \
--filter="FILTER"

Replace the following:

  • NOTIFICATION_NAME: the name of the notification. Must be between 1 and 128 characters and contain alphanumeric characters, underscores, or hyphens only.
  • PARENT: the scope in the resource hierarchy to which the notification applies, organization, folder, or project.
  • PARENT_ID: the ID of the parent organization, folder, or project, specified in the format of organizations/123, folders/456, or projects/789.
  • LOCATION: If data residency is enabled, specify the Security Command Center location in which to create the notification. The resulting notificationConfig resource is stored only in this location. Only findings that are issued in this location are sent to Pub/Sub.

If data residency is not enabled, specifying the --location flag creates the notification by using Security Command Center API v2, and the only valid value for the flag is global. * NOTIFICATION_DESCRIPTION: a description of the notification of no more than 1,024 characters. * PUBSUB_TOPIC: The Pub/Sub topic that will receive notifications. Its format is projects/PROJECT_ID/topics/TOPIC. * FILTER: the expression you define to select which findings get sent to Pub/Sub. For example, state=\"ACTIVE\".

Python

The following sample uses the v1 API. To modify the sample for v2, replace v1 with v2 and add /locations/LOCATION to the resource name.

For most resources, add /locations/LOCATION to the resource name after /PARENT/PARENT_ID, where PARENT is organizations, folders, or projects.

For findings, add /locations/LOCATION to the resource name after /sources/SOURCE_ID, where SOURCE_ID is the ID of the Security Command Center service that issued the finding.

def create_notification_config(parent_id, notification_config_id, pubsub_topic):
    """
    Args:
        parent_id: must be in one of the following formats:
            "organizations/{organization_id}"
            "projects/{project_id}"
            "folders/{folder_id}"
        notification_config_id: "your-config-id"
        pubsub_topic: "projects/{your-project-id}/topics/{your-topic-ic}"

    Ensure this ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the new topic.
    """
    from google.cloud import securitycenter as securitycenter

    client = securitycenter.SecurityCenterClient()

    created_notification_config = client.create_notification_config(
        request={
            "parent": parent_id,
            "config_id": notification_config_id,
            "notification_config": {
                "description": "Notification for active findings",
                "pubsub_topic": pubsub_topic,
                "streaming_config": {"filter": 'state = "ACTIVE"'},
            },
        }
    )

    print(created_notification_config)

Java

The following sample uses the v1 API. To modify the sample for v2, replace v1 with v2 and add /locations/LOCATION to the resource name.

For most resources, add /locations/LOCATION to the resource name after /PARENT/PARENT_ID, where PARENT is organizations, folders, or projects.

For findings, add /locations/LOCATION to the resource name after /sources/SOURCE_ID, where SOURCE_ID is the ID of the Security Command Center service that issued the finding.


import com.google.cloud.securitycenter.v1.CreateNotificationConfigRequest;
import com.google.cloud.securitycenter.v1.NotificationConfig;
import com.google.cloud.securitycenter.v1.NotificationConfig.StreamingConfig;
import com.google.cloud.securitycenter.v1.SecurityCenterClient;
import java.io.IOException;

public class CreateNotificationConfigSnippets {

  public static void main(String[] args) throws IOException {
    // parentId: must be in one of the following formats:
    //    "organizations/{organization_id}"
    //    "projects/{project_id}"
    //    "folders/{folder_id}"
    String parentId = String.format("organizations/%s", "ORG_ID");
    String notificationConfigId = "{config-id}";
    String projectId = "{your-project}";
    String topicName = "{your-topic}";

    createNotificationConfig(parentId, notificationConfigId, projectId, topicName);
  }

  // Crete a notification config.
  // Ensure the ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the new topic.
  public static NotificationConfig createNotificationConfig(
      String parentId, String notificationConfigId, String projectId, String topicName)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (SecurityCenterClient client = SecurityCenterClient.create()) {

      // Ensure this ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the topic.
      String pubsubTopic = String.format("projects/%s/topics/%s", projectId, topicName);

      CreateNotificationConfigRequest request =
          CreateNotificationConfigRequest.newBuilder()
              .setParent(parentId)
              .setConfigId(notificationConfigId)
              .setNotificationConfig(
                  NotificationConfig.newBuilder()
                      .setDescription("Java notification config")
                      .setPubsubTopic(pubsubTopic)
                      .setStreamingConfig(
                          StreamingConfig.newBuilder().setFilter("state = \"ACTIVE\"").build())
                      .build())
              .build();

      NotificationConfig response = client.createNotificationConfig(request);
      System.out.printf("Notification config was created: %s%n", response);
      return response;
    }
  }
}

Go

The following sample uses the v1 API. To modify the sample for v2, replace v1 with v2 and add /locations/LOCATION to the resource name.

For most resources, add /locations/LOCATION to the resource name after /PARENT/PARENT_ID, where PARENT is organizations, folders, or projects.

For findings, add /locations/LOCATION to the resource name after /sources/SOURCE_ID, where SOURCE_ID is the ID of the Security Command Center service that issued the finding.

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
)

func createNotificationConfig(w io.Writer, orgID string, pubsubTopic string, notificationConfigID string) error {
	// orgID := "your-org-id"
	// pubsubTopic := "projects/{your-project}/topics/{your-topic}"
	// notificationConfigID := "your-config-id"

	ctx := context.Background()
	client, err := securitycenter.NewClient(ctx)

	if err != nil {
		return fmt.Errorf("securitycenter.NewClient: %w", err)
	}
	defer client.Close()

	req := &securitycenterpb.CreateNotificationConfigRequest{
		// Parent must be in one of the following formats:
		//		"organizations/{orgId}"
		//		"projects/{projectId}"
		//		"folders/{folderId}"
		Parent:   fmt.Sprintf("organizations/%s", orgID),
		ConfigId: notificationConfigID,
		NotificationConfig: &securitycenterpb.NotificationConfig{
			Description: "Go sample config",
			PubsubTopic: pubsubTopic,
			NotifyConfig: &securitycenterpb.NotificationConfig_StreamingConfig_{
				StreamingConfig: &securitycenterpb.NotificationConfig_StreamingConfig{
					Filter: `state = "ACTIVE"`,
				},
			},
		},
	}

	notificationConfig, err := client.CreateNotificationConfig(ctx, req)
	if err != nil {
		return fmt.Errorf("Failed to create notification config: %w", err)
	}
	fmt.Fprintln(w, "New NotificationConfig created: ", notificationConfig)

	return nil
}

Node.js

The following sample uses the v1 API. To modify the sample for v2, replace v1 with v2 and add /locations/LOCATION to the resource name.

For most resources, add /locations/LOCATION to the resource name after /PARENT/PARENT_ID, where PARENT is organizations, folders, or projects.

For findings, add /locations/LOCATION to the resource name after /sources/SOURCE_ID, where SOURCE_ID is the ID of the Security Command Center service that issued the finding.

// npm install '@google-cloud/security-center'
const {SecurityCenterClient} = require('@google-cloud/security-center');

const client = new SecurityCenterClient();

// parent: must be in one of the following formats:
//    `organizations/${organization_id}`
//    `projects/${project_id}`
//    `folders/${folder_id}`
// configId = "your-config-name";
// pubsubTopic = "projects/{your-project}/topics/{your-topic}";
// Ensure this Service Account has the "pubsub.topics.setIamPolicy" permission on this topic.
const parent = `organizations/${organizationId}`;

async function createNotificationConfig() {
  const [response] = await client.createNotificationConfig({
    parent: parent,
    configId: configId,
    notificationConfig: {
      description: 'Sample config for node.js',
      pubsubTopic: pubsubTopic,
      streamingConfig: {filter: 'state = "ACTIVE"'},
    },
  });
  console.log('Notification config creation succeeded: ', response);
}

createNotificationConfig();

PHP

The following sample uses the v1 API. To modify the sample for v2, replace v1 with v2 and add /locations/LOCATION to the resource name.

For most resources, add /locations/LOCATION to the resource name after /PARENT/PARENT_ID, where PARENT is organizations, folders, or projects.

For findings, add /locations/LOCATION to the resource name after /sources/SOURCE_ID, where SOURCE_ID is the ID of the Security Command Center service that issued the finding.

use Google\Cloud\SecurityCenter\V1\Client\SecurityCenterClient;
use Google\Cloud\SecurityCenter\V1\CreateNotificationConfigRequest;
use Google\Cloud\SecurityCenter\V1\NotificationConfig;
use Google\Cloud\SecurityCenter\V1\NotificationConfig\StreamingConfig;

/**
 * @param string $organizationId        Your org ID
 * @param string $notificationConfigId  A unique identifier
 * @param string $projectId             Your Cloud Project ID
 * @param string $topicName             Your topic name
 */
function create_notification(
    string $organizationId,
    string $notificationConfigId,
    string $projectId,
    string $topicName
): void {
    $securityCenterClient = new SecurityCenterClient();
    // 'parent' must be in one of the following formats:
    //		"organizations/{orgId}"
    //		"projects/{projectId}"
    //		"folders/{folderId}"
    $parent = $securityCenterClient::organizationName($organizationId);
    $pubsubTopic = $securityCenterClient::topicName($projectId, $topicName);

    $streamingConfig = (new StreamingConfig())->setFilter('state = "ACTIVE"');
    $notificationConfig = (new NotificationConfig())
        ->setDescription('A sample notification config')
        ->setPubsubTopic($pubsubTopic)
        ->setStreamingConfig($streamingConfig);
    $createNotificationConfigRequest = (new CreateNotificationConfigRequest())
        ->setParent($parent)
        ->setConfigId($notificationConfigId)
        ->setNotificationConfig($notificationConfig);

    $response = $securityCenterClient->createNotificationConfig($createNotificationConfigRequest);
    printf('Notification config was created: %s' . PHP_EOL, $response->getName());
}

Ruby

The following sample uses the v1 API. To modify the sample for v2, replace v1 with v2 and add /locations/LOCATION to the resource name.

For most resources, add /locations/LOCATION to the resource name after /PARENT/PARENT_ID, where PARENT is organizations, folders, or projects.

For findings, add /locations/LOCATION to the resource name after /sources/SOURCE_ID, where SOURCE_ID is the ID of the Security Command Center service that issued the finding.

require "google/cloud/security_center"

# Your organization id. e.g. for "organizations/123", this would be "123".
# org_id = "YOUR_ORGANZATION_ID"

# Your notification config id. e.g. for
# "organizations/123/notificationConfigs/my-config" this would be "my-config".
# config_id = "YOUR_CONFIG_ID"

# The PubSub topic where notifications will be published.
# pubsub_topic = "YOUR_TOPIC"

client = Google::Cloud::SecurityCenter.security_center

# You can also use 'project_id' or 'folder_id' as a parent.
# client.project_path project: project_id
# client.folder_path folder: folder_id
parent = client.organization_path organization: org_id

notification_config = {
  description:      "Sample config for Ruby",
  pubsub_topic:     pubsub_topic,
  streaming_config: { filter: 'state = "ACTIVE"' }
}

response = client.create_notification_config(
  parent:              parent,
  config_id:           config_id,
  notification_config: notification_config
)
puts "Created notification config #{config_id}: #{response}."

C#

The following sample uses the v1 API. To modify the sample for v2, replace v1 with v2 and add /locations/LOCATION to the resource name.

For most resources, add /locations/LOCATION to the resource name after /PARENT/PARENT_ID, where PARENT is organizations, folders, or projects.

For findings, add /locations/LOCATION to the resource name after /sources/SOURCE_ID, where SOURCE_ID is the ID of the Security Command Center service that issued the finding.


using Google.Api.Gax.ResourceNames;
using Google.Cloud.SecurityCenter.V1;
using System;

///<summary> Create NotificationConfig Snippet. </summary>
public class CreateNotificationConfigSnippets
{
    public static NotificationConfig CreateNotificationConfig(
        string organizationId, string notificationConfigId, string projectId, string topicName)
    {
        // You can also use 'projectId' or 'folderId' instead of the 'organizationId'.
        //      ProjectName projectName = new ProjectName(projectId);
        //      FolderName folderName = new FolderName(folderId);
        OrganizationName orgName = new OrganizationName(organizationId);
        TopicName pubsubTopic = new TopicName(projectId, topicName);

        SecurityCenterClient client = SecurityCenterClient.Create();
        CreateNotificationConfigRequest request = new CreateNotificationConfigRequest
        {
            ParentAsOrganizationName = orgName,
            ConfigId = notificationConfigId,
            NotificationConfig = new NotificationConfig
            {
                Description = ".Net notification config",
                PubsubTopicAsTopicName = pubsubTopic,
                StreamingConfig = new NotificationConfig.Types.StreamingConfig { Filter = "state = \"ACTIVE\"" }
            }
        };

        NotificationConfig response = client.CreateNotificationConfig(request);
        Console.WriteLine($"Notification config was created: {response}");
        return response;
    }
}

Notifications are now published to the Pub/Sub topic you specified.

To publish notifications, a service account is created for you in the form of service-org-ORGANIZATION_ID@gcp-sa-scc-notification.iam.gserviceaccount.com. This service account is created when you create your first NotificationConfig and is automatically granted the securitycenter.notificationServiceAgent role on the IAM policy for PUBSUB_TOPIC when creating the notification config. This service account role is required for notifications to function.

Grant perimeter access in VPC Service Controls

If you use VPC Service Controls and your Pub/Sub topic is part of a project inside a service perimeter, you must grant access to projects in order to create notifications.

To grant access to projects, create ingress and egress rules for the principals and projects that are used to create notifications. The rules allow access to protected resources and let Pub/Sub verify that users have the setIamPolicy permission on the Pub/Sub topic.

Before creating a NotificationConfig

Before completing the steps in Creating a NotificationConfig, do the following:

  1. Go to the VPC Service Controls page in the Google Cloud console.

    Go to VPC Service Controls

  2. If necessary, select your organization.

  3. Click the name of the service perimeter you want to change.

    To find the service perimeter you need to modify, you can check your logs for entries that show RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER violations. In those entries, check the servicePerimeterName field: accessPolicies/ACCESS_POLICY_ID/servicePerimeters/SERVICE_PERIMETER_NAME.

  4. Click Edit Perimeter.

  5. In the navigation menu, click Ingress Policy.

  6. To configure ingress rules for users or service accounts, use the following parameters:

    • FROM attributes of the API client:
      • In the Source drop-down menu, select All Sources.
      • In the Identities drop-down menu, choose Selected identities.
      • Click Select, and then enter the principal that is used to call the Security Command Center API.
    • TO attributes of Google Cloud services/resources:
      • In the Project drop-down menu, choose Selected projects.
      • Click Select, and then enter the project that contains the Pub/Sub topic.
      • In the Services drop-down menu, choose Selected services, and then select Cloud Pub/Sub API.
      • In the Methods drop-down menu, choose All actions.
  7. Click Save.

  8. In the navigation menu, click Egress Policy.

  9. Click Add Rule.

  10. To configure egress rules for user or service accounts, enter the following parameters:

    • FROM attributes of the API client:
      • In the Identities drop-down menu, choose Selected identities.
      • Click Select, and then enter the principal that is used to call the Security Command Center API.
    • TO attributes of Google Cloud services/resources:
      • In the Project drop-down menu, choose All projects.
      • In the Services drop-down menu, choose Selected services, and then select Cloud Pub/Sub API.
      • In the Methods drop-down menu, choose All actions.
  11. Click Save.

Create an ingress rule for the NotificationConfig

To create an ingress rule for a NotificationConfig, do the following:

  1. Complete the instructions in Creating a NotificationConfig.
  2. Re-open the service perimeter from the previous section.
  3. Click Ingress Policy.
  4. Click Add Rule.
  5. To configure the ingress rule for the NotificationConfig service account you created, enter the following parameters:
    • FROM attributes of the API client:
      • In the Source drop-down menu, select All Sources.
      • In the Identities drop-down menu, choose Selected identities.
      • Click Select, and then enter the name of the NotificationConfig service account: service-org-ORGANIZATION_ID@gcp-sa-scc-notification.iam.gserviceaccount.com
    • TO attributes of GCP services/resources:
      • In the Project drop-down menu, choose Selected projects.
      • Click Select, and then select the project that contains the Pub/Sub topic.
      • In the Services drop-down menu, choose Selected services, and then select Cloud Pub/Sub API.
      • In the Methods drop-down menu, choose All actions.
  6. In the navigation menu, click Save.

The selected projects, users, and services accounts can now access the protected resources and create notifications.

If you followed all of the steps in this guide, and notifications are working properly, you can now delete the following:

  • The ingress rule for the principal
  • The egress rule for the principal

Those rules were only needed to configure the NotificationConfig. However, for notifications to continue working, you must keep the ingress rule for the NotificationConfig, which lets it publish notifications to your Pub/Sub topic behind the service perimeter.

What's next