Configurar notificações em um secret

Este tópico aborda a compatibilidade com notificações de eventos no Secret Manager.

Visão geral

As notificações de eventos enviam informações sobre as mudanças nos secrets e nas versões deles para o Pub/Sub. Essas notificações podem ser usadas para acionar fluxos de trabalho arbitrários, como reiniciar um aplicativo quando uma nova versão do secret é adicionada ou notificar os engenheiros de segurança quando um secret é excluído. Para mais informações sobre como usar essas notificações para acionar fluxos de trabalho, consulte a documentação do Pub/Sub.

Como as notificações de eventos funcionam no Gerenciador de secrets

Os secrets podem ser configurados com uma lista de até 10 tópicos do Pub/Sub. Sempre que for realizada uma operação que modifique o secret ou uma das versões dele, o Secret Manager publicará automaticamente uma mensagem em cada um dos tópicos do Pub/Sub nesse secret. As chamadas Get, List e Access não resultam em publicações de mensagens.

As mensagens do Pub/Sub têm um conjunto de pares de chave-valor de "atributo" que contém metadados sobre o evento, além de um campo "data" com uma serialização JSON completa do secret ou as versão do secret recurso que foi criado ou modificado. Este JSON é uma string codificada em UTF-8 que representa o recurso Secret ou SecretVersion exatamente no formato especificado pela API pública do Secret Manager, codificado em JSON, conforme especificado no Mapeamento JSON de proto3.

Tipos de evento

Confira a seguir uma lista dos tipos de evento compatíveis com o Secret Manager:

Tipo de evento Descrição
SECRET_CREATE É enviado quando um novo secret é criado.
SECRET_UPDATE É enviado quando uma nova chave secreta é atualizada.
SECRET_DELETE É enviado quando uma chave secreta é excluída, seja por uma solicitação iniciada pelo usuário ou pela expiração da chave secreta.
SECRET_VERSION_ADD É enviado quando uma nova versão do secret é adicionada.
SECRET_VERSION_ENABLE É enviado quando uma versão do secret é ativada.
SECRET_VERSION_DISABLE É enviado quando uma versão do secret é desativada.
SECRET_VERSION_DESTROY É enviado quando uma versão do secret é destruída.
SECRET_VERSION_DESTROY_SCHEDULED É enviado quando um período de duração do atraso de destruição é configurado no secret e o usuário tenta destruir uma versão do secret.
SECRET_ROTATE É enviado quando é hora de fazer a rotação de um secret. Consulte Como criar e gerenciar políticas de rotação em secrets para mais informações.
TOPIC_CONFIGURED

Esta é uma mensagem de teste sem corpo ou atributos diferentes de eventType: TOPIC_CONFIGURED. É enviado quando um secret é criado ou atualizado com uma lista de tópicos do Pub/Sub, mas não indica que a operação foi bem-sucedida.

Uma mensagem SECRET_CREATE ou SECRET_UPDATE será enviada imediatamente após a operação se a operação for bem-sucedida.

Sempre que os tópicos são atualizados em um secret, uma mensagem TOPIC_CONFIGURED é enviada para todos os tópicos no secret, incluindo aqueles que já estavam presentes.

Formato da notificação

As notificações enviadas ao tópico do Pub/Sub são compostas de duas partes:

  • Atributos: um conjunto de pares de chave-valor que descreve o evento.
  • Payload: uma string de caracteres que contém os metadados do objeto alterado.

Atributos

Atributos são pares chave-valor contidos em notificações enviadas pelo Gerenciador de secrets para seu tópico do Pub/Sub. Todas as notificações, exceto as mensagens de teste TOPIC_CONFIGURED, sempre contêm o seguinte conjunto de pares de chave-valor, independentemente dos dados da notificação:

Nome do atributo Exemplo Descrição
eventType SECRET_CREATE Tipo de evento que acabou de ocorrer. Para uma lista de valores possíveis, consulte Tipos de evento.
dataFormat JSON_API_V1 O formato dos dados do objeto.
secretId projects/p/secrets/my-secret O nome completo do recurso do secret em que o evento ocorreu.
timestamp 2021-01-20T11:17:45.081104-08:00 Hora em que o evento ocorreu

Além disso, as notificações às vezes contêm o seguinte conjunto de pares de chave-valor:

Nome do atributo Exemplo Descrição
versionId projects/p/secrets/my-secret/versions/456

É o nome da versão do secret em que o evento ocorreu.

Isso está presente apenas nas notificações de eventos SECRET_VERSION_ADD, SECRET_VERSION_ENABLE, SECRET_VERSION_DISABLE e SECRET_VERSION_DESTROY.

deleteType REQUESTED Se a exclusão foi solicitada por um usuário (REQUESTED) ou devido à expiração do secret (EXPIRATION). Presente apenas em notificações de eventos SECRET_DELETE.

Dados

O campo de dados é uma string UTF-8 que contém os metadados do objeto alterado. Os dados são um secret ou uma versão do secret.

Para notificações SECRET_DELETE, os metadados contidos no campo de dados representam os metadados do objeto como eram antes da exclusão. Para todas as outras notificações, os metadados incluídos no campo de dados representam os metadados do objeto após a alteração ocorrer.

Limitações

As notificações de eventos estão disponíveis apenas na API Secret Manager v1 e na Google Cloud CLI.

Antes de começar

É possível optar por armazenar todos os recursos no mesmo projeto ou armazenar secrets e tópicos do Pub/Sub em projetos separados. Conclua os seguintes pré-requisitos para configurar o Secret Manager e o Pub/Sub:

  • Secret Manager:

    • Crie ou use um projeto atual para armazenar os recursos do Secret Manager.
    • Se necessário, conclua as etapas mencionadas na página Ativar a API Secret Manager do guia do Secret Manager.
  • Pub/Sub:

    • Crie ou use um projeto atual para armazenar seus recursos do Pub/Sub.
    • Se necessário, ative a API Pub/Sub.

Faça a autenticação no Google Cloud:

$ gcloud auth login --update-adc

Criar uma identidade de agente de serviço

Você precisa criar uma identidade de agente de serviços para cada projeto que exige secrets com notificações de eventos.

Para criar uma identidade de serviço com a Google Cloud CLI, execute o seguinte comando:

$ gcloud beta services identity create \
    --service "secretmanager.googleapis.com" \
    --project "PROJECT_ID"

O comando anterior retorna um nome de conta de serviço usando o seguinte formato:

service-PROJECT_NUMBER@gcp-sa-secretmanager.iam.gserviceaccount.com

Você concederá a essa conta de serviço permissão para publicar nos tópicos do Pub/Sub que serão configurados nos seus secrets.

Salve o nome da conta de serviço como uma variável de ambiente:

# This is from the output of the command above
$ export SM_SERVICE_ACCOUNT="service-...."

As variáveis de ambiente para o projeto do Secret Manager, o projeto do Pub/Sub e a conta de serviço do Secret Manager precisam ser definidas durante todo o procedimento que você está seguindo.

Criar tópicos Pub/Sub

Siga o guia de início rápido do Pub/Sub para criar tópicos no seu projeto do Pub/Sub no console do Google Cloud. Como alternativa, crie tópicos com a Google Cloud CLI, como neste exemplo.

$ gcloud pubsub topics create "projects/PUBSUB_PROJECT_ID/topics/PUBSUB_TOPIC_NAME"

Repita essa ação várias vezes se quiser criar vários tópicos do Pub/Sub no secret.

Conceda permissão à conta de serviço para que o Secret Manager possa publicar nos tópicos que você acabou de criar. Isso pode ser feito pelo console do Google Cloud ou com a Google Cloud CLI. O comando a seguir concede o papel de Publicador do Pub/Sub (roles/pubsub.publisher) no tópico my-topic do Pub/Sub à conta de serviço.

$ gcloud pubsub topics add-iam-policy-binding PUBSUB_TOPIC_NAME \
    --member "serviceAccount:${SM_SERVICE_ACCOUNT}" \
    --role "roles/pubsub.publisher"

Criar assinaturas do Pub/Sub

Para visualizar as mensagens publicadas em um tópico, você também precisa criar uma assinatura do tópico. Siga o guia de início rápido do Pub/Sub para criar assinaturas no projeto do Pub/Sub no console do Google Cloud. Como alternativa, é possível criar assinaturas com a Google Cloud CLI, como neste exemplo.

$ gcloud pubsub subscriptions create "projects/PUBSUB_PROJECT_ID/subscriptions/PUBSUB_SUBSCRIPTION_NAME" \
    --topic "projects/PUBSUB_PROJECT_ID/topics/PUBSUB_TOPIC_NAME"

Criar um secret com tópicos configurados

Crie um secret com uma lista de até 10 tópicos configurados. Todos os tópicos configurados em um secret receberão notificações de eventos quando o secret ou uma das versões dele for alterada. O comando a seguir cria um secret com my-topic configurado.

gcloud

Para usar o Secret Manager na linha de comando, primeiro instale ou faça upgrade para a versão 378.0.0 ou mais recente da Google Cloud CLI. No Compute Engine ou no GKE, você precisa fazer a autenticação com o escopo do cloud-platform.

$ gcloud secrets create SECRET_ID --topics TOPIC_NAME

API

Esses exemplos usam curl para demonstrar o uso da API. É possível gerar tokens de acesso com o gcloud auth print-access-token. No Compute Engine ou no GKE, você precisa fazer a autenticação com o escopo do cloud-platform.

$ curl "https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets?secretId=SECRET_ID" \
    --request "POST" \
    --header "Content-Type: application/json" \
    --header "Authorization: Bearer $(gcloud auth print-access-token)" \
    --data-binary @- <<EOF
{
  "replication":{
    "automatic":{}
  },
  "topics":{
    "name": "TOPIC_NAME"
  }
}
EOF

Atualizar tópicos secretos

Modifique os tópicos do Pub/Sub configurados em um secret atualizando-o com os novos nomes de recursos dos tópicos do Pub/Sub. Com a CLI do Google Cloud, é possível adicionar ou remover um ou mais tópicos de um secret, além de limpar todos os tópicos dele.

Adicionar tópicos

Adiciona um ou mais tópicos a um secret. Adicionar um tópico que já está presente não terá efeito.

$ gcloud secrets update "SECRET_ID" \
    --project "PROJECT_ID" \
    --add-topics "projects/PUBSUB_PROJECT_ID/topics/my-topic-2,projects/PUBSUB_PROJECT_ID/topics/PUBSUB_TOPIC_NAME"

Remover tópicos

Remove um ou mais tópicos de um secret. Remover um tópico que não está presente não terá efeito.

$ gcloud secrets update "SECRET_ID" \
    --project "PROJECT_ID" \
    --remove-topics "projects/PUBSUB_PROJECT_ID/topics/PUBSUB_TOPIC_NAME,projects/PUBSUB_PROJECT_ID/topics/PUBSUB_OTHER_TOPIC_NAME"

Limpar temas

Remova todos os tópicos de um secret.

$ gcloud secrets update SECRET_ID \
    --project "PROJECT_ID" \
    --clear-topics

Consumir notificações de eventos com funções do Cloud Run

As notificações de eventos podem ser usadas para acionar fluxos de trabalho arbitrários, criando funções do Cloud Run para consumir as mensagens do Pub/Sub. Consulte a documentação do Cloud Run functions para conferir um guia completo. O exemplo de código a seguir é para uma função do Cloud que mostra eventType, secretId e metadados sempre que um evento é publicado no tópico. Confira aqui a lista de todos os tipos de evento do Secret Manager.

C#

Para executar esse código, primeiro configure um ambiente de desenvolvimento em C# e instale o SDK do C# do Secret Manager. No Compute Engine ou no GKE, você precisa fazer a autenticação com o escopo do cloud-platform.

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.PubSub.V1;
using System;
using System.Threading;
using System.Threading.Tasks;

// Triggered from a message on a Cloud Pub/Sub topic.
// The printed value will be visible in Cloud Logging
// (https://cloud.google.com/functions/docs/monitoring/logging).
namespace PubSubSample
{
    public class Function : ICloudEventFunction<MessagePublishedData>
    {
        public Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
        {
          string eventType = data.Message.Attributes["eventType"];
          string secretId = data.Message.Attributes["secretId"];
          string secretMetadata = data.Message.TextData;
          Console.WriteLine($"Received {eventType} for {secretId}. New metadata: {secretMetadata}.");
          return Task.CompletedTask;
        }
    }
}

Go

Para executar esse código, primeiro configure um ambiente de desenvolvimento do Go e instale o SDK do Go do Secret Manager. No Compute Engine ou no GKE, você precisa fazer a autenticação com o escopo do cloud-platform.

import (
	"context"
	"fmt"
)

// PubSubMessage is the payload of a Pub/Sub event.
type PubSubMessage struct {
	Attributes PubSubAttributes `json:"attributes"`
	Data       []byte           `json:"data"`
}

// PubSubAttributes are attributes from the Pub/Sub event.
type PubSubAttributes struct {
	SecretId  string `json:"secretId"`
	EventType string `json:"eventType"`
}

// ConsumeEventNotification demonstrates how to consume and process the Pub/Sub
// notification from Secret Manager.
func ConsumeEventNotification(ctx context.Context, m PubSubMessage) (string, error) {
	// The printed value will be visible in Cloud Logging:
	//
	//     https://cloud.google.com/functions/docs/monitoring/logging
	//
	eventType := m.Attributes.EventType
	secretID := m.Attributes.SecretId
	data := m.Data

	return fmt.Sprintf("Received %s for %s. New metadata: %q.",
		eventType, secretID, data), nil
}

Java

Para saber como instalar e usar a biblioteca de cliente do Secret Manager, consulte Bibliotecas de cliente do Secret Manager.

Para autenticar no Secret Manager, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


import java.util.Base64;
import java.util.Map;
import java.util.logging.Logger;
import lombok.Data;

// Demonstrates how to consume and process a Pub/Sub notification from Secret Manager. Triggered
// by a message on a Cloud Pub/Sub topic.
// Ideally the class should implement a background function that accepts a Pub/Sub message.
// public class ConsumeEventNotification implements BackgroundFunction<PubSubMessage> { }
public class ConsumeEventNotification {

  // You can configure the logs to print the message in Cloud Logging.
  private static final Logger logger = Logger.getLogger(ConsumeEventNotification.class.getName());

  // Accepts a message from a Pub/Sub topic and writes it to logger.
  public static String accept(PubSubMessage message) {
    String eventType = message.attributes.get("eventType");
    String secretId = message.attributes.get("secretId");
    String data = new String(Base64.getDecoder().decode(message.data));
    String log = String.format("Received %s for %s. New metadata: %s", eventType, secretId, data);
    logger.info(log);
    return log;
  }

  // Event payload. Mock of the actual Pub/Sub message.
  @Data
  public static class PubSubMessage {

    byte[] data;
    Map<String, String> attributes;
    String messageId;
    String publishTime;
    String orderingKey;
  }
}

Node.js

Para executar esse código, primeiro configure um ambiente de desenvolvimento do Node.js e instale o SDK do Node.js do Secret Manager. No Compute Engine ou no GKE, você precisa fazer a autenticação com o escopo do cloud-platform.

/**
* Triggered from a message on a Cloud Pub/Sub topic.
* The printed value will be visible in Cloud Logging
* (https://cloud.google.com/functions/docs/monitoring/logging).
*
* @param {!Object} event Event payload.
* @param {!Object} context Metadata for the event.
*/
exports.smEventsFunction = (event, context) => {
  const eventType = event.attributes.eventType;
  const secretID = event.attributes.secretId;
  const secretMetadata = Buffer.from(event.data, 'base64').toString();
  console.log(`Received ${eventType} for ${secretID}. New metadata: ${secretMetadata}.`);
};

Python

Para executar esse código, primeiro configure um ambiente de desenvolvimento do Python e instale o SDK do Python do Secret Manager. No Compute Engine ou no GKE, você precisa fazer a autenticação com o escopo do cloud-platform.

import base64


def consume_event_notification(event: dict, unused_context: None) -> str:
    """
    consume_event_notification demonstrates how to consume and process a
    Pub/Sub notification from Secret Manager.
    Args:
          event (dict): Event payload.
          unused_context (google.cloud.functions.Context): Metadata for the event.
    """
    event_type = event["attributes"]["eventType"]
    secret_id = event["attributes"]["secretId"]
    secret_metadata = base64.b64decode(event["data"]).decode("utf-8")
    event_notification = (
        f"Received {event_type} for {secret_id}. New metadata: {secret_metadata}"
    )
    print(event_notification)
    return event_notification

Ruby

Para executar esse código, primeiro configure um ambiente de desenvolvimento em Ruby e instale o SDK do Ruby do Secret Manager. No Compute Engine ou no GKE, você precisa fazer a autenticação com o escopo do cloud-platform.

require "functions_framework"
require "base64"

# Triggered from a message on a Cloud Pub/Sub topic.
# The printed value will be visible in Cloud Logging
# (https://cloud.google.com/functions/docs/monitoring/logging).
FunctionsFramework.cloud_event "sm_events_function" do |event|
  message = event.data["message"]
  event_type = message["attributes"]["eventType"]
  secret_id = message["attributes"]["secretId"]
  message_data = Base64.decode64 message["data"]
  FunctionsFramework.logger.info "Received %s for %s. New metadata: %s." % [event_type, secret_id, message_data]
end

Tópicos configurados incorretamente

Se tópicos do Pub/Sub forem adicionados a um secret em uma operação Create ou Update, mas o Secret Manager não puder publicar mensagens no tópico devido a uma configuração incorreta, a operação falhará com uma mensagem de erro indicando o motivo da falha na publicação. Isso pode acontecer, por exemplo, se o tópico não existir ou se a conta de serviço do Secret Manager não tiver permissão para publicar.

Se os tópicos do Pub/Sub forem adicionados a um secret e, em seguida, o tópico for alterado para que o Secret Manager não possa mais publicar mensagens (por exemplo, o tópico é excluído ou as permissões da conta de serviço do Secret Manager são removidas), o Secret Manager gravará registra no recurso Secret do Secret Manager com uma mensagem indicando o motivo da falha na publicação.

A seguir