Creating and managing Notification Configs

This page describes how to use the Security Command Center API notifications feature, including the following examples:

  • Create a NotificationConfig
  • Get a NotificationConfig
  • Update a NotificationConfig
  • Delete a NotificationConfig
  • List NotificationConfig
  • Receive Pub/Sub notifications

Alternatively, Security Command Center Premium customers can set up Continuous Exports for Pub/Sub in the Security Command Center dashboard.

Before you begin

To use the examples on this page, you need to complete the guide to Set up finding notifications.

To execute the following examples, you need an Identity and Access Management (IAM) role with appropriate permissions:

  • Create NotificationConfig: Security Center Notification Configurations Editor (roles/securitycenter.notificationConfigEditor)
  • Get and List NotificationConfig: Security Center Notification Configurations Viewer (roles/securitycenter.notificationConfigViewer) or Security Center Notification Configurations Editor (roles/securitycenter.notificationConfigEditor)
  • Update and Delete NotificationConfig: Security Center Notification Configurations Editor (roles/securitycenter.notificationConfigEditor)

To grant appropriate roles to a principal that accesses a notificationConfig, you must have one of the following IAM roles:

  • Organization Administrator (roles/resourcemanager.organizationAdmin)
  • Folder IAM Admin (roles/resourcemanager.folderIamAdmin)
  • Project IAM Admin (roles/resourcemanager.projectIamAdmin)

The IAM roles for Security Command Center can be granted at the organization, folder, or project level. Your ability to view, edit, create, or update findings, assets, and security sources depends on the level for which you are granted access. To learn more about Security Command Center roles, see Access control.

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

Creating a NotificationConfig

To create a NotificationConfig, you must have:

  • An existing Pub/Sub topic that you want to send notifications to.
  • Required IAM roles for the principal that creates the notificationConfig.

For more information, see the step to Set up a Pub/Sub topic in the guide to Set up finding notifications.

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.

Getting a NotificationConfig

To get a NotificationConfig, you must have an IAM role that includes the securitycenter.notification.get permission.

gcloud

gcloud scc notifications describe PARENT_TYPE/PARENT_ID/locations/LOCATION/notificationConfigs/NOTIFICATION_NAME

Replace the following:

  • PARENT_TYPE with organizations, folders, or projects, depending on which level of the resource hierarchy was specified in the notification configuration.
  • PARENT_ID with the numeric ID of the parent resource.
  • LOCATION: required if either data residency is enabled or the notificationConfig resources were created by using the API v2.

    If data residency is enabled, specify the Security Command Center location in which the notifications are stored.

    If data residency is not enabled, include /locations/LOCATION only if the notificationConfig resource was created by using the Security Command Center API v2, in which case, the only valid location is global.

  • NOTIFICATION_NAME: the name of the notification.

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 get_notification_config(parent_id, notification_config_id):
    """
    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"
    """
    from google.cloud import securitycenter as securitycenter

    client = securitycenter.SecurityCenterClient()

    notification_config_name = (
        f"{parent_id}/notificationConfigs/{notification_config_id}"
    )

    notification_config = client.get_notification_config(
        request={"name": notification_config_name}
    )
    print(f"Got notification config: {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.NotificationConfig;
import com.google.cloud.securitycenter.v1.SecurityCenterClient;
import java.io.IOException;

public class GetNotificationConfigSnippets {

  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}";

    getNotificationConfig(parentId, notificationConfigId);
  }

  // Retrieve an existing notification config.
  public static NotificationConfig getNotificationConfig(
      String parentId, String notificationConfigId) 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()) {
      NotificationConfig response =
          client.getNotificationConfig(String.format("%s/notificationConfigs/%s",
              parentId, notificationConfigId));

      System.out.printf("Notification config: %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 getNotificationConfig(w io.Writer, orgID string, notificationConfigID string) error {
	// orgID := "your-org-id"
	// 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()

	// Parent must be in one of the following formats:
	//		"organizations/{orgId}"
	//		"projects/{projectId}"
	//		"folders/{folderId}"
	parent := fmt.Sprintf("organizations/%s", orgID)
	req := &securitycenterpb.GetNotificationConfigRequest{
		Name: fmt.Sprintf("%s/notificationConfigs/%s", parent, notificationConfigID),
	}

	notificationConfig, err := client.GetNotificationConfig(ctx, req)
	if err != nil {
		return fmt.Errorf("Failed to retrieve notification config: %w", err)
	}
	fmt.Fprintln(w, "Received config: ", 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();

// formattedConfigName: You can also use
//    `client.projectNotificationConfigPath(projectId, configId)` or
//    `client.folderNotificationConfigPath(folderId, configId)`.
// configId = "your-config-id";
const formattedConfigName = client.organizationNotificationConfigPath(
  organizationId,
  configId
);

async function getNotificationConfg() {
  const [response] = await client.getNotificationConfig({
    name: formattedConfigName,
  });
  console.log('Notification config: ', response);
}

getNotificationConfg();

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\GetNotificationConfigRequest;

/**
 * @param string $organizationId        Your org ID
 * @param string $notificationConfigId  A unique identifier
 */
function get_notification(string $organizationId, string $notificationConfigId): void
{
    $securityCenterClient = new SecurityCenterClient();
    $notificationConfigName = $securityCenterClient::notificationConfigName(
        // You can also use 'projectId' or 'folderId' instead of the 'organizationId'.
        $organizationId,
        $notificationConfigId
    );
    $getNotificationConfigRequest = (new GetNotificationConfigRequest())
        ->setName($notificationConfigName);

    $response = $securityCenterClient->getNotificationConfig($getNotificationConfigRequest);
    printf('Notification config was retrieved: %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"

client = Google::Cloud::SecurityCenter.security_center

# You can also use 'project_id' or 'folder_id' as a parent.
config_path = client.notification_config_path organization:        org_id,
                                              notification_config: config_id

response = client.get_notification_config name: config_path
puts "Notification config fetched: #{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.Cloud.SecurityCenter.V1;
using System;

/// <summary>Snippet for GetNotificationConfig</summary>
public class GetNotificationConfigSnippets
{
    public static NotificationConfig GetNotificationConfig(string organizationId, string configId)
    {
        SecurityCenterClient client = SecurityCenterClient.Create();
        // You can also use 'projectId' or 'folderId' instead of the 'organizationId'.
        NotificationConfigName notificationConfigName = new NotificationConfigName(organizationId, configId);

        NotificationConfig response = client.GetNotificationConfig(notificationConfigName);
        Console.WriteLine($"Notification config: {response}");
        return response;
    }
}

Updating a NotificationConfig

To update a NotificationConfig, you must have an IAM role that includes the securitycenter.notification.update permission.

When you update using a field mask, only the fields you specify are updated. If you don't use a field mask, all mutable fields in the NotificationConfig are replaced by the new values. You can use a field mask to update the Pub/Sub topic and description.

To complete this example, you must be subscribed to the new topic, and your notifications service account must have the pubsub.topics.setIamPolicy permission on the topic.

After you grant the necessary permissions, update the NotificationConfig description, Pub/Sub topic and filter using the language of your choice:

gcloud

gcloud scc notifications update PARENT_TYPE/PARENT_ID/locations/LOCATION/notificationConfigs/NOTIFICATION_NAME
--description="NOTIFICATION_DESCRIPTION" \
--pubsub-topic=PUBSUB_TOPIC \
--filter="FILTER"

Replace the following:

  • PARENT_TYPE with organizations, folders, or projects, depending on which level of the resource hierarchy was specified in the notification configuration.
  • PARENT_ID with the numeric ID of the parent resource.
  • LOCATION: required if either data residency is enabled or the notificationConfig was created by using the API v2.

    If data residency is enabled, specify the Security Command Center location in which the notification is stored.

    If data residency is not enabled, include /locations/LOCATION in the full name or specify the --location flag only if the notificationConfig resource was created by using the Security Command Center API v2, in which case, the only valid location is global.

  • NOTIFICATION_NAME: the name of the notification.

  • NOTIFICATION_DESCRIPTION: a description of the notification of no more than 1,024 characters.

  • PUBSUB_TOPIC: the Pub/Sub topic which 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 update_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: "config-id-to-update"
        pubsub_topic: "projects/{new-project}/topics/{new-topic}"

    If updating a pubsub_topic, ensure this ServiceAccount has the
    "pubsub.topics.setIamPolicy" permission on the new topic.
    """
    from google.cloud import securitycenter as securitycenter
    from google.protobuf import field_mask_pb2

    client = securitycenter.SecurityCenterClient()

    notification_config_name = (
        f"{parent_id}/notificationConfigs/{notification_config_id}"
    )

    updated_description = "New updated description"
    updated_filter = 'state = "INACTIVE"'

    # Only description and pubsub_topic can be updated.
    field_mask = field_mask_pb2.FieldMask(
        paths=["description", "pubsub_topic", "streaming_config.filter"]
    )

    updated_notification_config = client.update_notification_config(
        request={
            "notification_config": {
                "name": notification_config_name,
                "description": updated_description,
                "pubsub_topic": pubsub_topic,
                "streaming_config": {"filter": updated_filter},
            },
            "update_mask": field_mask,
        }
    )

    print(updated_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.NotificationConfig;
import com.google.cloud.securitycenter.v1.NotificationConfig.StreamingConfig;
import com.google.cloud.securitycenter.v1.SecurityCenterClient;
import com.google.protobuf.FieldMask;
import java.io.IOException;

public class UpdateNotificationConfigSnippets {

  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}";

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

  // Update an existing notification config.
  // If updating a Pubsub Topic, ensure the ServiceAccount has the
  // "pubsub.topics.setIamPolicy" permission on the new topic.
  public static NotificationConfig updateNotificationConfig(
      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()) {

      String notificationConfigName =
          String.format(
              "%s/notificationConfigs/%s", parentId, notificationConfigId);

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

      NotificationConfig configToUpdate =
          NotificationConfig.newBuilder()
              .setName(notificationConfigName)
              .setDescription("updated description")
              .setPubsubTopic(pubsubTopic)
              .setStreamingConfig(StreamingConfig.newBuilder().setFilter("state = \"ACTIVE\""))
              .build();

      FieldMask fieldMask =
          FieldMask.newBuilder()
              .addPaths("description")
              .addPaths("pubsub_topic")
              .addPaths("streaming_config.filter")
              .build();

      NotificationConfig updatedConfig = client.updateNotificationConfig(configToUpdate, fieldMask);

      System.out.printf("Notification config: %s%n", updatedConfig);
      return updatedConfig;
    }
  }
}

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"
	"google.golang.org/genproto/protobuf/field_mask"
)

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

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

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

	updatedDescription := "Updated sample config"
	updatedFilter := `state = "INACTIVE"`
	// Parent must be in one of the following formats:
	//		"organizations/{orgId}"
	//		"projects/{projectId}"
	//		"folders/{folderId}"
	parent := fmt.Sprintf("organizations/%s", orgID)
	req := &securitycenterpb.UpdateNotificationConfigRequest{
		NotificationConfig: &securitycenterpb.NotificationConfig{
			Name:        fmt.Sprintf("%s/notificationConfigs/%s", parent, notificationConfigID),
			Description: updatedDescription,
			PubsubTopic: updatedPubsubTopic,
			NotifyConfig: &securitycenterpb.NotificationConfig_StreamingConfig_{
				StreamingConfig: &securitycenterpb.NotificationConfig_StreamingConfig{
					Filter: updatedFilter,
				},
			},
		},
		UpdateMask: &field_mask.FieldMask{
			Paths: []string{"description", "pubsub_topic", "streaming_config.filter"},
		},
	}

	notificationConfig, err := client.UpdateNotificationConfig(ctx, req)
	if err != nil {
		return fmt.Errorf("Failed to update notification config: %w", err)
	}

	fmt.Fprintln(w, "Updated NotificationConfig: ", 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();

// formattedConfigName: You can also use
//    `client.projectNotificationConfigPath(projectId, configId)` or
//    `client.folderNotificationConfigPath(folderId, configId)`.
// configId = "your-config-id";
const formattedConfigName = client.organizationNotificationConfigPath(
  organizationId,
  configId
);

// pubsubTopic = "projects/{your-project}/topics/{your-topic}";
// Ensure this Service Account has the "pubsub.topics.setIamPolicy" permission on this topic.

async function updateNotificationConfig() {
  const [response] = await client.updateNotificationConfig({
    updateMask: {
      paths: ['description', 'pubsub_topic', 'streaming_config.filter'],
    },
    notificationConfig: {
      name: formattedConfigName,
      description: 'Updated config description',
      pubsubTopic: pubsubTopic,
      streamingConfig: {filter: 'state = "INACTIVE"'},
    },
  });
  console.log('notification config update succeeded: ', response);
}

updateNotificationConfig();

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\NotificationConfig;
use Google\Cloud\SecurityCenter\V1\NotificationConfig\StreamingConfig;
use Google\Cloud\SecurityCenter\V1\UpdateNotificationConfigRequest;
use Google\Protobuf\FieldMask;

/**
 * @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 update_notification(
    string $organizationId,
    string $notificationConfigId,
    string $projectId,
    string $topicName
): void {
    $securityCenterClient = new SecurityCenterClient();

    // Ensure this ServiceAccount has the 'pubsub.topics.setIamPolicy' permission on the topic.
    // https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/setIamPolicy
    $pubsubTopic = $securityCenterClient::topicName($projectId, $topicName);
    // You can also use 'projectId' or 'folderId' instead of the 'organizationId'.
    $notificationConfigName = $securityCenterClient::notificationConfigName($organizationId, $notificationConfigId);

    $streamingConfig = (new StreamingConfig())->setFilter('state = "ACTIVE"');
    $fieldMask = (new FieldMask())->setPaths(['description', 'pubsub_topic', 'streaming_config.filter']);
    $notificationConfig = (new NotificationConfig())
        ->setName($notificationConfigName)
        ->setDescription('Updated description.')
        ->setPubsubTopic($pubsubTopic)
        ->setStreamingConfig($streamingConfig);
    $updateNotificationConfigRequest = (new UpdateNotificationConfigRequest())
        ->setNotificationConfig($notificationConfig);

    $response = $securityCenterClient->updateNotificationConfig($updateNotificationConfigRequest);
    printf('Notification config was updated: %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"

# Updated description of the notification config.
# description = "YOUR_DESCRIPTION"

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

# Updated filter string for Notification config.
# filter = "UPDATED_FILTER"

client = Google::Cloud::SecurityCenter.security_center

# You can also use 'project_id' or 'folder_id' as a parent.
config_path = client.notification_config_path organization:        org_id,
                                              notification_config: config_id
notification_config = { name: config_path }
notification_config[:description] = description unless description.nil?
notification_config[:pubsub_topic] = pubsub_topic unless pubsub_topic.nil?
notification_config[:streaming_config][:filter] = filter unless filter.nil?

paths = []
paths.push "description" unless description.nil?
paths.push "pubsub_topic" unless pubsub_topic.nil?
paths.push "streaming_config.filter" unless filter.nil?
update_mask = { paths: paths }

response = client.update_notification_config(
  notification_config: notification_config,
  update_mask:         update_mask
)
puts 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.Cloud.SecurityCenter.V1;
using static Google.Cloud.SecurityCenter.V1.NotificationConfig.Types;
using Google.Protobuf.WellKnownTypes;
using System;

/// <summary>Snippet for UpdateNotificationConfig</summary>
public class UpdateNotificationConfigSnippets
{
    public static NotificationConfig UpdateNotificationConfig(
        string organizationId, string notificationConfigId, string projectId, string topicName)
    {
        // You can also use 'projectId' or 'folderId' instead of the 'organizationId'.
        NotificationConfigName notificationConfigName = new NotificationConfigName(organizationId, notificationConfigId);
        TopicName pubsubTopic = new TopicName(projectId, topicName);

        NotificationConfig configToUpdate = new NotificationConfig
        {
            NotificationConfigName = notificationConfigName,
            Description = "updated description",
            PubsubTopicAsTopicName = pubsubTopic,
            StreamingConfig = new StreamingConfig { Filter = "state = \"INACTIVE\"" }
        };

        FieldMask fieldMask = new FieldMask { Paths = { "description", "pubsub_topic", "streaming_config.filter" } };
        SecurityCenterClient client = SecurityCenterClient.Create();
        NotificationConfig updatedConfig = client.UpdateNotificationConfig(configToUpdate, fieldMask);

        Console.WriteLine($"Notification config updated: {updatedConfig}");
        return updatedConfig;
    }
}

Deleting a NotificationConfig

To delete a NotificationConfig, you must have an IAM role that includes the securitycenter.notification.delete permission.

When you delete a NotificationConfig, the securitycenter.notificationServiceAgent role stays on the Pub/Sub topic. If you aren't using the Pub/Sub topic in any other NotificationConfig, remove the role from the topic. For more information, see access control.

Delete a NotificationConfig using the language of your choice:

gcloud

gcloud scc notifications delete PARENT_TYPE/PARENT_ID/locations/LOCATION/notificationConfigs/NOTIFICATION_NAME

Replace the following:

  • PARENT_TYPE with organizations, folders, or projects, depending on which level of the resource hierarchy was specified in the notification configuration.
  • PARENT_ID with the numeric ID of the parent resource.
  • LOCATION: required if either data residency is enabled or the notificationConfig was created by using the API v2.

    If data residency is enabled, specify the Security Command Center location in which the notification is stored.

    If data residency is not enabled, include /locations/LOCATION in the full name or specify the --location flag only if the notificationConfig was created by using the Security Command Center API v2, in which case, the only valid location is global.

  • NOTIFICATION_NAME: the name of the notification.

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 delete_notification_config(parent_id, notification_config_id):
    """
    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"
    """
    from google.cloud import securitycenter as securitycenter

    client = securitycenter.SecurityCenterClient()

    notification_config_name = (
        f"{parent_id}/notificationConfigs/{notification_config_id}"
    )

    client.delete_notification_config(request={"name": notification_config_name})
    print(f"Deleted notification config: {notification_config_name}")

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.SecurityCenterClient;
import java.io.IOException;

public class DeleteNotificationConfigSnippets {

  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}";

    deleteNotificationConfig(parentId, notificationConfigId);
  }

  // Delete a notification config.
  public static boolean deleteNotificationConfig(String parentId, String notificationConfigId)
      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()) {

      client.deleteNotificationConfig(String.format("%s/notificationConfigs/%s",
          parentId, notificationConfigId));

      System.out.printf("Deleted Notification config: %s%n", notificationConfigId);
    }
    return true;
  }
}

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 deleteNotificationConfig(w io.Writer, orgID string, notificationConfigID string) error {
	// orgID := "your-org-id"
	// notificationConfigID := "config-to-delete"

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

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

	// Parent must be in one of the following formats:
	//		"organizations/{orgId}"
	//		"projects/{projectId}"
	//		"folders/{folderId}"
	parent := fmt.Sprintf("organizations/%s", orgID)
	name := fmt.Sprintf("%s/notificationConfigs/%s", parent, notificationConfigID)
	req := &securitycenterpb.DeleteNotificationConfigRequest{
		Name: name,
	}

	if err = client.DeleteNotificationConfig(ctx, req); err != nil {
		return fmt.Errorf("Failed to retrieve notification config: %w", err)
	}
	fmt.Fprintln(w, "Deleted config: ", name)

	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();

// formattedConfigName: You can also use
//    `client.projectNotificationConfigPath(projectId, configId)` or
//    `client.folderNotificationConfigPath(folderId, configId)`.
// configId = "your-config-id";
const formattedConfigName = client.organizationNotificationConfigPath(
  organizationId,
  configId
);

async function deleteNotificationConfg() {
  await client.deleteNotificationConfig({name: formattedConfigName});
  console.log('Notification config deleted: ', formattedConfigName);
}

deleteNotificationConfg();

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\DeleteNotificationConfigRequest;

/**
 * @param string $organizationId        Your org ID
 * @param string $notificationConfigId  A unique identifier
 */
function delete_notification(string $organizationId, string $notificationConfigId): void
{
    $securityCenterClient = new SecurityCenterClient();
    $notificationConfigName = $securityCenterClient::notificationConfigName(
        // You can also use 'projectId' or 'folderId' instead of the 'organizationId'.
        $organizationId,
        $notificationConfigId
    );
    $deleteNotificationConfigRequest = (new DeleteNotificationConfigRequest())
        ->setName($notificationConfigName);

    $securityCenterClient->deleteNotificationConfig($deleteNotificationConfigRequest);
    print('Notification config was deleted' . PHP_EOL);
}

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"

client = Google::Cloud::SecurityCenter.security_center

# You can also use 'project_id' or 'folder_id' as a parent.
config_path = client.notification_config_path organization:        org_id,
                                              notification_config: config_id

response = client.delete_notification_config name: config_path
puts "Deleted notification config #{config_id} with response: #{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.Cloud.SecurityCenter.V1;
using System;

/// <summary>Snippet for DeleteNotificationConfig</summary>
public class DeleteNotificationConfigSnippets
{
    public static bool DeleteNotificationConfig(string organizationId, string notificationConfigId)
    {
        // You can also use 'projectId' or 'folderId' instead of the 'organizationId'.
        NotificationConfigName notificationConfigName = new NotificationConfigName(organizationId, notificationConfigId);
        SecurityCenterClient client = SecurityCenterClient.Create();

        client.DeleteNotificationConfig(notificationConfigName);
        Console.WriteLine($"Deleted Notification config: {notificationConfigName}");
        return true;
    }
}

Listing NotificationConfigs

To list NotificationConfigs, you must have an IAM role that includes the securitycenter.notification.list permission.

All Security Command Center API lists are paginated. Each response returns a page of results and a token to return the next page. The default pageSize is 10. You can configure page size to a minimum of 1, and a maximum of 1000.

List NotificationConfigs using the language of your choice:

gcloud

gcloud scc notifications list PARENT_TYPE/PARENT_ID/locations/LOCATION

Replace the following:

  • PARENT_TYPE with organizations, folders, or projects, depending on the scope at which you need to list notifications.
  • PARENT_ID with the numeric ID of the parent resource.
  • LOCATION: required if either data residency is enabled or the notificationConfig resources were created by using the API v2.

    If data residency is enabled, specify the Security Command Center location in which the notifications are stored.

    If data residency is not enabled, including /locations/LOCATION in the name or the --location flag in the command lists only the notificationConfig resources that were created by using the Security Command Center API v2 and the only valid location is global.

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 list_notification_configs(parent_id):
    """
    Args:
        parent_id: must be in one of the following formats:
            "organizations/{organization_id}"
            "projects/{project_id}"
            "folders/{folder_id}"
    """
    from google.cloud import securitycenter as securitycenter

    client = securitycenter.SecurityCenterClient()

    notification_configs_iterator = client.list_notification_configs(
        request={"parent": parent_id}
    )
    for i, config in enumerate(notification_configs_iterator):
        print(f"{i}: notification_config: {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.NotificationConfig;
import com.google.cloud.securitycenter.v1.SecurityCenterClient;
import com.google.cloud.securitycenter.v1.SecurityCenterClient.ListNotificationConfigsPagedResponse;
import com.google.common.collect.ImmutableList;
import java.io.IOException;

public class ListNotificationConfigSnippets {

  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");

    listNotificationConfigs(parentId);
  }

  // List notification configs present in the given parent.
  public static ImmutableList<NotificationConfig> listNotificationConfigs(String parentId)
      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()) {

      ListNotificationConfigsPagedResponse response = client.listNotificationConfigs(parentId);

      ImmutableList<NotificationConfig> notificationConfigs =
          ImmutableList.copyOf(response.iterateAll());

      System.out.printf("List notifications response: %s%n", response.getPage().getValues());
      return notificationConfigs;
    }
  }
}

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"
	"google.golang.org/api/iterator"
)

func listNotificationConfigs(w io.Writer, orgID string) error {
	// orgId := "your-org-id"

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

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

	req := &securitycenterpb.ListNotificationConfigsRequest{
		// Parent must be in one of the following formats:
		//		"organizations/{orgId}"
		//		"projects/{projectId}"
		//		"folders/{folderId}"
		Parent: fmt.Sprintf("organizations/%s", orgID),
	}
	it := client.ListNotificationConfigs(ctx, req)
	for {
		result, err := it.Next()
		if err == iterator.Done {
			break
		}

		if err != nil {
			return fmt.Errorf("it.Next: %w", err)
		}

		fmt.Fprintln(w, "NotificationConfig: ", result)
	}

	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}`
const parent = `organizations/${organizationId}`;

async function listNotificationConfigs() {
  const [resources] = await client.listNotificationConfigs({parent: parent});
  console.log('Received Notification configs: ');
  for (const resource of resources) {
    console.log(resource);
  }
}

listNotificationConfigs();

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\ListNotificationConfigsRequest;

/**
 * @param string $organizationId        Your org ID
 */
function list_notification(string $organizationId): void
{
    $securityCenterClient = new SecurityCenterClient();
    // 'parent' must be in one of the following formats:
    //		"organizations/{orgId}"
    //		"projects/{projectId}"
    //		"folders/{folderId}"
    $parent = $securityCenterClient::organizationName($organizationId);
    $listNotificationConfigsRequest = (new ListNotificationConfigsRequest())
        ->setParent($parent);

    foreach ($securityCenterClient->listNotificationConfigs($listNotificationConfigsRequest) as $element) {
        printf('Found notification config %s' . PHP_EOL, $element->getName());
    }

    print('Notification configs were listed' . PHP_EOL);
}

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"

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

client.list_notification_configs(parent: parent).each_page do |page|
  page.each do |element|
    puts element
  end
end

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.Api.Gax;
using Google.Cloud.SecurityCenter.V1;
using System;

/// <summary>Snippet for ListNotificationConfig</summary>
public class ListNotificationConfigSnippets
{
    public static PagedEnumerable<ListNotificationConfigsResponse, NotificationConfig> ListNotificationConfigs(string organizationId)
    {
        // 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);
        SecurityCenterClient client = SecurityCenterClient.Create();
        PagedEnumerable<ListNotificationConfigsResponse, NotificationConfig> notificationConfigs = client.ListNotificationConfigs(orgName);

        // Print Notification Configuration names.
        foreach (var config in notificationConfigs)
        {
            Console.WriteLine(config.NotificationConfigName);
        }
        return notificationConfigs;
    }
}

Receiving Pub/Sub notifications

This section provides a sample notification message and examples that show how to convert a Pub/Sub message into a NotificationMessage that contains a finding.

Notifications are published to Pub/Sub in the JSON format. Following is an example of a notification message:

{
   "notificationConfigName": "organizations/ORGANIZATION_ID/notificationConfigs/CONFIG_ID",
   "finding": {
     "name": "organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID",
     "parent": "organizations/ORGANIZATION_ID/sources/SOURCE_ID",
     "state": "ACTIVE",
     "category": "TEST-CATEGORY",
     "securityMarks": {
       "name": "organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID/securityMarks"
     },
     "eventTime": "2019-07-26T07:32:37Z",
     "createTime": "2019-07-29T18:45:27.243Z"
   }
 }

Convert a Pub/Sub message into a NotificationMessage using the language of your choice:

gcloud

The gcloud CLI doesn't support converting a Pub/Sub message into a NotificationMessage. You can use the gcloud CLI to get a NotificationMessage and print the JSON directly in your terminal:

  # The subscription used to receive published messages from a topic
  PUBSUB_SUBSCRIPTION="projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID"

  gcloud pubsub subscriptions pull $PUBSUB_SUBSCRIPTION

Replace the following:

  • PROJECT_ID with your project ID.
  • SUBSCRIPTION_ID with your subscription ID.

Python

# Requires https://cloud.google.com/pubsub/docs/quickstart-client-libraries#pubsub-client-libraries-python
import concurrent

from google.cloud import pubsub_v1
from google.cloud.securitycenter_v1 import NotificationMessage

# TODO: project_id = "your-project-id"
# TODO: subscription_name = "your-subscription-name"

def callback(message):
    # Print the data received for debugging purpose if needed
    print(f"Received message: {message.data}")

    notification_msg = NotificationMessage.from_json(message.data)

    print(
        "Notification config name: {}".format(
            notification_msg.notification_config_name
        )
    )
    print(f"Finding: {notification_msg.finding}")

    # Ack the message to prevent it from being pulled again
    message.ack()

subscriber = pubsub_v1.SubscriberClient()
subscription_path = subscriber.subscription_path(project_id, subscription_name)

streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)

print(f"Listening for messages on {subscription_path}...\n")
try:
    streaming_pull_future.result(timeout=1)  # Block for 1 second
except concurrent.futures.TimeoutError:
    streaming_pull_future.cancel()

Java


import com.google.cloud.pubsub.v1.AckReplyConsumer;
import com.google.cloud.pubsub.v1.MessageReceiver;
import com.google.cloud.pubsub.v1.Subscriber;
import com.google.cloud.securitycenter.v1.NotificationMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.pubsub.v1.PubsubMessage;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class NotificationReceiver {

  private NotificationReceiver() {
  }

  public static void receiveNotificationMessages(String projectId, String subscriptionId) {
    // String projectId = "{your-project}";
    // String subscriptionId = "{your-subscription}";
    ProjectSubscriptionName subscriptionName =
        ProjectSubscriptionName.of(projectId, subscriptionId);

    try {
      Subscriber subscriber =
          Subscriber.newBuilder(subscriptionName, new NotificationMessageReceiver()).build();
      subscriber.startAsync().awaitRunning();

      // This sets the timeout value of the subscriber to 10s.
      subscriber.awaitTerminated(10_000, TimeUnit.MILLISECONDS);
    } catch (IllegalStateException | TimeoutException e) {
      System.out.println("Subscriber stopped: " + e);
    }
  }

  static class NotificationMessageReceiver implements MessageReceiver {

    @Override
    public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
      NotificationMessage.Builder notificationMessageBuilder = NotificationMessage.newBuilder();

      try {
        String jsonString = message.getData().toStringUtf8();
        JsonFormat.parser().merge(jsonString, notificationMessageBuilder);

        NotificationMessage notificationMessage = notificationMessageBuilder.build();
        System.out.println(
            String.format("Config id: %s", notificationMessage.getNotificationConfigName()));
        System.out.println(String.format("Finding: %s", notificationMessage.getFinding()));
      } catch (InvalidProtocolBufferException e) {
        System.out.println("Could not parse message: " + e);
      } finally {
        consumer.ack();
      }
    }
  }
}

Go

import (
	"bytes"
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/pubsub"
	"cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
	"github.com/golang/protobuf/jsonpb"
)

func receiveMessages(w io.Writer, projectID string, subscriptionName string) error {
	// projectID := "your-project-id"
	// subsriptionName := "your-subscription-name"

	ctx := context.Background()

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

	sub := client.Subscription(subscriptionName)
	cctx, cancel := context.WithCancel(ctx)
	err = sub.Receive(cctx, func(ctx context.Context, msg *pubsub.Message) {
		var notificationMessage = new(securitycenterpb.NotificationMessage)
		jsonpb.Unmarshal(bytes.NewReader(msg.Data), notificationMessage)

		fmt.Fprintln(w, "Got finding: ", notificationMessage.GetFinding())
		msg.Ack()
		cancel()
	})
	if err != nil {
		return fmt.Errorf("Receive: %w", err)
	}

	return nil
}

Node.js

const {PubSub} = require('@google-cloud/pubsub');
const {StringDecoder} = require('string_decoder');

// projectId = 'your-project-id'
// subscriptionId = 'your-subscription-id'

const subscriptionName =
  'projects/' + projectId + '/subscriptions/' + subscriptionId;
const pubSubClient = new PubSub();

function listenForMessages() {
  const subscription = pubSubClient.subscription(subscriptionName);

  // message.data is a buffer array of json
  // 1. Convert buffer to normal string
  // 2. Convert json to NotificationMessage object
  const messageHandler = message => {
    const jsonString = new StringDecoder('utf-8').write(message.data);
    const parsedNotificationMessage = JSON.parse(jsonString);

    console.log(parsedNotificationMessage);
    console.log(parsedNotificationMessage.finding);

    // ACK when done with message
    message.ack();
  };

  subscription.on('message', messageHandler);

  // Set timeout to 10 seconds
  setTimeout(() => {
    subscription.removeListener('message', messageHandler);
  }, 10000);
}

listenForMessages();

PHP

use Google\Cloud\PubSub\PubSubClient;

/**
 * @param string $projectId             Your Cloud Project ID
 * @param string $subscriptionId        Your subscription ID
 */
function receive_notification(string $projectId, string $subscriptionId): void
{
    $pubsub = new PubSubClient([
        'projectId' => $projectId,
    ]);
    $subscription = $pubsub->subscription($subscriptionId);

    foreach ($subscription->pull() as $message) {
        printf('Message: %s' . PHP_EOL, $message->data());
        // Acknowledge the Pub/Sub message has been received, so it will not be pulled multiple times.
        $subscription->acknowledge($message);
    }
}

What's next