啟用 Pub/Sub 發現項目通知

本頁說明如何啟用 Security Command Center API 通知。

通知會在幾分鐘內將發現項目和發現項目更新傳送至 Pub/Sub 主題。Security Command Center API 通知包含 Security Command Center 在Google Cloud 控制台中顯示的所有發現項目資訊。

您可以將 Pub/Sub 中的 Security Command Center 通知,直接連結至 Cloud Run 函式動作。如需有助於回應、擴充和補救的函式範例,請參閱 Cloud Run 函式程式碼的 Security Command Center 開放原始碼存放區。這個存放區包含的解決方案可協助您對安全性發現事項採取自動化動作。

或者,您也可以將發現項目匯出至 BigQuery,或在 Google Cloud 控制台中設定 Pub/Sub 的持續匯出作業

事前準備

  1. 如要取得設定及配置 Security Command Center API 通知所需的權限,請管理員授予您下列 IAM 角色:

    如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。

    您或許還可透過自訂角色或其他預先定義的角色取得必要權限。

  2. Enable the Security Command Center API:

    gcloud services enable securitycenter.googleapis.com

資料落地和通知

如果 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 區域端點」。

設定 Pub/Sub 主題

在這項工作中,您會建立並訂閱要傳送通知的 Pub/Sub 主題。

步驟 1:設定 Pub/Sub

如要設定及訂閱 Pub/Sub 主題,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台。

    前往 Google Cloud 控制台

  2. 選取您啟用 Security Command Center API 的專案。

  3. 按一下「啟用 Cloud Shell」

  4. 選用:如要建立新的 Pub/Sub 主題,請執行下列指令:

    gcloud pubsub topics create TOPIC_ID
    

    TOPIC_ID 替換為主題名稱。

  5. 為主題建立訂閱:

    gcloud pubsub subscriptions create SUBSCRIPTION_ID --topic=TOPIC_ID
    

    更改下列內容:

    • SUBSCRIPTION_ID:訂閱 ID
    • TOPIC_ID:主題 ID

如要進一步瞭解如何設定 Pub/Sub,請參閱「管理主題和訂閱項目」。

步驟 2:授予 Pub/Sub 主題的角色

如要建立 NotificationConfig,您必須在已建立訂閱項目的 Pub/Sub 主題上,擁有 Pub/Sub 管理員角色 (roles/pubsub.admin)。

如要授予這個角色,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台。

    前往 Google Cloud 控制台

  2. 選取您已啟用 Security Command Center API 的專案。

  3. 按一下「啟用 Cloud Shell」

  4. 在 Pub/Sub 主題上,將必要角色授予您的 Google 帳戶:

    gcloud pubsub topics add-iam-policy-binding \
        projects/PUBSUB_PROJECT/topics/TOPIC_ID \
        --member="user:GOOGLE_ACCOUNT" \
        --role="roles/pubsub.admin"
    

    更改下列內容:

    • PUBSUB_PROJECT:包含 Pub/Sub 主題的 Google Cloud 專案
    • TOPIC_ID:主題 ID
    • GOOGLE_ACCOUNT:您的 Google 帳戶電子郵件地址

建立 NotificationConfig

建立 NotificationConfig 前,請注意每個機構可擁有的 NotificationConfig 檔案數量有限。詳情請參閱配額與限制

NotificationConfig 包含 filter 欄位,可將通知限制為實用事件。這個欄位接受 Security Command Center API findings.list 方法中提供的所有篩選器。

建立 NotificationConfig 時,您會從 Google Cloud 資源階層指定 NotificationConfig 的父項,可以是機構、資料夾或專案。如要日後擷取、更新或刪除 NotificationConfig,請在參照時一併提供父項機構、資料夾或專案的數值 ID。

在 Google Cloud 控制台中,部分NotificationConfig資源可能會顯示「舊版」標籤,表示這些資源是使用 v1 Security Command Center API 建立。您可以使用 Google Cloud 控制台、gcloud CLI、v1 版 Security Command Center API,或 Security Command Center 的 v1 版用戶端程式庫,管理這些 NotificationConfig 資源。

如要使用 gcloud CLI 管理這些 NotificationConfig 資源,執行 gcloud CLI 指令時不得指定位置。

如要使用所選語言或平台建立 NotificationConfig,請按照下列步驟操作:

gcloud

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

更改下列內容:

  • NOTIFICATION_NAME:通知名稱。 長度必須介於 1 至 128 個字元之間,而且只能使用英數字元、底線或連字號。
  • PARENT:通知適用的資源階層範圍,即 organizationfolderproject
  • PARENT_ID:父項機構、資料夾或專案的 ID,格式為 organizations/123folders/456projects/789
  • LOCATION: 要儲存資料的Security Command Center 位置。如果已啟用資料落地功能,請使用 euksaus;否則請使用 global 值。
  • NOTIFICATION_DESCRIPTION:通知說明,最多 1,024 個字元。
  • PUBSUB_TOPIC:將接收通知的 Pub/Sub 主題。格式為 projects/PROJECT_ID/topics/TOPIC
  • FILTER:您定義的運算式,用於選取要傳送至 Pub/Sub 的調查結果。例如:state=\"ACTIVE\"

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"
  location     = "global"
  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 角色。通知功能需要這個服務帳戶角色才能運作。

在 VPC Service Controls 中授予範圍存取權

如果您使用 VPC Service Controls,且 Pub/Sub 主題屬於服務範圍內的專案,您必須授予專案存取權,才能建立通知。

如要授予專案存取權,請為用於建立通知的主體和專案建立輸入和輸出規則。這些規則可讓您存取受保護的資源,並讓 Pub/Sub 驗證使用者是否具備 Pub/Sub 主題的 setIamPolicy 權限。

建立 NotificationConfig 前

完成「建立 NotificationConfig」一文中的步驟前,請先完成下列步驟。

控制台

  1. 在 Google Cloud 控制台中,前往「VPC Service Controls」頁面。

    前往 VPC Service Controls

  2. 選取您的機構或專案。
  3. 如果您選取機構,請按一下「選取存取權政策」,然後選取要更新的周邊相關存取權政策。
  4. 按一下要更新的周邊裝置名稱。

    如要找出需要修改的服務安全防護範圍,請檢查記錄檔中顯示 RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER 違規事項的項目。在這些項目中,檢查 servicePerimeterName 欄位:

    accessPolicies/ACCESS_POLICY_ID/servicePerimeters/SERVICE_PERIMETER_NAME
  5. 按一下「編輯範圍」
  6. 按一下「輸出政策」
  7. 按一下「新增 egress 規則」
  8. 在「FROM」部分,設定下列詳細資料:

    1. 在「身分」部分,選取「特定身分和群組」
    2. 按一下「新增身分」
    3. 輸入用於呼叫 Security Command Center API 的主體電子郵件地址。

    4. 選取主體或按下 ENTER 鍵,然後按一下「新增身分」
  9. 在「TO」(收件者) 部分,設定下列詳細資料:

    1. 在「Project」(專案) 部分,選取「All projects」(所有專案)
    2. 在「作業或 IAM 角色」部分,選取「選取作業」
    3. 按一下「新增作業」,然後新增下列作業:

      • 新增 pubsub.googleapis.com 服務。
        1. 按一下「所有方法」
        2. 按一下「新增所有方法」
  10. 按一下「輸入政策」
  11. 按一下「新增 Ingress 規則」
  12. 在「FROM」部分,設定下列詳細資料:

    1. 在「身分」部分,選取「特定身分和群組」
    2. 按一下「新增身分」
    3. 輸入用於呼叫 Security Command Center API 的主體電子郵件地址。

    4. 選取主體或按下 ENTER 鍵,然後按一下「新增身分」
    5. 在「來源」部分,選取「所有來源」
  13. 在「TO」(收件者) 部分,設定下列詳細資料:

    1. 在「Project」(專案) 部分,選取「Select projects」(選取專案)
    2. 按一下「新增專案」,然後新增包含 Pub/Sub 主題的專案。
    3. 在「作業或 IAM 角色」部分,選取「選取作業」
    4. 按一下「新增作業」,然後新增下列作業:

      • 新增 pubsub.googleapis.com 服務。
        1. 按一下「所有方法」
        2. 按一下「新增所有方法」
  14. 按一下 [儲存]

gcloud

  1. 如果尚未設定配額專案,請設定配額專案。選擇已啟用 Access Context Manager API 的專案。

    gcloud config set billing/quota_project QUOTA_PROJECT_ID

    QUOTA_PROJECT_ID 替換為您要用於帳單和配額的專案 ID。

  2. 建立名為 egress-rule.yaml 的檔案,並在當中加入下列內容:

    - egressFrom:
        identities:
        - PRINCIPAL_ADDRESS
      egressTo:
        operations:
        - serviceName: pubsub.googleapis.com
          methodSelectors:
          - method: '*'
        resources:
        - '*'

    PRINCIPAL_ADDRESS 替換為用於呼叫 Security Command Center API 的主體地址。

  3. 建立名為 ingress-rule.yaml 的檔案,並在當中加入下列內容:

    - ingressFrom:
        identities:
        - PRINCIPAL_ADDRESS
        sources:
        - accessLevel: '*'
      ingressTo:
        operations:
        - serviceName: pubsub.googleapis.com
          methodSelectors:
          - method: '*'
        resources:
        - '*'

    PRINCIPAL_ADDRESS 替換為用於呼叫 Security Command Center API 的主體地址。

  4. 將 Egress 規則新增至範圍:

    gcloud access-context-manager perimeters update PERIMETER_NAME \
        --set-egress-policies=egress-rule.yaml

    更改下列內容:

    • PERIMETER_NAME:perimeter 的名稱。例如: accessPolicies/1234567890/servicePerimeters/example_perimeter

      如要找出需要修改的服務安全防護範圍,請檢查記錄檔中顯示 RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER 違規事項的項目。在這些項目中,檢查 servicePerimeterName 欄位:

      accessPolicies/ACCESS_POLICY_ID/servicePerimeters/SERVICE_PERIMETER_NAME
  5. 將 Ingress 規則新增至範圍:

    gcloud access-context-manager perimeters update PERIMETER_NAME \
        --set-ingress-policies=ingress-rule.yaml

    更改下列內容:

    • PERIMETER_NAME:perimeter 的名稱。例如: accessPolicies/1234567890/servicePerimeters/example_perimeter

      如要找出需要修改的服務安全防護範圍,請檢查記錄檔中顯示 RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER 違規事項的項目。在這些項目中,檢查 servicePerimeterName 欄位:

      accessPolicies/ACCESS_POLICY_ID/servicePerimeters/SERVICE_PERIMETER_NAME

詳情請參閱「輸入和輸出規則」。

為 NotificationConfig 建立 Ingress 規則

如要為 NotificationConfig 建立 Ingress 規則,請按照「建立 NotificationConfig」中的操作說明完成步驟,然後完成下列步驟。

控制台

  1. 重新開啟上一節中的服務周邊。

    前往 VPC Service Controls

  2. 按一下「輸入政策」
  3. 按一下「新增 Ingress 規則」
  4. 在「FROM」部分,設定下列詳細資料:

    1. 在「身分」部分,選取「特定身分和群組」
    2. 按一下「新增身分」
    3. 輸入服務專員的電子郵件地址。 NotificationConfig 服務代理人的地址格式如下:

      service-org-ORGANIZATION_ID@gcp-sa-scc-notification.iam.gserviceaccount.com

      ORGANIZATION_ID 替換為機構 ID。

    4. 選取服務代理人或按 ENTER 鍵,然後按一下「新增身分」
    5. 在「來源」部分,選取「所有來源」
  5. 在「TO」(收件者) 部分,設定下列詳細資料:

    1. 在「Project」(專案) 部分,選取「Select projects」(選取專案)
    2. 按一下「新增專案」,然後新增包含 Pub/Sub 主題的專案。
    3. 在「作業或 IAM 角色」部分,選取「選取作業」
    4. 按一下「新增作業」,然後新增下列作業:

      • 新增 pubsub.googleapis.com 服務。
        1. 按一下「所有方法」
        2. 按一下「新增所有方法」
  6. 按一下 [儲存]

gcloud

  1. 如果尚未設定配額專案,請設定配額專案。選擇已啟用 Access Context Manager API 的專案。

    gcloud config set billing/quota_project QUOTA_PROJECT_ID

    QUOTA_PROJECT_ID 替換為您要用於帳單和配額的專案 ID。

  2. 建立名為 ingress-rule.yaml 的檔案,並在當中加入下列內容:

    - ingressFrom:
        identities:
        - serviceAccount:service-org-ORGANIZATION_ID@gcp-sa-scc-notification.iam.gserviceaccount.com
        sources:
        - accessLevel: '*'
      ingressTo:
        operations:
        - serviceName: pubsub.googleapis.com
          methodSelectors:
          - method: '*'
        resources:
        - '*'

    ORGANIZATION_ID 替換為機構 ID。

  3. 將 Ingress 規則新增至範圍:

    gcloud access-context-manager perimeters update PERIMETER_NAME \
        --set-ingress-policies=ingress-rule.yaml

    更改下列內容:

    • PERIMETER_NAME:perimeter 的名稱。例如: accessPolicies/1234567890/servicePerimeters/example_perimeter

      如要找出需要修改的服務安全防護範圍,請檢查記錄檔中顯示 RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER 違規事項的項目。在這些項目中,檢查 servicePerimeterName 欄位:

      accessPolicies/ACCESS_POLICY_ID/servicePerimeters/SERVICE_PERIMETER_NAME

詳情請參閱「輸入和輸出規則」。

所選專案、使用者和服務帳戶現在可以存取受保護的資源,並建立通知。

如果按照本指南操作後,通知功能已正常運作,現在可以刪除下列項目:

  • 主體的輸入規則
  • 主體的輸出規則

這些規則僅用於設定 NotificationConfig。不過,如要讓通知功能繼續運作,您必須保留 NotificationConfig 的連入規則,讓通知發布至服務邊界後方的 Pub/Sub 主題。

後續步驟