创建和管理通知配置

本页面介绍如何使用 Security Command Center API 通知功能,包括以下示例:

  • 创建 NotificationConfig
  • 获取 NotificationConfig
  • 更新 NotificationConfig
  • 删除 NotificationConfig
  • 列出 NotificationConfig
  • 接收 Pub/Sub 通知

或者,Security Command Center Premium 客户可以在 Security Command Center 信息中心为 Pub/Sub 设置持续导出

准备工作

要使用此页面上的示例,您需要完成设置发现结果通知指南。

要执行以下示例,您需要具有适当权限的 Identity and Access Management (IAM) 角色:

  • 创建 NotificationConfig:Security Center Notification Configurations Editor (roles/securitycenter.notificationConfigEditor)
  • 获取并列出 NotificationConfig:Security Center Notification Configurations Viewer (roles/securitycenter.notificationConfigViewer) 或 Security Center Notification Configurations Editor (roles/securitycenter.notificationConfigEditor)
  • 更新和删除 NotificationConfig:Security Center Notification Configurations Editor (roles/securitycenter.notificationConfigEditor)

如需向访问 notificationConfig 的主账号授予适当的角色,您必须具有以下 IAM 角色之一:

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

Security Command Center 的 IAM 角色可以在组织、文件夹或项目级层授予。您能否查看、修改、创建或更新发现结果、资产和安全来源,取决于您获授予的访问权限级别。如需详细了解 Security Command Center 角色,请参阅访问权限控制

数据驻留和通知

如果 Security Command Center 启用了数据驻留,则用于定义持续导出到 Pub/Sub(notificationConfig 资源)的配置受数据驻留控制,并存储在您的 Security Command Center 位置

如需将某个 Security Command Center 位置中的发现结果导出到 Pub/Sub,您必须在发现结果所在的 Security Command Center 位置配置持续导出。

由于持续导出中使用的过滤条件可能包含受驻留控制措施约束的数据,因此在创建它们之前,请务必指定正确的位置。Security Command Center 不限制您在哪个位置创建导出作业。

持续导出仅存储在创建它们的位置,无法在其他位置查看或修改。

创建持续导出后,便无法更改其位置。如需更改位置,您需要删除持续导出,然后在新位置重新创建。

如需使用 API 调用检索连续导出,您需要在 notificationConfig 的完整资源名称中指定位置。例如:

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

同样,如需使用 gcloud CLI 检索连续导出,您需要在配置的完整资源名称中或使用 --locations 标志指定位置。例如:

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

创建 NotificationConfig

要创建 NotificationConfig,您必须具有:

  • 您要向其发送通知的现有 Pub/Sub 主题。
  • 创建 notificationConfig 的主账号所需的 IAM 角色。

如需了解详情,请参阅设置发现结果通知指南中的设置 Pub/Sub 主题步骤。

创建 NotificationConfig 之前,请注意每个组织只能有一定数量的 NotificationConfig 文件。如需了解详情,请参阅配额和限制

NotificationConfig 包含一个 filter 字段,用于限制对有用事件的通知。此字段接受 Security Command Center API findings.list 方法中提供的所有过滤条件。

创建 NotificationConfig 时,您需要为 Google Cloud 资源层次结构中的 NotificationConfig 指定一个父项,可以是组织、文件夹或项目。如果您稍后需要检索、更新或删除 NotificationConfig,则需要在引用时添加父级组织、文件夹或项目的数字 ID。

使用您选择的语言或平台创建 NotificationConfig

gcloud

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

替换以下内容:

  • NOTIFICATION_NAME:通知的名称。长度必须介于 1 到 128 个字符之间,并且只能包含字母数字字符、下划线或连字符。
  • PARENT:通知适用的资源层次结构中的范围,即 organizationfolderproject
  • PARENT_ID:父级组织、文件夹或项目的 ID,采用 organizations/123folders/456projects/789 格式指定。
  • LOCATION:如果启用了数据驻留,请指定要在其中创建通知的 Security Command Center 位置。生成的 notificationConfig 资源仅存储在此位置。系统仅会将在此位置发布的发现结果发送到 Pub/Sub。

    如果未启用数据驻留,则指定 --location 标志会使用 Security Command Center API v2 创建通知,并且该标志的唯一有效值为 global

  • NOTIFICATION_DESCRIPTION:不超过 1024 个字符的通知说明。

  • PUBSUB_TOPIC:将接收通知的 Pub/Sub 主题。其格式为 projects/PROJECT_ID/topics/TOPIC

  • FILTER:您定义的表达式,用于选择将哪些发现结果发送到 Pub/Sub。例如 state="ACTIVE"

Python

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

// 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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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#

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

通知现已发布到您指定的 Pub/Sub 主题。

如需发布通知,系统会以 service-org-ORGANIZATION_ID@gcp-sa-scc-notification.iam.gserviceaccount.com 的形式为您创建一个服务账号。此服务账号是在您创建第一个 NotificationConfig 时由系统创建的,并在创建通知配置时被自动授予 PUBSUB_TOPIC 的 IAM 政策上的 securitycenter.notificationServiceAgent 角色。需要此服务账号角色才能接收通知。

获取 NotificationConfig

如需获取 NotificationConfig,您必须具有包含 securitycenter.notification.get 权限的 IAM 角色。

gcloud

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

替换以下内容:

  • PARENT_TYPE 替换为 organizationsfoldersprojects,具体取决于在通知配置中指定的资源层次结构的级别。
  • PARENT_ID 替换为父资源的数字 ID。
  • LOCATION:如果已启用数据驻留,或者 notificationConfig 资源是使用 API v2 创建的,则为必需。

    如果启用了数据驻留,请指定存储通知的 Security Command Center 位置

    如果未启用数据驻留,请仅在 notificationConfig 资源是使用 Security Command Center API v2 创建的情况下添加 /locations/LOCATION(在这种情况下,唯一有效的位置是 global)。

  • NOTIFICATION_NAME:通知的名称。

Python

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

// 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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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#

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

更新 NotificationConfig

要更新 NotificationConfig,您必须具有包含 securitycenter.notification.update 权限的 IAM 角色。

使用字段掩码更新时,只有指定的字段才会更新。如果您不使用字段掩码,则 NotificationConfig 中的所有可变字段都将替换为新值。您可以使用字段掩码来更新 Pub/Sub 主题和说明。

如需完成此示例,您必须订阅新主题,并且您的通知服务账号必须具有该主题的 pubsub.topics.setIamPolicy 权限。

授予必要的权限后,使用您选择的语言更新 NotificationConfig 说明、Pub/Sub 主题和过滤条件:

gcloud

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

替换以下内容:

  • PARENT_TYPE 替换为 organizationsfoldersprojects,具体取决于在通知配置中指定的资源层次结构的级别。
  • PARENT_ID 替换为父资源的数字 ID。
  • LOCATION:如果启用了数据驻留或 notificationConfig 是使用 API v2 创建的,则需要。

    如果启用了数据驻留,请指定存储通知的 Security Command Center 位置

    如果未启用数据驻留,则仅当 notificationConfig 资源是使用 Security Command Center API v2 创建时,才在全名中包含 /locations/LOCATION 或指定 --location 标志(在这种情况下,唯一有效的位置是 global)。

  • NOTIFICATION_NAME:通知的名称。

  • NOTIFICATION_DESCRIPTION:不超过 1024 个字符的通知说明。

  • PUBSUB_TOPIC:将接收通知的 Pub/Sub 主题。其格式为 projects/PROJECT_ID/topics/TOPIC

  • FILTER:您定义的表达式,用于选择将哪些发现结果发送到 Pub/Sub。例如 state="ACTIVE"

Python

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

// 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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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#

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

删除 NotificationConfig

要删除 NotificationConfig,您必须具有包含 securitycenter.notification.delete 权限的 IAM 角色。

删除 NotificationConfig 时,securitycenter.notificationServiceAgent 角色将保留在 Pub/Sub 主题上。如果您在任何其他 NotificationConfig 中使用 Pub/Sub 主题,请从主题中移除该角色。如需了解详情,请参阅访问控制

使用您选择的语言删除 NotificationConfig

gcloud

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

替换以下内容:

  • PARENT_TYPE 替换为 organizationsfoldersprojects,具体取决于在通知配置中指定的资源层次结构的级别。
  • PARENT_ID 替换为父资源的数字 ID。
  • LOCATION:如果启用了数据驻留或 notificationConfig 是使用 API v2 创建的,则需要。

    如果启用了数据驻留,请指定存储通知的 Security Command Center 位置

    如果未启用数据驻留,则仅当 notificationConfig 是使用 Security Command Center API v2 创建时,才在全名中包含 /locations/LOCATION 或指定 --location 标志(在这种情况下,唯一有效的位置是 global)。

  • NOTIFICATION_NAME:通知的名称。

Python

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

// 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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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#

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

列出 NotificationConfig

要列出 NotificationConfigs,您必须拥有一个包含 securitycenter.notification.list 权限的 IAM 角色。

所有 Security Command Center API 列表均已分页。每个响应都会返回一个结果页面和一个返回下一页的令牌。默认 pageSize 为 10。您可以将页面大小配置为最小值 1,最大值 1000。

使用您选择的语言列出 NotificationConfigs

gcloud

gcloud scc notifications list PARENT_TYPE/PARENT_ID/locations/LOCATION

替换以下内容:

  • PARENT_TYPE 替换为 organizationsfoldersprojects,具体取决于您列出通知的范围。
  • PARENT_ID 替换为父资源的数字 ID。
  • LOCATION:如果已启用数据驻留,或者 notificationConfig 资源是使用 API v2 创建的,则为必需。

    如果启用了数据驻留,请指定存储通知的 Security Command Center 位置

    如果未启用数据驻留,则在名称中包含 /locations/LOCATION 或命令中的 --location 标志只会列出使用 Security Command Center API v2 创建的 notificationConfig 资源,并且唯一有效的位置是 global

Python

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

// 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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。

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#

以下示例使用 v1 API。如需修改 v2 的示例,请将 v1 替换为 v2,并将 /locations/LOCATION 添加到资源名称中。

对于大多数资源,请在资源名称的 /PARENT/PARENT_ID 后添加 /locations/LOCATION,其中 PARENTorganizationsfoldersprojects

对于发现结果,请在资源名称的 /sources/SOURCE_ID 后添加 /locations/LOCATION,其中 SOURCE_ID 是发出发现结果的 Security Command Center 服务的 ID。


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

接收 Pub/Sub 通知

本部分提供了一个示例通知消息和示例,展示如何将 Pub/Sub 消息转换为包含发现结果的 NotificationMessage

通知以 JSON 格式发布到 Pub/Sub。以下是通知消息的示例:

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

使用您选择的语言将 Pub/Sub 消息转换为 NotificationMessage

gcloud

gcloud CLI 不支持将 Pub/Sub 消息转换为 NotificationMessage。您可以使用 gcloud CLI 获取 NotificationMessage 并直接在终端中输出 JSON

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

  gcloud pubsub subscriptions pull $PUBSUB_SUBSCRIPTION

替换以下内容:

  • PROJECT_ID 替换为您的项目 ID。
  • SUBSCRIPTION_ID 替换为您的订阅 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);
    }
}

后续步骤