알림 구성 만들기 및 관리

>

이 페이지에서는 다음 예시를 포함하여 Security Command Center API 알림 기능을 사용하는 방법을 설명합니다.

  • NotificationConfig 만들기
  • NotificationConfig 받기
  • NotificationConfig 업데이트
  • NotificationConfig 삭제
  • NotificationConfig 나열
  • Pub/Sub 알림 수신

시작하기 전에

이 페이지의 예시를 사용하려면 발견 항목 알림 설정 가이드를 완료해야 합니다.

다음 예시를 실행하려면 적절한 권한이 있는 ID 및 액세스 관리(IAM) 역할이 필요합니다.

  • NotificationConfig 가져오기 및 나열: 보안 센터 알림 뷰어 또는 편집자
  • NotificationConfig 업데이트 및 삭제: 보안 센터 알림 편집자

Security Command Center 역할에 대해 자세히 알아보세요.

NotificationConfig 만들기

NotificationConfig를 만들려면 다음이 필요합니다.

  • 알림을 전송하려는 기존 Pub/Sub 주제
  • 서비스 계정 또는 gcloud 도구 명령어를 실행하는 데 사용하는 계정의 필수 IAM 역할

자세한 내용은 발견 항목 알림 설정 가이드의 Pub/Sub 주제 설정 단계를 참조하세요.

NotificationConfig를 만들기 전에 다음 사항에 유의하세요.

  • 각 조직에는 제한된 수의 NotificationConfig 파일이 포함될 수 있습니다. 자세한 내용은 할당량 및 제한을 참조하세요.
  • 알림 서비스 계정 또는 gcloud 도구 계정에 적절한 역할을 부여할 수 있도록 조직 관리자 IAM 역할이 있어야 합니다.

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

자바

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에서는 securitycenter.notificationServiceAgent 역할의 service-org-organization-id@gcp-sa-scc-notification.iam.gserviceaccount.com 형태로 조직 수준 서비스 계정을 사용합니다. 알림이 작동하려면 이 조직 수준 서비스 계정 역할이 필요합니다.

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

자바

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

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

updated_notification_config = client.update_notification_config(
    {
        "name": notification_config_name,
        "description": updated_description,
        "pubsub_topic": pubsub_topic,
    },
    update_mask=field_mask,
)

print(updated_notification_config)

자바

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"
	req := &securitycenterpb.UpdateNotificationConfigRequest{
		NotificationConfig: &securitycenterpb.NotificationConfig{
			Name:        fmt.Sprintf("organizations/%s/notificationConfigs/%s", orgID, notificationConfigID),
			Description: updatedDescription,
			PubsubTopic: updatedPubsubTopic,
		},
		UpdateMask: &field_mask.FieldMask{
			Paths: []string{"description", "pubsub_topic"},
		},
	}

	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"

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?

paths = []
paths.push "description" unless description.nil?
paths.push "pubsub_topic" unless pubsub_topic.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 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
        };

        FieldMask fieldMask = new FieldMask { Paths = { "description", "pubsub_topic" } };
        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 주제에 유지됩니다. Pub/Sub 주제를 다른 NotificationConfig에서 사용하지 않는 경우 주제에서 역할을 삭제합니다. 자세한 내용은 액세스 제어를 참조하세요.

선택한 언어를 사용하여 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 alpha 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))

자바

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에서 최대 1,000으로 구성할 수 있습니다.

원하는 언어를 사용하여 NotificationConfigs을 나열합니다.

gcloud

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

  gcloud alpha 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))

자바

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로 변환하는 방법을 보여주는 샘플 알림 메시지 및 예시를 제공합니다.

알림은 Pub/Sub에 JSON 형식으로 게시됩니다. 다음은 알림 메시지의 예시입니다.

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

자바


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

다음 단계