알림 구성 만들기 및 관리

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

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

또는 Security Command Center에서 Pub/Sub의 지속적 내보내기를 설정할 수 있습니다.

시작하기 전에

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

다음 예시를 실행하려면 적절한 권한이 있는 Identity and Access Management(IAM) 역할이 필요합니다.

  • NotificationConfig 만들기: 보안 센터 알림 구성 편집자(roles/securitycenter.notificationConfigEditor)
  • NotificationConfig 가져오기 및 나열: 보안 센터 알림 구성 뷰어(roles/securitycenter.notificationConfigViewer) 또는 보안 센터 알림 구성 편집자(roles/securitycenter.notificationConfigEditor)
  • NotificationConfig 업데이트 및 삭제: 보안 센터 알림 편집자(roles/securitycenter.notificationConfigEditor)

notificationConfig에 액세스하는 주 구성원에게 적절한 역할을 부여하려면 다음 IAM 역할 중 하나가 있어야 합니다.

  • 조직 관리자(roles/resourcemanager.organizationAdmin)
  • 폴더 IAM 관리자(roles/resourcemanager.folderIamAdmin)
  • 프로젝트 IAM 관리자(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는 내보내기를 만드는 위치를 제한하지 않습니다.

지속적 내보내기는 생성되는 위치에만 저장되며 다른 위치에서 보거나 수정할 수 없습니다.

지속적 내보내기를 만든 후에는 해당 위치를 변경할 수 없습니다. 위치를 변경하려면 지속적 내보내기를 삭제하고 새 위치에 다시 만들어야 합니다.

데이터 레지던시가 사용 설정되었을 때 Security Command Center를 사용하는 방법은 Security Command Center 리전 엔드포인트를 참조하세요.

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"

다음을 바꿉니다.

Terraform

조직의 NotificationConfig를 만듭니다.

resource "google_pubsub_topic" "scc_v2_organization_notification_config" {
  name = "my-topic"
}

resource "google_scc_v2_organization_notification_config" "custom_organization_notification_config" {
  config_id    = "my-config"
  organization = "123456789"
  location     = "global"
  description  = "My custom Cloud Security Command Center Finding Organization Notification Configuration"
  pubsub_topic = google_pubsub_topic.scc_v2_organization_notification_config.id

  streaming_config {
    filter = "category = \"OPEN_FIREWALL\" AND state = \"ACTIVE\""
  }
}

폴더의 NotificationConfig를 만듭니다.

resource "google_folder" "folder" {
  parent       = "organizations/123456789"
  display_name = "folder-name"
}

resource "google_pubsub_topic" "scc_v2_folder_notification_config" {
  name = "my-topic"
}

resource "google_scc_v2_folder_notification_config" "custom_notification_config" {
  config_id    = "my-config"
  folder       = google_folder.folder.folder_id
  location     = "global"
  description  = "My custom Cloud Security Command Center Finding Notification Configuration"
  pubsub_topic =  google_pubsub_topic.scc_v2_folder_notification_config.id

  streaming_config {
    filter = "category = \"OPEN_FIREWALL\" AND state = \"ACTIVE\""
  }
}

프로젝트의 NotificationConfig를 만듭니다.

resource "google_pubsub_topic" "scc_v2_project_notification" {
  name = "my-topic"
}

resource "google_scc_v2_project_notification_config" "custom_notification_config" {
  config_id    = "my-config"
  project      = "my-project-name"
  description  = "My custom Cloud Security Command Center Finding Notification Configuration"
  pubsub_topic =  google_pubsub_topic.scc_v2_project_notification.id

  streaming_config {
    filter = "category = \"OPEN_FIREWALL\" AND state = \"ACTIVE\""
  }
}

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv2"
	"cloud.google.com/go/securitycenter/apiv2/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}/locations/global"
		//		"projects/{projectId}/locations/global"
		//		"folders/{folderId}/locations/global"
		Parent:   fmt.Sprintf("organizations/%s/locations/global", 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
}

Java


package vtwo.notifications;

import com.google.cloud.securitycenter.v2.LocationName;
import com.google.cloud.securitycenter.v2.NotificationConfig;
import com.google.cloud.securitycenter.v2.SecurityCenterClient;
import java.io.IOException;

public class CreateNotification {

  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 = "{parent-id}";
    String topicName = "{your-topic}";
    String notificationConfigId = "{your-notification-id}";
    // Specify the location of the notification config.
    String location = "global";

    createNotificationConfig(parentId, location, topicName, notificationConfigId);
  }

  // Crete a notification config.
  // Ensure the ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the new topic.
  public static NotificationConfig createNotificationConfig(
      String parentId, String location, String topicName, 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()) {

      String pubsubTopic = String.format("projects/%s/topics/%s", parentId, topicName);

      NotificationConfig notificationConfig = NotificationConfig.newBuilder()
          .setDescription("Java notification config")
          .setPubsubTopic(pubsubTopic)
          .setStreamingConfig(
              NotificationConfig.StreamingConfig.newBuilder().setFilter("state = \"ACTIVE\"")
                  .build())
          .build();

      NotificationConfig response = client.createNotificationConfig(
          LocationName.of(parentId, location), notificationConfig, notificationConfigId);

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

Node.js

// npm install '@google-cloud/security-center'
const {SecurityCenterClient} = require('@google-cloud/security-center').v2;
const uuidv1 = require('uuid').v1;

const client = new SecurityCenterClient();
/*
 *  Required. Resource name of the new notification config's parent. Its format
 *  is "organizations/[organization_id]/locations/[location_id]",
 *  "folders/[folder_id]/locations/[location_id]", or
 *  "projects/[project_id]/locations/[location_id]".
 */
const parent = `projects/${projectId}/locations/${location}`;

/**
 *  Required.
 *  Unique identifier provided by the client within the parent scope.
 *  It must be between 1 and 128 characters and contain alphanumeric
 *  characters, underscores, or hyphens only.
 */
const configId = 'notif-config-test-node-create-' + uuidv1();

// pubsubTopic = "projects/{your-project}/topics/{your-topic}";
const pubsubTopic = `projects/${projectId}/topics/${topicName}`;

/**
 *  Required. The notification config being created. The name and the service
 *  account will be ignored as they are both output only fields on this
 *  resource.
 */
const notificationConfig = {
  description: 'Sample config for node v2',
  pubsubTopic: pubsubTopic,
  streamingConfig: {filter: 'state = "ACTIVE"'},
};

// Build the request.
const createNotificationRequest = {
  parent: parent,
  configId: configId,
  notificationConfig: notificationConfig,
};

async function createNotificationConfig() {
  const [response] = await client.createNotificationConfig(
    createNotificationRequest
  );
  console.log('Notification configuration creation successful: %j', response);
}

await createNotificationConfig();

Python

def create_notification_config(
    parent_id, location_id, pubsub_topic, notification_config_id
) -> NotificationConfig:
    """
    This method is used to create the Notification Config.
    Args:
        parent_id: must be in one of the following formats:
            "organizations/{organization_id}"
            "projects/{project_id}"
            "folders/{folder_id}"
        location_id: "global"
        pubsub_topic: "projects/{your-project-id}/topics/{your-topic-id}"
        notification_config_id: "your-config-id"


    Ensure this ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the new topic.
    """
    from google.cloud import securitycenter_v2 as securitycenter_v2

    client = securitycenter_v2.SecurityCenterClient()
    parent_id = parent_id + "/locations/" + location_id
    response = 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(f"create notification config response:{response}")
    return response

이제 알림이 지정된 Pub/Sub 주제에 게시됩니다.

알림을 게시하려면 service-org-ORGANIZATION_ID@gcp-sa-scc-notification.iam.gserviceaccount.com 형식으로 서비스 계정이 생성됩니다. 이 서비스 계정은 첫 번째 NotificationConfig 을 만들 때 생성되며 알림 구성을 만들 때 PUBSUB_TOPIC에 대한 IAM 정책에 securitycenter.notificationServiceAgent 역할 이 자동으로 부여됩니다. 알림이 작동하려면 서비스 계정 역할이 필요합니다.

NotificationConfig 가져오기

NotificationConfig를 가져오려면 securitycenter.notification.get 권한이 포함된 IAM 역할이 있어야 합니다.

gcloud

gcloud scc notifications describe NOTIFICATION_NAME \
  --PARENT_TYPE=PARENT_ID \
  --location=LOCATION

다음을 바꿉니다.

NotificationConfig 업데이트

NotificationConfig를 업데이트하려면 securitycenter.notification.update 권한이 포함된 IAM 역할이 있어야 합니다.

필드 마스크를 사용하여 업데이트할 때 지정한 필드만 업데이트됩니다. 필드 마스크를 사용하지 않으면 NotificationConfig의 모든 변경 가능한 필드가 새 값으로 바뀝니다. 필드 마스크를 사용하여 Pub/Sub 주제 및 설명을 업데이트할 수 있습니다.

이 예시를 완료하려면 새 주제를 구독해야 하고 알림 서비스 계정에 해당 주제에 대한 pubsub.topics.setIamPolicy 권한이 있어야 합니다.

필요한 권한을 부여한 후 원하는 언어를 사용하여 NotificationConfig 설명, Pub/Sub 주제, 필터를 업데이트합니다.

gcloud

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

다음을 바꿉니다.

  • NOTIFICATION_NAME: 알림 구성의 이름입니다.
  • PARENT_TYPE: 구성이 지정된 리소스 계층 구조의 수준입니다. organization, folder 또는 project를 사용합니다.
  • PARENT_ID: 상위 리소스의 숫자 ID입니다.
  • LOCATION: Security Command Center를 업데이트하려는 위치입니다. 데이터 레지던시가 사용 설정된 경우 eu, sa, 또는 us를 사용하고, 그렇지 않으면 global 값을 사용합니다.NotificationConfig
  • NOTIFICATION_DESCRIPTION: 알림에 대한 설명입니다(1,024자 이내).
  • PUBSUB_TOPIC: 알림을 수신할 Pub/Sub 주제입니다. 형식은 projects/PROJECT_ID/topics/TOPIC입니다.
  • FILTER: Pub/Sub에 전송되는 발견 사항을 선택하기 위해 정의하는 표현식입니다. 예를 들면 state="ACTIVE"입니다.

NotificationConfig 삭제

NotificationConfig을 삭제하려면 securitycenter.notification.delete 권한이 포함된 IAM 역할이 있어야 합니다.

NotificationConfig를 삭제해도 securitycenter.notificationServiceAgent 역할은 Pub/Sub 주제에 유지됩니다. 다른 NotificationConfig에서 Pub/Sub 주제를 사용하지 않는 경우 주제에서 역할을 삭제합니다. 자세한 내용은 액세스 제어를 참조하세요.

선택한 언어를 사용하여 NotificationConfig를 삭제합니다.

gcloud

gcloud scc notifications delete NOTIFICATION_NAME \
  --PARENT_TYPE=PARENT_ID \
  --location=LOCATION

다음을 바꿉니다.

NotificationConfig 나열

NotificationConfigs를 나열하려면 securitycenter.notification.list 권한이 포함된 IAM 역할이 있어야 합니다.

모든 Security Command Center API 목록은 페이지로 나눠집니다. 각 응답은 결과 페이지와 다음 페이지를 반환하는 토큰을 반환합니다. pageSize의 기본값은 10입니다. 페이지 크기는 최소 1에서 최대 1,000으로 구성할 수 있습니다.

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

gcloud

gcloud scc notifications list PARENT_TYPE/PARENT_ID \
  --location=LOCATION

다음을 바꿉니다.

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

Go

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

	"cloud.google.com/go/pubsub"
	"cloud.google.com/go/securitycenter/apiv2/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
}

다음 단계