Secret Manager 이벤트 알림

이 주제에서는 Secret Manager에서 이벤트 알림을 지원하는 방법을 설명합니다.

개요

이벤트 알림은 보안 비밀 및 보안 비밀 버전 변경사항에 대한 정보를 Pub/Sub로 전송합니다. 이러한 알림은 새로운 보안 비밀 버전이 추가될 때 애플리케이션을 다시 시작하거나, 보안 비밀이 삭제될 때 보안 엔지니어에게 알리는 등의 임의 워크플로를 트리거하는 데 사용될 수 있습니다. 이러한 알림을 사용하여 워크플로를 트리거하는 방법에 대한 자세한 내용은 Pub/Sub 문서를 참조하세요.

Secret Manager에서 이벤트 알림이 작동하는 방식

보안 비밀은 최대 10개의 Pub/Sub 주제 목록으로 구성할 수 있습니다. 보안 비밀 또는 버전 중 하나를 수정하는 작업이 수행될 때마다 Secret Manager는 해당 보안 비밀의 각 Pub/Sub 주제에 메시지를 자동으로 게시합니다. Get, List, Access 호출은 메시지 게시로 이어지지 않습니다.

Pub/Sub 메시지에는 이벤트에 대한 메타데이터가 포함된 '속성' 키-값 쌍 및 생성되거나 수정된 보안 비밀 또는 SecretVersion 리소스의 전체 JSON 직렬화를 포함하는 'data' 필드가 포함됩니다. 이 JSON은 Secret Manager 공개 API에서 지정한 형식과 정확히 동일한 형식으로 보안 비밀 또는 SecretVersion 리소스를 나타내는 UTF-8로 인코딩된 문자열이며, proto3 JSON 매핑에 지정된 대로 JSON으로 인코딩됩니다.

이벤트 유형

다음은 현재 Secret Manager에서 지원하는 이벤트 유형 목록입니다.

이벤트 유형 설명
SECRET_CREATE 새 보안 비밀이 성공적으로 생성되면 전송됩니다.
SECRET_UPDATE 새 보안 비밀이 성공적으로 업데이트되면 전송됩니다.
SECRET_DELETE 사용자가 시작한 요청 또는 보안 비밀 만료로 인해 보안 비밀이 삭제되면 전송됩니다.
SECRET_VERSION_ADD 새 보안 비밀 버전이 성공적으로 추가되면 전송됩니다.
SECRET_VERSION_ENABLE 보안 비밀 버전이 사용 설정되면 전송됩니다.
SECRET_VERSION_DISABLE 보안 비밀 버전이 사용 중지되면 전송됩니다.
SECRET_VERSION_DESTROY 보안 비밀 버전이 삭제되면 전송됩니다.
SECRET_ROTATE 보안 비밀을 순환해야 할 시점에 전송됩니다. 자세한 내용은 보안 비밀의 순환 정책 만들기 및 관리를 참조하세요.
TOPIC_CONFIGURED

eventType: TOPIC_CONFIGURED 이외의 본문 또는 속성이 없는 테스트 메시지입니다. 이는 보안 비밀이 생성되거나 Pub/Sub 주제 목록으로 업데이트될 때 전송되지만 작업 성공을 나타내지는 않습니다.

작업이 성공하면 SECRET_CREATE 또는 SECRET_UPDATE 메시지가 즉시 전송됩니다.

주제가 보안 비밀에 업데이트될 때마다 TOPIC_CONFIGURED 메시지가 이미 존재하는 주제를 비롯한 보안 비밀의 모든 주제로 전송됩니다.

알림 형식

Pub/Sub 주제로 전송되는 알림은 다음 두 부분으로 구성됩니다.

  • 속성: 이벤트를 설명하는 키:값 쌍의 조합입니다.
  • 데이터: 변경된 객체의 메타데이터를 포함하는 문자열입니다.

속성

속성은 Secret Manager에서 Pub/Sub 주제로 전송한 알림에 포함된 키:값 쌍입니다. TOPIC_CONFIGURED 테스트 메시지를 제외한 모든 알림에는 알림 데이터에 관계없이 항상 다음 키:값 쌍 조합이 포함됩니다.

속성 이름 예시 설명
eventType SECRET_CREATE 방금 발생한 이벤트의 유형. 가능한 값 목록은 이벤트 유형을 참조하세요.
dataFormat JSON_API_V1 객체 데이터의 형식입니다.
secretId projects/p/secrets/my-secret 이벤트가 발생한 보안 비밀의 전체 리소스 이름입니다.
timestamp 2021-01-20T11:17:45.081104-08:00 이벤트가 발생한 시간입니다.

또한 알림에는 다음과 같은 키:값 쌍 조합이 포함되는 경우가 있습니다.

속성 이름 예시 설명
versionId projects/p/secrets/my-secret/versions/456

이벤트가 발생한 보안 비밀 버전의 이름입니다.

SECRET_VERSION_ADD, SECRET_VERSION_ENABLE, SECRET_VERSION_DISABLE, SECRET_VERSION_DESTROY 이벤트 알림에만 있습니다.

deleteType REQUESTED 사용자(REQUESTED) 또는 보안 비밀 만료(EXPIRATION)로 인해 삭제가 요청되었는지 여부입니다. SECRET_DELETE 이벤트 알림에만 있습니다.

데이터

데이터 필드는 변경된 객체의 메타데이터를 포함하는 UTF-8 문자열입니다. 데이터는 보안 비밀 또는 보안 비밀 버전입니다.

SECRET_DELETE 알림의 경우 데이터 필드에 포함된 메타데이터는 삭제되기 전의 객체 메타데이터를 나타냅니다. 다른 모든 알림의 경우, 데이터 필드에 포함된 메타데이터는 변경이 발생한 이후의 객체 메타데이터를 나타냅니다.

제한사항

이벤트 알림은 Secret Manager v1 API 및 gcloud 명령줄 도구에서만 사용할 수 있습니다.

시작하기 전에

모든 리소스를 동일한 프로젝트에 저장하거나 보안 비밀과 Pub/Sub 주제를 별도의 프로젝트에 저장할 수 있습니다. 다음 기본 요건을 완료하여 Secret Manager와 Pub/Sub를 설정합니다.

  • Secret Manager:

    • 프로젝트를 만들거나 기존 프로젝트를 사용하여 Secret Manager 리소스를 보존합니다.
    • 필요한 경우 Secret Manager 빠른 시작의 Secret Manager 구성 섹션의 단계를 완료합니다.
  • Pub/Sub:

    • 프로젝트를 만들거나 기존 프로젝트를 사용하여 Pub/Sub 리소스를 보존합니다.
    • 필요한 경우 Pub/Sub API를 사용 설정합니다.

Google Cloud에 인증합니다.

$ gcloud auth login --update-adc

서비스 에이전트 ID 만들기

이벤트 알림과 함께 보안 비밀이 필요한 각 프로젝트에 대해 서비스 에이전트 ID를 만들어야 합니다.

Cloud SDK를 사용하여 서비스 ID를 만들려면 다음 명령어를 실행하세요.

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

이전 명령어는 다음 형식을 사용하여 서비스 계정 이름을 반환합니다.

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

이 서비스 계정에 보안 비밀에 구성될 Pub/Sub 주제에 게시할 권한을 부여합니다.

서비스 계정 이름을 환경 변수로 저장합니다.

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

이 절차를 따를 때는 항상 Secret Manager 프로젝트, Pub/Sub 프로젝트, Secret Manager 서비스 계정의 환경 변수를 설정해야 합니다.

Pub/Sub 주제 만들기

Pub/Sub 빠른 시작을 따라 Cloud Console의 Pub/Sub 프로젝트에 주제를 만듭니다. 또는 이 예시와 같이 gcloud 명령줄 도구를 사용하여 주제를 만들 수 있습니다.

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

보안 비밀에 여러 Pub/Sub 주제를 만들려면 이 과정을 여러 번 반복합니다.

서비스 계정에 방금 만든 주제에 게시할 수 있는 Secret Manager 권한을 부여합니다. 이 작업은 Cloud Console 또는 gcloud 명령줄 도구를 통해 수행할 수 있습니다. 다음 명령어는 my-topic Pub/Sub 주제에 대한 Pub/Sub 게시자 역할(roles/pubsub.publisher)을 서비스 계정에 부여합니다.

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

Pub/Sub 구독 만들기

주제에 게시된 메시지를 보려면 주제에 대한 구독도 만들어야 합니다. Pub/Sub 빠른 시작을 따라 Cloud Console의 Pub/Sub 프로젝트에 구독을 만듭니다. 또는 이 예시와 같이 gcloud 명령줄 도구를 사용하여 구독을 만들 수 있습니다.

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

주제가 구성된 보안 비밀 만들기

최대 10개의 주제 목록으로 구성된 보안 비밀을 만듭니다. 보안 비밀에 구성된 모든 주제는 보안 비밀 또는 보안 비밀 버전 중 하나가 변경될 때 이벤트 알림을 수신합니다. 다음 명령어는 my-topic이 구성된 보안 비밀을 만듭니다.

gcloud

명령줄에서 Secret Manager를 사용하려면 먼저 Cloud SDK 버전 338.0.0 이상을 설치하거나 업그레이드합니다. Compute Engine 또는 GKE에서는 cloud-platform 범위로 인증해야 합니다.

$ gcloud secrets create SECRET_ID --topics TOPIC_NAME

API

이 예시에서는 curl을 사용하여 API를 사용하는 방법을 보여줍니다. gcloud auth print-access-token을 사용하여 액세스 토큰을 생성할 수 있습니다. Compute Engine 또는 GKE에서는 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

보안 비밀 주제 업데이트

새 Pub/Sub 주제 리소스 이름으로 보안 비밀을 업데이트하여 보안 비밀에 구성된 Pub/Sub 주제를 수정합니다. gcloud 명령줄 도구를 사용하면 보안 비밀에서 하나 이상의 주제를 추가 또는 삭제할 수 있으며 보안 비밀에서 모든 주제를 삭제할 수 있습니다.

주제 추가

보안 비밀에 하나 이상의 주제를 추가합니다. 존재하는 주제를 추가하면 영향이 없습니다.

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

주제 삭제

보안 비밀에서 하나 이상의 주제를 삭제합니다. 존재하지 않는 주제를 삭제하면 영향이 없습니다.

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

주제 지우기

보안 비밀에서 모든 주제를 삭제합니다.

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

Cloud Functions로 이벤트 알림 사용

이벤트 알림을 사용하여 Pub/Sub 메시지를 사용할 Cloud 함수를 만들어 임의의 워크플로를 트리거할 수 있습니다. 전체 가이드는 Cloud Functions 문서를 참조하세요. 아래 샘플 코드는 UPDATE_SECRET 이벤트가 주제에 게시될 때마다 보안 비밀 메타데이터를 출력하는 Cloud 함수용입니다.

C#

이 코드를 실행하려면 먼저 C# 개발 환경을 설정하고 Secret Manager C# SDK를 설치합니다. Compute Engine 또는 GKE에서는 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

이 코드를 실행하려면 먼저 Go 개발 환경을 설정하고 Secret Manager Go SDK를 설치합니다. Compute Engine 또는 GKE에서는 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
}

자바

이 코드를 실행하려면 먼저 자바 개발 환경을 설정하고 Secret Manager 자바 SDK를 설치합니다. Compute Engine 또는 GKE에서는 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

이 코드를 실행하려면 먼저 Node.js 개발 환경을 설정하고 Secret Manager Node.js SDK를 설치합니다. Compute Engine 또는 GKE에서는 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

이 코드를 실행하려면 먼저 Python 개발 환경을 설정하고 Secret Manager Python SDK를 설치합니다. Compute Engine 또는 GKE에서는 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

이 코드를 실행하려면 먼저 Ruby 개발 환경을 설정하고 Secret Manager Ruby SDK를 설치합니다. Compute Engine 또는 GKE에서는 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

잘못 구성된 주제

Pub/Sub 주제가 생성 또는 업데이트 작업의 보안 비밀에 추가되었지만 구성 오류로 인해 Secret Manager에서 주제에 메시지를 게시할 수 없는 경우 게시 실패 이유를 나타내는 오류 메시지와 함께 작업이 실패합니다. 예를 들어 주제가 없거나 Secret Manager 서비스 계정에 게시 권한이 없는 경우 이러한 상황이 발생할 수 있습니다.

Pub/Sub 주제가 보안 비밀에 추가된 후 Secret Manager에서 더 이상 메시지를 게시할 수 없도록 주제가 변경되면(예: 주제가 삭제되었거나 Secret Manager 서비스 계정 권한이 삭제된 경우) Secret Manager는 게시에 실패한 이유를 나타내는 메시지를 포함하여 Secret Manager Secret 리소스에 로그를 작성합니다.

다음 단계