创建和管理通知配置

>

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

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

准备工作

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

要执行以下示例,您需要具有适当权限的身份和访问权限管理 (IAM) 角色:

  • 获取和列出 NotificationConfig:安全中心通知查看者或编辑者
  • 更新和删除 NotificationConfig:安全中心通知编辑者

详细了解 Security Command Center 角色

创建 NotificationConfig

要创建 NotificationConfig,您必须具有:

  • 您要向其发送通知的现有 Pub/Sub 主题。
  • 您的服务帐号或您用于运行 gcloud 工具命令的帐号所需的 IAM 角色。

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

在创建 NotificationConfig 之前,请注意以下事项:

  • 每个组织只能有一定数量的 NotificationConfig 文件。如需了解详情,请参阅配额和限制
  • 您必须拥有组织管理员 IAM 角色,以便向通知服务帐号或 gcloud 工具帐号授予适当的角色。

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

要使用 gcloud 命令行工具向帐号授予安全中心通知配置编辑者 IAM 角色,请执行以下操作:

  1. 设置环境变量:

    1. 设置您的组织名称:

        export ORGANIZATION_ID=organization-id
      
    2. 设置您在设置发现结果通知时创建的服务帐号的电子邮件,或设置用于运行 gcloud 工具命令的帐号:

      • 设置用于运行 gcloud 工具命令的帐号的电子邮件:

        export EMAIL=your-username@email.com
        
      • 或设置服务帐号的电子邮件:

        export EMAIL=service-account-name@$CONSUMER_PROJECT.iam.gserviceaccount.com
        
  2. 向该服务帐号或用于 gcloud 工具命令的帐号授予必要的角色:

    • 向运行 gcloud 工具命令的帐号授予角色:

         gcloud organizations add-iam-policy-binding \
           $ORGANIZATION_ID \
           --member="user:$EMAIL" \
           --role='roles/securitycenter.notificationConfigEditor'
           ```
      
    • 或向服务帐号授予角色:

         gcloud organizations add-iam-policy-binding \
           $ORGANIZATION_ID \
           --member="serviceAccount:$EMAIL" \
           --role='roles/securitycenter.notificationConfigEditor'
           ```
      

向服务帐号或 gcloud 工具帐号授予权限之后,使用您选择的语言或平台创建 NotificationConfig

gcloud

  # The numeric ID of the organization
  ORGANIZATION_ID=organization-id

  # The topic to which the notifications are published
  PUBSUB_TOPIC="projects/project-id/topics/topic-id"

  # The description for the NotificationConfig
  DESCRIPTION="Notifies for active findings"

  # Filters for active findings
  FILTER="state=\"ACTIVE\""

  gcloud scc notifications create notification-name \
    --organization "$ORGANIZATION_ID" \
    --description "$DESCRIPTION" \
    --pubsub-topic $PUBSUB_TOPIC \
    --filter "$FILTER"

Python

from google.cloud import securitycenter as securitycenter

client = securitycenter.SecurityCenterClient()

# TODO: organization_id = "your-org-id"
# TODO: notification_config_id = "your-config-id"
# TODO: pubsub_topic = "projects/{your-project-id}/topics/{your-topic-ic}"
# Ensure this ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the new topic.

org_name = "organizations/{org_id}".format(org_id=organization_id)

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

print(created_notification_config)

Java

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 static NotificationConfig createNotificationConfig(
      String organizationId, String notificationConfigId, String projectId, String topicName)
      throws IOException {
    // String organizationId = "{your-org-id}";
    // String notificationConfigId = {"your-unique-id"};
    // String projectId = "{your-project}"";
    // String topicName = "{your-topic}";

    String orgName = String.format("organizations/%s", organizationId);

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

    try (SecurityCenterClient client = SecurityCenterClient.create()) {
      CreateNotificationConfigRequest request =
          CreateNotificationConfigRequest.newBuilder()
              .setParent(orgName)
              .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.println(String.format("Notification config was created: %s", response));
      return response;
    }
  }

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)

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: %v", err)
	}
	defer client.Close()

	req := &securitycenterpb.CreateNotificationConfigRequest{
		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: %v", err)
	}
	fmt.Fprintln(w, "New NotificationConfig created: ", notificationConfig)

	return nil
}

Node.js

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

const client = new SecurityCenterClient();

// organizationId = "your-org-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 orgName = client.organizationPath(organizationId);

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

createNotificationConfig();

PHP

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

/** Uncomment and populate these variables in your code */
// $organizationId = "{your-org-id}";
// $notificationConfigId = {"your-unique-id"};
// $projectId = "{your-project}"";
// $topicName = "{your-topic}";

$securityCenterClient = new SecurityCenterClient();
$organizationName = $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);

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

Ruby

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

org_path = 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:              org_path,
  config_id:           config_id,
  notification_config: notification_config
)
puts "Created notification config #{config_id}: #{response}."

C#


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)
    {
        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 主题。要发布通知,Security Command Center 会使用 service-org-organization-id@gcp-sa-scc-notification.iam.gserviceaccount.com 形式的组织级层服务帐号,角色为 securitycenter.notificationServiceAgent。需要组织级层的服务帐号角色才能接收通知。

获取 NotificationConfig

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

gcloud

  # The numeric ID of the organization and the name of the notification that you want to get
  NOTIFICATION="organizations/organization-id/notificationConfigs/notification-name"

  gcloud scc notifications describe $NOTIFICATION

Python

from google.cloud import securitycenter as securitycenter

client = securitycenter.SecurityCenterClient()

# TODO: organization_id = "your-org-id"
# TODO: notification_config_id = "your-config-id"

notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format(
    org_id=organization_id, config_id=notification_config_id
)

notification_config = client.get_notification_config(notification_config_name)
print("Got notification config: {}".format(notification_config))

Java

import com.google.cloud.securitycenter.v1.NotificationConfig;
import com.google.cloud.securitycenter.v1.NotificationConfigName;
import com.google.cloud.securitycenter.v1.SecurityCenterClient;
import java.io.IOException;
  public static NotificationConfig getNotificationConfig(
      String organizationId, String notificationConfigId) throws IOException {

    // String organizationId = "{your-org-id}";
    // String notificationConfigId = "{config-id}";

    try (SecurityCenterClient client = SecurityCenterClient.create()) {
      NotificationConfig response =
          client.getNotificationConfig(
              NotificationConfigName.newBuilder()
                  .setOrganization(organizationId)
                  .setNotificationConfig(notificationConfigId)
                  .build());

      System.out.println(String.format("Notification config: %s", response));
      return response;
    }
  }

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)

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: %v", err)
	}
	defer client.Close()

	req := &securitycenterpb.GetNotificationConfigRequest{
		Name: fmt.Sprintf("organizations/%s/notificationConfigs/%s", orgID, notificationConfigID),
	}

	notificationConfig, err := client.GetNotificationConfig(ctx, req)
	if err != nil {
		return fmt.Errorf("Failed to retrieve notification config: %v", err)
	}
	fmt.Fprintln(w, "Received config: ", notificationConfig)

	return nil
}

Node.js

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

const client = new SecurityCenterClient();

// organizationId = "your-org-id";
// configId = "your-config-id";
const formattedConfigName = client.notificationConfigPath(
  organizationId,
  configId
);

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

getNotificationConfg();

PHP

use Google\Cloud\SecurityCenter\V1\SecurityCenterClient;

/** Uncomment and populate these variables in your code */
// $organizationId = '{your-org-id}';
// $notificationConfigId = {'your-unique-id'};

$securityCenterClient = new SecurityCenterClient();
$notificationConfigName = $securityCenterClient::notificationConfigName(
    $organizationId,
    $notificationConfigId
);

$response = $securityCenterClient->getNotificationConfig($notificationConfigName);
printf('Notification config was retrieved: %s' . PHP_EOL, $response->getName());

Ruby

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

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#


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();
        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 权限。要授予适当的角色,请执行以下操作:

  1. 设置环境变量:

    1. 设置主题 ID:

        export TOPIC_ID=topic-id
      
    2. 为启用了通知 API 的项目设置项目 ID

        export CONSUMER_PROJECT=project-id
      
    3. 设置您在先前步骤中创建的服务帐号的电子邮件:

        export SERVICE_ACCOUNT_EMAIL=service-account-name@$CONSUMER_PROJECT.iam.gserviceaccount.com
      
  2. 向通知服务帐号授予具有 pubsub.topics.setIamPolicy 权限的角色:

       gcloud pubsub topics add-iam-policy-binding \
         projects/$CONSUMER_PROJECT/topics/$TOPIC_ID \
         --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
         --role='roles/pubsub.admin'
    

授予服务帐号角色后,使用您选择的语言更新 NotificationConfig 说明、Pub/Sub 主题和过滤条件:

gcloud

  # The topic to which the notifications are published
  PUBSUB_TOPIC="projects/project-id/topics/topic-id"

  # The description for the NotificationConfig
  DESCRIPTION="description"
  # The numeric ID of the organization and the name of the notification that you want to update
  NOTIFICATION="organizations/organization-id/notificationConfigs/notification-name"

  gcloud scc notifications update $NOTIFICATION
    --description "$DESCRIPTION" \
    --pubsub-topic $PUBSUB_TOPIC \
    --filter       $FILTER

Python

from google.cloud import securitycenter as securitycenter
from google.protobuf import field_mask_pb2

client = securitycenter.SecurityCenterClient()

# TODO organization_id = "your-org-id"
# TODO notification_config_id = "config-id-to-update"
# TODO 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.

notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format(
    org_id=organization_id, config_id=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.fitler"]
)

updated_notification_config = client.update_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

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 static NotificationConfig updateNotificationConfig(
      String organizationId, String notificationConfigId, String projectId, String topicName)
      throws IOException {
    // String organizationId = "{your-org-id}";
    // String notificationConfigId = "{your-config-id}";
    // String projectId = "{your-project}";
    // String topicName = "{your-topic}";

    String notificationConfigName =
        String.format(
            "organizations/%s/notificationConfigs/%s", organizationId, 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();

    try (SecurityCenterClient client = SecurityCenterClient.create()) {
      NotificationConfig updatedConfig = client.updateNotificationConfig(configToUpdate, fieldMask);

      System.out.println(String.format("Notification config: %s", updatedConfig));
      return updatedConfig;
    }
  }

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
	"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: %v", err)
	}
	defer client.Close()

	updatedDescription := "Updated sample config"
	updatedFilter := `state = "INACTIVE"`
	req := &securitycenterpb.UpdateNotificationConfigRequest{
		NotificationConfig: &securitycenterpb.NotificationConfig{
			Name:        fmt.Sprintf("organizations/%s/notificationConfigs/%s", orgID, 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: %v", err)
	}

	fmt.Fprintln(w, "Updated NotificationConfig: ", notificationConfig)

	return nil
}

Node.js

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

const client = new SecurityCenterClient();

// organizationId = "your-org-id";
// configId = "your-config-id";
const formattedConfigName = client.notificationConfigPath(
  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

use Google\Cloud\SecurityCenter\V1\SecurityCenterClient;
use Google\Cloud\SecurityCenter\V1\NotificationConfig;
use Google\Cloud\SecurityCenter\V1\NotificationConfig\StreamingConfig;
use Google\Protobuf\FieldMask;

/** Uncomment and populate these variables in your code */
// $organizationId = '{your-org-id}';
// $notificationConfigId = {'your-unique-id'};
// $projectId = '{your-project}';
// $topicName = '{your-topic}';

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

$response = $securityCenterClient->updateNotificationConfig($notificationConfig, [$fieldMask]);
printf('Notification config was updated: %s' . PHP_EOL, $response->getName());

Ruby

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

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#


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)
    {
        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

  # The numeric ID of the organization and the name of the notification that you want to delete
  NOTIFICATION="organizations/organization-id/notificationConfigs/notification-name"

  gcloud scc notifications delete $NOTIFICATION

Python

from google.cloud import securitycenter as securitycenter

client = securitycenter.SecurityCenterClient()

# TODO: organization_id = "your-org-id"
# TODO: notification_config_id = "your-config-id"

notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format(
    org_id=organization_id, config_id=notification_config_id
)

client.delete_notification_config(notification_config_name)
print("Deleted notification config: {}".format(notification_config_name))

Java

import com.google.cloud.securitycenter.v1.NotificationConfigName;
import com.google.cloud.securitycenter.v1.SecurityCenterClient;
import java.io.IOException;
  public static boolean deleteNotificationConfig(String organizationId, String notificationConfigId)
      throws IOException {
    // String organizationId = "{your-org-id}";
    // String notificationConfigId = "{config-id}";

    NotificationConfigName notificationConfigName =
        NotificationConfigName.newBuilder()
            .setOrganization(organizationId)
            .setNotificationConfig(notificationConfigId)
            .build();

    try (SecurityCenterClient client = SecurityCenterClient.create()) {
      client.deleteNotificationConfig(notificationConfigName);

      System.out.println(String.format("Deleted Notification config: %s", notificationConfigName));
    }

    return true;
  }

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)

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: %v", err)
	}
	defer client.Close()

	name := fmt.Sprintf("organizations/%s/notificationConfigs/%s", orgID, notificationConfigID)
	req := &securitycenterpb.DeleteNotificationConfigRequest{
		Name: name,
	}

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

	return nil
}

Node.js

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

const client = new SecurityCenterClient();

// organizationId = "your-org-id";
// configId = "your-config-id";
const formattedConfigName = client.notificationConfigPath(
  organizationId,
  configId
);

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

deleteNotificationConfg();

PHP

use Google\Cloud\SecurityCenter\V1\SecurityCenterClient;

/** Uncomment and populate these variables in your code */
// $organizationId = '{your-org-id}';
// $notificationConfigId = {'your-unique-id'};

$securityCenterClient = new SecurityCenterClient();
$notificationConfigName = $securityCenterClient::notificationConfigName(
    $organizationId,
    $notificationConfigId
);

$response = $securityCenterClient->deleteNotificationConfig($notificationConfigName);
print('Notification config was deleted' . PHP_EOL);

Ruby

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

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

列出 NotificationConfig

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

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

使用您选择的语言列出 NotificationConfigs

gcloud

  # The numeric ID of the organization
  ORGANIZATION=organization-id

  gcloud scc notifications list $ORGANIZATION

Python

from google.cloud import securitycenter as securitycenter

client = securitycenter.SecurityCenterClient()

# TODO: organization_id = "your-org-id"
org_name = "organizations/{org_id}".format(org_id=organization_id)

notification_configs_iterator = client.list_notification_configs(org_name)
for i, config in enumerate(notification_configs_iterator):
    print("{}: notification_config: {}".format(i, config))

Java

import com.google.cloud.securitycenter.v1.NotificationConfig;
import com.google.cloud.securitycenter.v1.OrganizationName;
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 static ImmutableList<NotificationConfig> listNotificationConfigs(String organizationId)
      throws IOException {
    // String organizationId = "{your-org-id}";

    OrganizationName orgName =
        OrganizationName.newBuilder().setOrganization(organizationId).build();

    try (SecurityCenterClient client = SecurityCenterClient.create()) {
      ListNotificationConfigsPagedResponse response = client.listNotificationConfigs(orgName);

      ImmutableList<NotificationConfig> notificationConfigs =
          ImmutableList.copyOf(response.iterateAll());
      System.out.println(
          String.format("List notifications response: %s", response.getPage().getValues()));
      return notificationConfigs;
    }
  }

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"google.golang.org/api/iterator"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)

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: %v", err)
	}
	defer client.Close()

	req := &securitycenterpb.ListNotificationConfigsRequest{
		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: %v", err)
		}

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

	return nil
}

Node.js

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

const client = new SecurityCenterClient();

// organizationId = "your-org-id";
const orgName = client.organizationPath(organizationId);

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

listNotificationConfigs();

PHP

use Google\Cloud\SecurityCenter\V1\SecurityCenterClient;

/** Uncomment and populate these variables in your code */
// $organizationId = '{your-org-id}';

$securityCenterClient = new SecurityCenterClient();
$organizationName = $securityCenterClient::organizationName($organizationId);

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

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

Ruby

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

org_path = client.organization_path organization: org_id

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

C#


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)
    {
        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 工具不支持将 Pub/Sub 消息转换为 NotificationMessage。您可以使用 gcloud 工具获取 NotificationMessage,并直接在终端中输出 JSON

  # The topic to which the notifications are published
  PUBSUB_TOPIC="projects/project-id/topics/topic-id"

  gcloud pubsub subscriptions pull $PUBSUB_TOPIC

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.proto.notification_message_pb2 import (
    NotificationMessage,
)
from google.protobuf import json_format

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

def callback(message):
    print("Received message")

    notification_msg = NotificationMessage()
    json_format.Parse(message.data, notification_msg)

    print(
        "Notification config name: {}".format(
            notification_msg.notification_config_name
        )
    )
    print("Finding: {}".format(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("Listening for messages on {}...\n".format(subscription_path))
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() {}

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

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

Go

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

	"cloud.google.com/go/pubsub"
	"github.com/golang/protobuf/jsonpb"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)

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: %v", 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: %v", 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();

后续步骤