CFnテンプレートの中でSecrets Managerシークレットを参照していて、シークレット値の更新をスタックに反映させたい

2022.06.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

やりたいこと

Secrets Manager のシークレットを作成して、それをCloudFormation(以下CFn)スタックテンプレートの中で参照し、スタックを作成しました。

EventBridgeからSlackにメッセージを送信するための接続設定

Resources:
  ConnectionToSlack:
      Type: AWS::Events::Connection
      Properties:
        Name: sample-connection-slack
        Description: Connection Setting to Slack
        AuthorizationType: API_KEY
        AuthParameters: 
          ApiKeyAuthParameters:
            ApiKeyName: Authorization
            ApiKeyValue: "Bearer {{resolve:secretsmanager:my-secret:SecretString:slack-oauth-token}}"

その後、このトークンの値を更新する必要があり、シークレットの値を更新しました。この更新をCFnスタックに反映したいのですが、テンプレート自体には差分が無いのでNo updates are to be performed.となります。どうやってCFnに参照しているSecrets Managerのシークレットの値が変わったことを伝えればよいでしょうか?

解決: version-idを使う

Secrets Managerのシークレットは値を更新する度に、version_idというユニークなIDが発行されます。またCFnテンプレートでシークレットを参照する際にversion_idまで指定することができます。これを使って更新後のシークレットのversion_idを指定するようにすれば良いです。

version_idを取得する

まずは更新後のシークレットのversion_idを取得しましょう。version_idは現在のところSecrets Managerのマネジメントコンソールでは表示されないようです。今回はAWS CLIを使って取得します。

% aws secretsmanager list-secret-version-ids --secret-id my-secret
{
    "Versions": [
        {
            "VersionId": "08a9757f-d8e4-4634-abf1-bbbbbbbbbbbb",
            "VersionStages": [
                "AWSCURRENT"
            ],
            "LastAccessedDate": "2022-06-27T09:00:00+09:00",
            "CreatedDate": "2022-06-27T16:50:05.006000+09:00",
            "KmsKeyIds": [
                "DefaultEncryptionKey"
            ]
        },
        {
            "VersionId": "4252bb91-7a01-41dc-b8d2-aaaaaaaaaaaa",
            "VersionStages": [
                "AWSPREVIOUS"
            ],
            "LastAccessedDate": "2022-06-27T09:00:00+09:00",
            "CreatedDate": "2022-06-27T16:06:48.366000+09:00",
            "KmsKeyIds": [
                "DefaultEncryptionKey"
            ]
        }
    ],
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:012345678901:secret:my-secret-L9VBSp",
    "Name": "my-secret"
}

1回更新したので、バージョンが2つあることがわかりますね。更新後のversion_id08a9757f-d8e4-4634-abf1-bbbbbbbbbbbbだということがわかりました。

テンプレートを更新する

 Resources:
   ConnectionToSlack:
       Type: AWS::Events::Connection
       Properties:
         Name: sample-connection-slack
         Description: Connection Setting to Slack
         AuthorizationType: API_KEY
         AuthParameters: 
           ApiKeyAuthParameters:
             ApiKeyName: Authorization
-            ApiKeyValue: "Bearer {{resolve:secretsmanager:my-secret:SecretString:slack-oauth-token}}"
+            ApiKeyValue: "Bearer {{resolve:secretsmanager:my-secret:SecretString:slack-oauth-token::08a9757f-d8e4-4634-abf1-bbbbbbbbbbbb}}"

このテンプレートでスタックを更新すれば、やりたかったシークレットの更新をスタックに反映することができます。

ステージングラベルもある

ちょっと蛇足です。シークレットの各バージョンには任意のラベルを設定することができ、CFnテンプレートでシークレットを参照する際にこのラベルを指定してそれに紐づく特定のバージョンを使うこともできます。

SAMPLE_LABELというステージングラベルを更新後のバージョンに追加してみましょう。

% aws secretsmanager update-secret-version-stage --secret-id my-secret --version-stage SAMPLE_LABEL --move-to-version-id  08a9757f-d8e4-4634-abf1-bbbbbbbbbbb
{
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:012345678901:secret:my-secret-L9VBSp",
    "Name": "my-secret"
}

list-secret-version-idsで再度各バージョンを確認すると、SAMPLE_LABELが付与されていることがわかります。

% aws secretsmanager list-secret-version-ids --secret-id my-secret
{
    "Versions": [
        {
            "VersionId": " 08a9757f-d8e4-4634-abf1-bbbbbbbbbbb",
            "VersionStages": [
                "SAMPLE_LABEL",
                "AWSCURRENT"
            ],
            "LastAccessedDate": "2022-06-27T09:00:00+09:00",
            "CreatedDate": "2022-06-27T16:50:05.006000+09:00",
            "KmsKeyIds": [
                "DefaultEncryptionKey"
            ]
        },
        {
            "VersionId": "4252bb91-7a01-41dc-b8d2-aaaaaaaaaaaa",
            "VersionStages": [
                "AWSPREVIOUS"
            ],
            "LastAccessedDate": "2022-06-27T09:00:00+09:00",
            "CreatedDate": "2022-06-27T16:06:48.366000+09:00",
            "KmsKeyIds": [
                "DefaultEncryptionKey"
            ]
        }
    ],
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:012345678901:secret:my-secret-L9VBSp",
    "Name": "my-secret"
}

これを参照するようにテンプレートを更新します。

Resources:
  ConnectionToSlack:
      Type: AWS::Events::Connection
      Properties:
        Name: sample-connection-slack
        Description: Connection Setting to Slack
        AuthorizationType: API_KEY
        AuthParameters: 
          ApiKeyAuthParameters:
            ApiKeyName: Authorization
            ApiKeyValue: "Bearer {{resolve:secretsmanager:my-secret:SecretString:slack-oauth-token:SAMPLE_LABEL}}"

参考情報