Cómo configurar notificaciones en un secreto

En este tema, se analiza la compatibilidad con notificaciones de eventos en Secret Manager.

Descripción general

Las notificaciones de eventos envían información sobre los cambios en los secretos y las versiones de los secretos a Pub/Sub. Estas notificaciones se pueden usar para activar flujos de trabajo arbitrarios, como el reinicio de una aplicación cuando se agrega una nueva versión de un secreto o la notificación a ingenieros de seguridad cuando se borra un secreto. Si deseas obtener más información para usar estas notificaciones a fin de activar flujos de trabajo, consulta la documentación de Pub/Sub.

Cómo funcionan las notificaciones de eventos en Secret Manager

Los secretos se pueden configurar con una lista de hasta 10 temas de Pub/Sub. Cada vez que se realiza una operación que modifica el secreto o una de sus versiones, Secret Manager publicará automáticamente un mensaje en cada uno de los temas de Pub/Sub de ese secreto. Las llamadas a Get, List y Access no dan como resultado publicaciones de mensajes.

Los mensajes de Pub/Sub tienen un conjunto de pares clave-valor “atributos” que contienen metadatos sobre el evento, así como un campo “datos” que contiene una serialización JSON completa del Secreto o SecretVersion que se creó o modificó. Este JSON es una string codificada en UTF-8 que representa el recurso Secreto o SecretVersion en el formato especificado por la API pública de Secret Manager, codificado en JSON como se especifica en la Asignación de JSON de proto3

Tipos de eventos

La siguiente es una lista de los tipos de eventos que admite Secret Manager:

Tipo de evento Descripción
SECRET_CREATE Se envía cuando se crea un secreto nuevo de forma correcta.
SECRET_UPDATE Se envía cuando un secreto nuevo se actualiza correctamente.
SECRET_DELETE Se envía cuando se borra un secreto, ya sea por una solicitud iniciada por el usuario o un vencimiento del secreto.
SECRET_VERSION_ADD Se envía cuando una nueva versión del secreto se agrega con éxito.
SECRET_VERSION_ENABLE Se envía cuando una versión del secreto está habilitada.
SECRET_VERSION_DISABLE Se envía cuando una versión de secreto está inhabilitada.
SECRET_VERSION_DESTROY Se envía cuando se destruye una versión del secreto.
SECRET_VERSION_DESTROY_SCHEDULED Se envía cuando se configura una duración de demora de destrucción en el secreto y el usuario intenta destruir una versión del secreto.
SECRET_ROTATE Se envía cuando es el momento de rotar un secreto. Consulta Crea y administra políticas de rotación de secretos para obtener más información.
TOPIC_CONFIGURED

Este es un mensaje de prueba sin cuerpo ni atributos que no sea eventType: TOPIC_CONFIGURED. Esto se envía cuando se crea o actualiza un secreto con una lista de temas de Pub/Sub, pero no indica que la operación se realizó con éxito.

Si la operación se realizó de forma correcta, se enviará un mensaje SECRET_CREATE o SECRET_UPDATE inmediatamente después.

Cada vez que se actualizan los temas de un secreto, se envía un mensaje de TOPIC_CONFIGURED a todos los temas del secreto, incluidos los que ya estaban presentes.

Formato de las notificaciones

Las notificaciones enviadas al tema de Pub/Sub constan de dos partes:

  • Atributos: Un conjunto de pares clave-valor que describen el evento
  • Carga útil: Una string que contiene los metadatos del objeto modificado

Atributos

Los atributos son pares clave-valor incluidos en las notificaciones que envía Secret Manager a tu tema de Pub/Sub. Todas las notificaciones que no sean mensajes de prueba de TOPIC_CONFIGURED siempre contienen el siguiente conjunto de pares clave-valor, sin importar los datos de la notificación:

Nombre del atributo Ejemplo Descripción
eventType SECRET_CREATE El tipo de evento que acaba de ocurrir. Consulta Tipos de eventos para obtener una lista de valores posibles.
dataFormat JSON_API_V1 El formato de los datos del objeto.
secretId projects/p/secrets/my-secret El nombre completo del recurso del secreto en el que se produjo el evento.
timestamp 2021-01-20T11:17:45.081104-08:00 La hora en que ocurrió el evento.

Además, las notificaciones a veces contienen el siguiente conjunto de pares clave-valor:

Nombre del atributo Ejemplo Descripción
versionId projects/p/secrets/my-secret/versions/456

El nombre de la versión del secreto en la que se produjo el evento.

Solo está presente en las notificaciones de eventos SECRET_VERSION_ADD, SECRET_VERSION_ENABLE, SECRET_VERSION_DISABLE y SECRET_VERSION_DESTROY.

deleteType REQUESTED Indica si un usuario (REQUESTED) solicitó la eliminación o debido a un vencimiento del secreto (EXPIRATION). Solo está presente en las notificaciones de eventos SECRET_DELETE.

Datos

El campo de datos es una string UTF-8 que contiene los metadatos del objeto modificado. Los datos pueden ser un secreto o una versión del secreto.

Para las notificaciones SECRET_DELETE, los metadatos que contiene el campo de datos representan los metadatos del objeto como estaban antes de la eliminación. Para todas las demás notificaciones, los metadatos incluidos en el campo de datos representan los metadatos del objeto después de la modificación.

Limitaciones

Las notificaciones de eventos solo están disponibles en la API de v1 de Secret Manager y en Google Cloud CLI.

Antes de comenzar

Puedes elegir almacenar todos los recursos en el mismo proyecto o almacenar secretos y temas de Pub/Sub en proyectos separados. Completa los siguientes requisitos previos para configurar Secret Manager y Pub/Sub:

  • Secret Manager

    • Crea o usa un proyecto existente para guardar tus recursos de Secret Manager.
    • Si es necesario, completa los pasos que se mencionan en la página Habilita la API de Secret Manager de la guía de Secret Manager.
  • Pub/Sub

Autentica en Google Cloud:

$ gcloud auth login --update-adc

Crea una identidad de agente de servicio

Debes crear una identidad de agente de servicio para cada proyecto que requiera secretos con notificaciones de eventos.

Para crear una identidad de servicio con Google Cloud CLI, ejecuta el siguiente comando:

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

En el comando anterior, se muestra un nombre de cuenta de servicio con el siguiente formato:

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

Otorgarás a esta cuenta de servicio permiso para publicar en los temas de Pub/Sub que se configurarán en tus secretos.

Guarda el nombre de la cuenta de servicio como una variable de entorno:

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

Las variables de entorno del proyecto de Secret Manager, el proyecto de Pub/Sub y la cuenta de servicio de Secret Manager deben configurarse todo el tiempo que sigas este procedimiento.

Crea temas de Pub/Sub

Sigue la Guía de inicio rápido de Pub/Sub para crear temas en tu proyecto de Pub/Sub en la consola de Google Cloud. Como alternativa, puedes crear temas con Google Cloud CLI como en este ejemplo.

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

Repite esto varias veces si deseas crear varios temas de Pub/Sub en el secreto.

Otorga a la cuenta de servicio para que Secret Manager pueda publicar en los temas recién creados. Esto se puede hacer a través de la consola de Google Cloud o con Google Cloud CLI. Con el siguiente comando, se otorga a la cuenta de servicio el rol de publicador de Pub/Sub (roles/pubsub.publisher) en el tema my-topic de Pub/Sub.

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

Crea suscripciones a Pub/Sub

Para ver los mensajes publicados en un tema, también debes crear una suscripción al tema. Sigue la Guía de inicio rápido de Pub/Sub para crear suscripciones en tu proyecto de Pub/Sub en la consola de Google Cloud. Como alternativa, puedes crear suscripciones con Google Cloud CLI como en este ejemplo.

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

Crea un secreto con temas configurados

Crea un secreto con una lista de hasta 10 temas configurados. Todos los temas configurados en un secreto recibirán notificaciones de eventos cuando se modifique el secreto o una de sus versiones. El siguiente comando crea un secreto con my-topic configurado.

gcloud

Para usar Secret Manager en la línea de comandos, primero instala o actualiza a la versión 378.0.0 o posterior de Google Cloud CLI. En Compute Engine o GKE, debes autenticarte con el permiso cloud-platform.

$ gcloud secrets create SECRET_ID --topics TOPIC_NAME

API

En estos ejemplos, se usa curl para demostrar el uso de la API. Puedes generar tokens de acceso con gcloud auth print-access-token. En Compute Engine o GKE, debes autenticarte con el permiso 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

Actualiza temas de secreto

Modifica los temas de Pub/Sub configurados en un secreto mediante la actualización del secreto con los nombres de los recursos del tema de Pub/Sub nuevos. Con Google Cloud CLI, puedes agregar o quitar uno o más temas de un secreto, así como borrar todos los temas del secreto.

Agrega temas

Agrega uno o más temas a un secreto. Agregar un tema que ya está presente no tendrá efecto.

$ 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"

Quita temas

Quita uno o más temas de un secreto. Quitar un tema que no está presente no tendrá efecto.

$ 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"

Borra temas

Quita todos los temas de un secreto.

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

Consume notificaciones de eventos con funciones de Cloud Run

Las notificaciones de eventos se pueden usar para activar flujos de trabajo arbitrarios mediante la creación de funciones de Cloud Run para consumir los mensajes de Pub/Sub. Consulta la documentación de Cloud Run Functions para obtener una guía completa. El siguiente código de muestra corresponde a una función de Cloud Functions que imprime eventType, secretId y metadatos cada vez que se publica un evento en el tema. Aquí puedes encontrar una lista de todos los tipos de eventos de Secret Manager.

C#

Para ejecutar este código, primero configura un entorno de desarrollo de C# e instala el SDK de C# para Secret Manager. En Compute Engine o GKE, debes autenticarte con el permiso 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 ejecutar este código, primero configura un entorno de desarrollo de Go e instala el SDK de Go para Secret Manager. En Compute Engine o GKE, debes autenticarte con el permiso 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 obtener información sobre cómo instalar y usar la biblioteca cliente de Secret Manager, consulta la sección sobre bibliotecas cliente de Secret Manager.

Para autenticarte en Secret Manager, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo 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 ejecutar este código, primero configura un entorno de desarrollo de Node.js e instala el SDK de Node.js para Secret Manager. En Compute Engine o GKE, debes autenticarte con el permiso 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 ejecutar este código, primero configura un entorno de desarrollo de Python e instala el SDK de Python para Secret Manager. En Compute Engine o GKE, debes autenticarte con el permiso 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 ejecutar este código, primero configura un entorno de desarrollo de Ruby e instala el SDK de Ruby de Secret Manager. En Compute Engine o GKE, debes autenticarte con el permiso 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

Temas mal configurados

Si los temas de Pub/Sub se agregan a un secreto en una operación de creación o actualización, Secret Manager no puede publicar mensajes en el tema debido a una configuración incorrecta, la operación fallará y mostrará un mensaje de error que indica por qué falló la publicación. Esto podría suceder, por ejemplo, si el tema no existe o si la cuenta de servicio de Secret Manager no tiene permiso para publicar.

Si se agregan temas de Pub/Sub a un secreto y, luego, se cambia el tema para que Secret Manager ya no pueda publicar mensajes (por ejemplo, se borra el tema o se quitan los permisos de la cuenta de servicio de Secret Manager), escribirá Secret Manager. se registra en el recurso Secret de Secret Manager con un mensaje que indica por qué falló la publicación.

¿Qué sigue?