创建和管理通知配置

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

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

或者,Security Command Center 高级方案客户也可以 设置持续导出

准备工作

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

要执行以下示例,您需要具有适当权限的 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:父级组织、文件夹或 项目,以 organizations/123 格式指定, folders/456projects/789
  • LOCATION:如果启用了数据驻留,请指定用于创建通知的 Security Command Center 位置。生成的 notificationConfig 资源仅存储在此位置。只有在此位置发出的发现结果会发送到 Pub/Sub。

如果未启用数据驻留,则指定 --location 标志可创建 使用 Security Command Center API v2 发出通知,并且是唯一有效的 该标志的值为 global。 * NOTIFICATION_DESCRIPTION:通知说明,不超过 1,024 个字符。* PUBSUB_TOPIC:Cloud 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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

// 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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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 添加到资源名称中。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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 时创建的 并且会自动获得 securitycenter.notificationServiceAgent 角色 (针对 PUBSUB_TOPIC 的 IAM 政策)。这个 需要有服务账号角色,通知才能正常运行。

获取 NotificationConfig

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

gcloud

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

替换以下内容:

  • PARENT_TYPEorganizationsfoldersprojects 搭配使用,具体取决于通知配置中指定的资源层次结构级别。
  • PARENT_ID 替换为父级资源的数字 ID。
  • LOCATION:如果启用了任一数据驻留选项,或者使用 API v2 创建了 notificationConfig 资源,则必需提供此值。

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

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

  • NOTIFICATION_NAME:通知的名称。

Python

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

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

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 添加到资源名称中。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

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 添加到资源名称中。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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_TYPEorganizationsfoldersprojects 搭配使用,具体取决于通知配置中指定的资源层次结构级别。
  • PARENT_ID 替换为父资源的数字 ID。
  • LOCATION:如果是数据驻留,则为必需 或者 notificationConfig 是使用 API v2。

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

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

  • NOTIFICATION_NAME:通知的名称。

  • NOTIFICATION_DESCRIPTION:对 不超过 1,024 个字符的通知。

  • 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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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 添加到资源名称中。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。


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_TYPEorganizationsfoldersprojects 搭配使用,具体取决于通知配置中指定的资源层次结构级别。
  • PARENT_ID 替换为父资源的数字 ID。
  • LOCATION:如果启用了任一数据驻留选项,或者使用 API v2 创建了 notificationConfig,则必填。

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

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

  • NOTIFICATION_NAME:通知的名称。

Python

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

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

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

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 添加到资源名称中。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。


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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

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 添加到资源名称中。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。


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_TYPEorganizationsfolders、 或 projects,具体取决于您需要列出 通知。
  • PARENT_ID 替换为父级的数字 ID 资源。
  • LOCATION:如果启用了任一数据驻留选项,或者使用 API v2 创建了 notificationConfig 资源,则必需提供此值。

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

    如果未启用数据驻留,包括 /locations/LOCATION,或 命令中的 --location 标志只会列出 notificationConfig使用 Security Command Center API v2 和 唯一的有效位置是 global

Python

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

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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 添加到资源名称中。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

// 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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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

对于发现结果,请将 /locations/LOCATION 添加到资源中 名称在 /sources/SOURCE_ID 之后,其中 SOURCE_IDSecurity Command Center 服务 发出该发现结果。

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 设置为资源名称。

对于大多数资源,请将 /locations/LOCATION 添加到 资源名称在 /PARENT/PARENT_ID 之后,其中 PARENTorganizationsfolders、 或 projects

对于发现结果,请在资源名称的 /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);
    }
}

后续步骤