Notificações de eventos do Gerenciador de secrets

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

Veja a seguir uma lista dos tipos de evento atualmente 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_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 ferramenta de linha de comando gcloud.

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 na seção Como configurar o Secret Manager do guia de início rápido 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

Como 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 o SDK do Cloud, execute o comando a seguir:

$ 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 Cloud. Como alternativa, crie tópicos com a ferramenta de linha de comando gcloud, 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 no Console do Cloud ou com a ferramenta de linha de comando gcloud. O comando a seguir concede o papel de Editor do Pub/Sub (roles/pubsub.publisher) no tópico my-topic do Pub/Sub para a 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 Cloud. Como alternativa, é possível criar assinaturas com a ferramenta de linha de comando gcloud, 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 338.0.0 ou posterior do SDK do Cloud. 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

Como 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 ferramenta de linha de comando gcloud, é 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 o Cloud Functions

As notificações de eventos podem ser usadas para acionar fluxos de trabalho arbitrários, criando funções em nuvem para consumir as mensagens do Pub/Sub. Consulte a documentação do Cloud Functions para ver um guia completo. O exemplo de código abaixo é para uma Função do Cloud que exibe metadados secretos sempre que um evento UPDATE_SECRET é publicado no tópico.

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
    {
        public Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
        {
            if (data.Message.Attributes["eventType"] == "SECRET_UPDATE") {
                string secretId = data.Message.Attributes["secretId"];
                string secretMetadata = data.Message.TextData;
                Console.WriteLine($"Secret {secretId} was updated. Its new metadata is: {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 executar esse código, primeiro configure um ambiente de desenvolvimento do Java e instale o SDK do Java do Secret Manager. No Compute Engine ou no GKE, você precisa fazer a autenticação com o escopo do cloud-platform.

package com.example;

import com.example.Example.PubSubMessage;
import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import java.util.Base64;
import java.util.Map;
import java.util.logging.Logger;

// 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).
public class Example implements BackgroundFunction {
  private static final Logger logger = Logger.getLogger(Example.class.getName());

  @Override
  public void accept(PubSubMessage message, Context context) {
    if (message.attributes.get("eventType").equals("SECRET_UPDATE")) {
      String secretId = message.attributes.get("secretId");
      String data = new String(Base64.getDecoder().decode(message.data));
      logger.info(String.format("Secret %s was updated. Its new metadata is: %s", secretId, data));
    }
  }

  public static class PubSubMessage {
    String data;
    Map attributes;
    String messageId;
    String publishTime;
  }
}

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) => {
  event_type = event.attributes.eventType;
  if (event_type == 'SECRET_UPDATE') {
    const secretID = event.attributes.secretId;
    const secretMetadata = Buffer.from(event.data, 'base64').toString();
    console.log(`Secret ${secretID} was updated. Its new metadata is: ${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.

def consume_event_notification(event, unused_context):
    """
    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")
    return f"Received {event_type} for {secret_id}. New metadata: {secret_metadata}"

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"]
  if message["attributes"]["eventType"] == "SECRET_UPDATE"
    secret_id = message["attributes"]["secretId"]
    message_data = Base64.decode64 message["data"]
    FunctionsFramework.logger.info "Secret %s was updated. Its new metadata is: %s" % [secret_id, message_data]
  end
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