Como criar e gerenciar configurações de notificação

Nesta página, você verá como usar o recurso de notificações da API Security Command Center, incluindo os exemplos a seguir:

  • Criar um NotificationConfig
  • Receber um NotificationConfig
  • Atualizar um NotificationConfig
  • Excluir um NotificationConfig
  • Listar NotificationConfig
  • Receber notificações do Pub/Sub

Como alternativa, os clientes do Security Command Center Premium podem configurar exportações contínuas para o Pub/Sub no Security Command Center.

Antes de começar

Para usar os exemplos nesta página, você precisa concluir o guia para configurar notificações de localização.

Para executar os exemplos a seguir, você precisa de um papel de Gerenciamento de identidade e acesso (IAM, na sigla em inglês) com as permissões apropriadas:

  • Criar NotificationConfig: editor de configurações de notificação da Central de segurança (roles/securitycenter.notificationConfigEditor)
  • Receber e listar NotificationConfig: visualizador de configurações de notificação da Central de segurança (roles/securitycenter.notificationConfigViewer) ou editor de configurações de notificação da Central de segurança (roles/securitycenter.notificationConfigEditor)
  • Atualizar e excluir NotificationConfig: Editor de notificações da Central de segurança (roles/securitycenter.notificationConfigEditor)

Para conceder os papéis apropriados a um principal que acesse um notificationConfig, é preciso ter um dos seguintes papéis do IAM:

  • Administrador da organização (roles/resourcemanager.organizationAdmin)
  • Administrador de pastas do IAM (roles/resourcemanager.folderIamAdmin)
  • Administrador de IAM do projeto (roles/resourcemanager.projectIamAdmin)

Os papéis do IAM para o Security Command Center podem ser concedidos no nível da organização, da pasta ou do projeto. A capacidade de ver, editar, criar ou atualizar descobertas, recursos e fontes de segurança depende do nível a que você tem acesso. Para saber mais sobre os papéis do Security Command Center, consulte Controle de acesso.

Residência de dados e notificações

Se a residência de dados estiver ativada para o Security Command Center, as configurações que definem exportações contínuas para o Pub/Sub, ou seja, recursos notificationConfig, estão sujeitas ao controle de residência de dados e são armazenadas no local do Security Command Center.

Para exportar descobertas em um local do Security Command Center para o Pub/Sub, configure a exportação contínua no mesmo local do Security Command Center.

Como os filtros usados nas exportações contínuas podem conter dados sujeitos a controles de residência, especifique o local correto antes de criá-los. O Security Command Center não restringe o local em que você cria as exportações.

As exportações contínuas são armazenadas apenas no local em que são criadas e não podem ser visualizadas ou editadas em outros locais.

Depois de criar uma exportação contínua, não é possível mudar o local dela. Para mudar o local, exclua a exportação contínua e a recrie no novo local.

Para recuperar uma exportação contínua usando chamadas de API, especifique o local no nome completo do recurso do notificationConfig. Exemplo:

GET https://securitycenter.googleapis.com/v2/organizations/123/locations/eu/notificationConfigs/my-pubsub-export-01

Da mesma forma, para recuperar uma exportação contínua usando a CLI gcloud, especifique o local usando a flag --location. Exemplo:

gcloud scc notifications describe myContinuousExport --organization=123 \
    --location=us

Como criar um NotificationConfig

Para criar um NotificationConfig, você precisa ter:

  • um tópico do Pub/Sub para onde você quer enviar notificações;
  • Papéis do IAM necessários para o principal que cria o notificationConfig.

Para mais informações, consulte a etapa para configurar um tópico do Pub/Sub no guia para configurar notificações de localização.

Antes de criar um NotificationConfig, observe que cada organização pode ter um número limitado de arquivos NotificationConfig. Para mais informações, consulte Cotas e limites.

O NotificationConfig inclui um campo filter, que limita as notificações a eventos úteis. Esse campo aceita todos os filtros disponíveis no método findings.list da API Security Command Center.

Ao criar um NotificationConfig, você especifica um pai para o NotificationConfig da hierarquia de recursos do Google Cloud, seja uma organização, uma pasta ou um projeto. Se for necessário recuperar, atualizar ou excluir o NotificationConfig mais tarde, será necessário incluir o ID numérico da organização, pasta ou projeto pai ao fazer referência a ele.

No console do Google Cloud, alguns recursos NotificationConfig podem ter um rótulo Legacy, o que indica que eles foram criados com a API v1 do Security Command Center. É possível gerenciar esses recursos NotificationConfig com o console do Google Cloud, a CLI gcloud, a API Security Command Center v1 ou as bibliotecas de cliente v1 do Security Command Center.

Para gerenciar esses recursos NotificationConfig com a CLI gcloud, não especifique um local ao executar o comando da CLI gcloud.

Para criar o NotificationConfig usando o idioma ou a plataforma de sua escolha:

gcloud

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

Substitua:

  • NOTIFICATION_NAME: o nome da notificação. Precisa ter entre 1 e 128 caracteres e conter apenas caracteres alfanuméricos, sublinhados ou hifens.
  • PARENT: o escopo na hierarquia de recursos a que a notificação se aplica, organization, folder ou project.
  • PARENT_ID: o ID da organização, pasta ou projeto pai, especificado no formato organizations/123, folders/456 ou projects/789.
  • LOCATION: se a residência de dados estiver ativada, o local do Security Command Center em que uma NotificationConfig será criada. Se a residência de dados não estiver ativada, use o valor global.
  • NOTIFICATION_DESCRIPTION: uma descrição da notificação de no máximo 1.024 caracteres.
  • PUBSUB_TOPIC: o tópico do Pub/Sub que vai receber notificações. O formato é projects/PROJECT_ID/topics/TOPIC.
  • FILTER: a expressão que você define para selecionar quais resultados são enviados ao Pub/Sub. Por exemplo, 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

Agora, as notificações são publicadas no tópico Pub/Sub que você especificou.

Para publicar notificações, uma conta de serviço é criada para você na forma de service-org-ORGANIZATION_ID@gcp-sa-scc-notification.iam.gserviceaccount.com. Essa conta de serviço é criada quando você cria seu primeiro NotificationConfig e recebe automaticamente o papel securitycenter.notificationServiceAgent na política do IAM para PUBSUB_TOPIC ao criar a configuração de notificação. Esse papel de conta de serviço é necessário para que as notificações funcionem.

Como receber uma NotificationConfig

Para acessar um NotificationConfig, você precisa ter um papel do IAM que inclua a permissão securitycenter.notification.get.

gcloud

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

Substitua:

  • NOTIFICATION_NAME: o nome da configuração de notificação.
  • PARENT_TYPE: o nível da hierarquia de recursos em que a configuração é especificada. Use organization, folder ou project.
  • PARENT_ID: o ID numérico do recurso pai.
  • LOCATION: se a residência de dados estiver ativada, o local do Security Command Center em que o NotificationConfig será recebido. Se a residência de dados não estiver ativada, use o valor global.

Como atualizar um NotificationConfig

Para atualizar um NotificationConfig, você precisa ter um papel de IAM que inclua a permissão securitycenter.notification.update.

Quando você faz a atualização usando uma máscara de campo, somente os campos especificados são atualizados. Se você não usar uma máscara de campo, todos os campos mutáveis no NotificationConfig serão substituídos pelos novos valores. Você pode usar uma máscara de campo para atualizar o tópico e a descrição do Pub/Sub.

Para concluir este exemplo, você precisa estar inscrito no novo tópico e sua conta de serviço de notificações precisa ter a permissão pubsub.topics.setIamPolicy no tópico.

Depois de conceder as permissões necessárias, atualize a descrição de NotificationConfig, o tópico do Pub/Sub e filtre usando a linguagem de sua escolha:

gcloud

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

Substitua:

  • NOTIFICATION_NAME: o nome da configuração de notificação.
  • PARENT_TYPE: o nível da hierarquia de recursos em que a configuração é especificada. Use organization, folder ou project.
  • PARENT_ID: o ID numérico do recurso pai.
  • LOCATION: se a residência de dados estiver ativada, o local do Security Command Center em que a NotificationConfig será atualizada. Se a residência de dados não estiver ativada, use o valor global.
  • NOTIFICATION_DESCRIPTION: uma descrição da notificação de no máximo 1.024 caracteres.
  • PUBSUB_TOPIC: o tópico do Pub/Sub que vai receber notificações. O formato é projects/PROJECT_ID/topics/TOPIC.
  • FILTER: a expressão que você define para selecionar quais descobertas são enviadas ao Pub/Sub. Por exemplo, state="ACTIVE".

Como excluir uma NotificationConfig

Para excluir um NotificationConfig, você precisa ter um papel do IAM que inclua a permissão securitycenter.notification.delete.

Quando você exclui um NotificationConfig, o papel securitycenter.notificationServiceAgent permanece no tópico do Pub/Sub. Se você não estiver usando o tópico Pub/Sub em qualquer outro NotificationConfig, remova o papel do tópico. Para mais informações, consulte controle de acesso.

Exclua um NotificationConfig usando o idioma de sua escolha:

gcloud

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

Substitua:

  • NOTIFICATION_NAME: o nome da configuração de notificação.
  • PARENT_TYPE: o nível da hierarquia de recursos em que a configuração é especificada. Use organization, folder ou project.
  • PARENT_ID: o ID numérico do recurso pai.
  • LOCATION: se a residência de dados estiver ativada, o local do Security Command Center em que o NotificationConfig será excluído. Se a residência de dados não estiver ativada, use o valor global.

Como listar NotificationConfigs

Para listar NotificationConfigs, você precisa ter um papel do IAM que inclua a permissão securitycenter.notification.list.

Todas as listas da API Security Command Center são paginadas. Cada resposta retorna uma página de resultados e um token para retornar a próxima página. O padrão pageSize é 10. Você pode configurar o tamanho da página para um mínimo de 1 e um máximo de 1.000.

Liste NotificationConfigs usando o idioma de sua escolha:

gcloud

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

Substitua:

  • PARENT_TYPE: o nível da hierarquia de recursos em que a configuração é especificada. Use organizations, folders ou projects.
  • PARENT_ID: o ID numérico do recurso pai.
  • LOCATION: se a residência de dados estiver ativada, o local do Security Command Center em que os recursos NotificationConfig serão listados. Se a residência de dados não estiver ativada, use o valor global.

Como receber notificações do Pub/Sub

Nesta seção, apresentamos um exemplo de mensagem de notificação e exemplos que mostram como converter uma mensagem do Pub/Sub em um NotificationMessage que contém uma descoberta.

As notificações são publicadas no Pub/Sub no formato JSON. Veja abaixo um exemplo de mensagem de notificação:

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

Converta uma mensagem do Pub/Sub em um NotificationMessage usando a linguagem de sua escolha:

gcloud

A CCLI gcloud não é compatível com a conversão de uma mensagem do Pub/Sub em NotificationMessage. É possível usar a CLI gcloud para receber um NotificationMessage e imprimir o JSON diretamente no terminal:

  # The subscription used to receive published messages from a topic
  PUBSUB_SUBSCRIPTION="projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID"

  gcloud pubsub subscriptions pull $PUBSUB_SUBSCRIPTION

Substitua:

  • PROJECT_ID pelo código do projeto;
  • SUBSCRIPTION_ID pelo ID da sua assinatura.

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
}

A seguir