新サービス AWS Secrets Manager のシークレットを CLI から更新し、その動作を理解する

こんにちは、菊池です。

AWS Summit 2018 San Francisco で発表された新サービス、Secrets Managerを触ってます。

今回は、シークレットに保存される値がどのように管理されているのか、AWS CLIを使って、その構成要素であるバージョン、ステージラベルを色々と操作しながら理解してみたいと思います。

シークレットの構成

シークレットを構成する要素は、公式ドキュメントに記載の以下の図がわかりやすいでしょう。

シークレットはメタデータと、シークレットの値を格納する各バージョンで構成されます。

  • メタデータ
    • ARN
    • 名前
    • 説明
    • KMSキー
    • ローテション設定
    • 最終利用日
    • タグ
  • バージョン
    • ID
    • ステージングラベル
    • シークレットの値

1つのシークレットには、複数のバージョンを持つことでシークレットの値を使い分けることができます。そのバージョンを管理するための要素が、ステージングラベルです。ステージングラベルに付与するラベルによって、シークレットの複数バージョンを管理します。

ステージングラベル:AWSCURRENT

デフォルトのバージョンに付与されるラベルです。このラベルが付与されたバージョンのシークレットの値を、通常は利用します。明示的にステージングラベルを指定しなければ、このバージョンが取得されます。

ステージングラベル:AWSPREVIOUS

1つ前のバージョンに付与されるラベルです。新しいバージョンにAWSCURRENTを付与すると、それまでAWSCURRENTが付与されていたバージョンにAWSPREVIOUSが付与されます。

この他にも、任意の文字列のラベルをバージョンに付与することができます。1つのバージョンには最大で20個までのラベルが付与可能です。ただし、同時に複数のバージョンに同じラベルを付与することはできません。例えば、AWSCURRENTをもつラベルは1つのバージョンのみで、他のバージョンに付与する場合には、それまで付与されていたバージョンからは削除する必要があります。

シークレットのバージョンを操作してみる

実際にシークレットのバージョンを操作して、その挙動を確認していきます。まずは単純なシークレットをコンソールから登録しました。

この状態で、AWS CLIからシークレットを取得してみます。get-secret-valueコマンドでシークレットの値が取得できます。

$ aws secretsmanager get-secret-value --secret-id test
{
    "Name": "test",
    "VersionId": "56301bf3-21f9-4ce5-a42b-dd9667d63151",
    "SecretString": "{\"password\":\"version1\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1523092005.303,
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

{password:version1}が取得できました。また、ステージングラベル(VersionStages)にAWSCURRENTが設定されています。

次に、コンソールからシークレットをversion2に更新します。

これで再度取得してみると、{password:version2}が取得できます。

$ aws secretsmanager get-secret-value --secret-id test
{
    "Name": "test",
    "VersionId": "f03f988d-1658-4b54-b825-eb98992e6d41",
    "SecretString": "{\"password\":\"version2\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1523092141.428,
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

ここで、保存されたバージョンをlist-secret-version-idsコマンドで確認してます。

$ aws secretsmanager list-secret-version-ids --secret-id test
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG",
    "Versions": [
        {
            "VersionId": "f03f988d-1658-4b54-b825-eb98992e6d41",
            "VersionStages": [
                "AWSCURRENT"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092141.428
        },
        {
            "VersionId": "56301bf3-21f9-4ce5-a42b-dd9667d63151",
            "VersionStages": [
                "AWSPREVIOUS"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092005.303
        }
    ]
}

すると、{password:version1}を保存していた"VersionId": "56301bf3-21f9-4ce5-a42b-dd9667d63151"には、AWSPREVIOUSのラベルが保存されていることがわかります。1つ前のバージョンには、AWSPREVIOUSが付与されて保存されるということです。

ラベルを指定せずに新しいバージョンを作成するとAWSCURRENTが指定される

続いて、CLIからput-secret-valueで新しいバージョンを作成します。特にラベルは指定していませんが、レスポンスにAWSCURRENTのラベルが付与されています。

$ aws secretsmanager put-secret-value \
> --secret-id test \
> --secret-string "{\"password\":\"version3\"}"
{
    "VersionId": "e9ec4d8f-3012-48ae-a5f8-dc0b249f574e",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

シークレットの値を取得しても、新しいバージョンが取得できます。

$ aws secretsmanager get-secret-value --secret-id test
{
    "Name": "test",
    "VersionId": "e9ec4d8f-3012-48ae-a5f8-dc0b249f574e",
    "SecretString": "{\"password\":\"version3\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1523092732.549,
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

ラベルが空になったバージョンは削除される

保存されているバージョンを取得すると、AWSCURRENTAWSPREVIOUSが1つずつ進んでいます。一方で、1つ前にAWSPREVIOUSが付与されていたバージョン({password:version1})は削除されました。

$ aws secretsmanager list-secret-version-ids --secret-id test
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG",
    "Versions": [
        {
            "VersionId": "f03f988d-1658-4b54-b825-eb98992e6d41",
            "VersionStages": [
                "AWSPREVIOUS"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092643.074
        },
        {
            "VersionId": "e9ec4d8f-3012-48ae-a5f8-dc0b249f574e",
            "VersionStages": [
                "AWSCURRENT"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092732.549
        }
    ]
}

ラベルを指定してバージョンを作成するとAWSCURRENTは付与されない

続いて、明示的にラベルを指定してバージョンを作成してみます。put-secret-valueに--version-stages "NEXT"を付与して作成します。

$ aws secretsmanager put-secret-value \
> --secret-id test \
> --secret-string "{\"password\":\"version4\"}" \
> --version-stages "NEXT"
{
    "VersionId": "87b38f9f-5422-4e7f-8fa3-0857c0905b22",
    "VersionStages": [
        "NEXT"
    ],
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

この場合、シークレットの値を取得しても、AWSCURRENTは変わらずに以前のバージョンが取得できます。

$ aws secretsmanager get-secret-value --secret-id test
{
    "Name": "test",
    "VersionId": "e9ec4d8f-3012-48ae-a5f8-dc0b249f574e",
    "SecretString": "{\"password\":\"version3\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1523092732.549,
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

ラベル--version-stages "NEXT"を指定して取得すれば、作成したバージョンを取得できます。

$ aws secretsmanager get-secret-value \
> --secret-id test \
> --version-stage "NEXT"
{
    "Name": "test",
    "VersionId": "87b38f9f-5422-4e7f-8fa3-0857c0905b22",
    "SecretString": "{\"password\":\"version4\"}",
    "VersionStages": [
        "NEXT"
    ],
    "CreatedDate": 1523092955.717,
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

バージョンのリストを取得すると、AWSCURRENTAWSPREVIOUSは変わらないまま、新しいバージョンが保存されたことがわかります。

$ aws secretsmanager list-secret-version-ids --secret-id test
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG",
    "Versions": [
        {
            "VersionId": "f03f988d-1658-4b54-b825-eb98992e6d41",
            "VersionStages": [
                "AWSPREVIOUS"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092643.074
        },
        {
            "VersionId": "e9ec4d8f-3012-48ae-a5f8-dc0b249f574e",
            "VersionStages": [
                "AWSCURRENT"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092732.549
        },
        {
            "VersionId": "87b38f9f-5422-4e7f-8fa3-0857c0905b22",
            "VersionStages": [
                "NEXT"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092955.717
        }
    ]
}

ラベルAWSCURRENTを変更するとAWSPREVIOUSも変更される

AWSCURRENTを新しく保存したバージョンに付与してみます。update-secret-version-stageコマンドで、以前のバージョンからAWSCURRENTremoveし、新しいバージョンにmoveします。

$ aws secretsmanager update-secret-version-stage \
> --secret-id test \
> --version-stage AWSCURRENT \
> --remove-from-version-id e9ec4d8f-3012-48ae-a5f8-dc0b249f574e \
> --move-to-version-id 87b38f9f-5422-4e7f-8fa3-0857c0905b22
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

AWSCURRENTの変更と共に、AWSPREVIOUSも1つ前のバージョンに移動しました。AWSPREVIOUSが外されたバージョンは削除されています。

$ aws secretsmanager list-secret-version-ids --secret-id test
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG",
    "Versions": [
        {
            "VersionId": "87b38f9f-5422-4e7f-8fa3-0857c0905b22",
            "VersionStages": [
                "AWSCURRENT",
                "NEXT"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092955.717
        },
        {
            "VersionId": "e9ec4d8f-3012-48ae-a5f8-dc0b249f574e",
            "VersionStages": [
                "AWSPREVIOUS"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092732.549
        }
    ]
}

ステージラベルがあれば古いバージョンも保持可能

以下のように、現在3つのバージョンを保持しています。ラベルVERSION4のバージョンがAWSCURRENTです。

$ aws secretsmanager list-secret-version-ids --secret-id test
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG",
    "Versions": [
        {
            "VersionId": "87b38f9f-5422-4e7f-8fa3-0857c0905b22",
            "VersionStages": [
                "AWSCURRENT",
                "VERSION4"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092955.717
        },
        {
            "VersionId": "2625bf18-971d-44ec-abc9-46a600a85673",
            "VersionStages": [
                "VERSION5"
            ],
            "CreatedDate": 1523094151.125
        },
        {
            "VersionId": "422a96da-9790-4081-819c-4d123c3c96ed",
            "VersionStages": [
                "VERSION6"
            ],
            "CreatedDate": 1523094223.278
        }
    ]
}

AWSCURRENTVERSION5に移動します。

$ aws secretsmanager update-secret-version-stage \
> --secret-id test \
> --version-stage AWSCURRENT \
> --remove-from-version-id 87b38f9f-5422-4e7f-8fa3-0857c0905b22 \
> --move-to-version-id 2625bf18-971d-44ec-abc9-46a600a85673
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

VERSION5AWSCURRENTVERSION4AWSPREVIOUSに変更されました。

$ aws secretsmanager list-secret-version-ids --secret-id test
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG",
    "Versions": [
        {
            "VersionId": "87b38f9f-5422-4e7f-8fa3-0857c0905b22",
            "VersionStages": [
                "VERSION4",
                "AWSPREVIOUS"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092955.717
        },
        {
            "VersionId": "2625bf18-971d-44ec-abc9-46a600a85673",
            "VersionStages": [
                "AWSCURRENT",
                "VERSION5"
            ],
            "CreatedDate": 1523094151.125
        },
        {
            "VersionId": "422a96da-9790-4081-819c-4d123c3c96ed",
            "VersionStages": [
                "VERSION6"
            ],
            "CreatedDate": 1523094223.278
        }
    ]
}

ここからさらに、VERSION6AWSCURRENTに指定します。

$ aws secretsmanager update-secret-version-stage \
> --secret-id test \
> --version-stage AWSCURRENT \
> --remove-from-version-id 2625bf18-971d-44ec-abc9-46a600a85673 \
> --move-to-version-id 422a96da-9790-4081-819c-4d123c3c96ed

{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

VERSION6AWSCURRENTVERSION5AWSPREVIOUSに変更されました。AWSPREVIOUSが取り外されたバージョンも、ラベルVERSION4が残ってますので削除されずに保持されたままになります。

$ aws secretsmanager list-secret-version-ids --secret-id test
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG",
    "Versions": [
        {
            "VersionId": "87b38f9f-5422-4e7f-8fa3-0857c0905b22",
            "VersionStages": [
                "VERSION4"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092955.717
        },
        {
            "VersionId": "2625bf18-971d-44ec-abc9-46a600a85673",
            "VersionStages": [
                "VERSION5",
                "AWSPREVIOUS"
            ],
            "CreatedDate": 1523094151.125
        },
        {
            "VersionId": "422a96da-9790-4081-819c-4d123c3c96ed",
            "VersionStages": [
                "AWSCURRENT",
                "VERSION6"
            ],
            "CreatedDate": 1523094223.278
        }
    ]
}

バージョン作成時に複数ラベルを同時に指定

バージョン作成時に複数のラベルを同時に指定できます。AWSCURRENTVERSION7を同時に指定して作成します。

$ aws secretsmanager put-secret-value \
> --secret-id test \
> --secret-string "{\"password\":\"version7\"}" \
> --version-stages VERSION7 AWSCURRENT
{
    "VersionId": "cc824ce3-e79b-44ad-bd15-83f03d06d364",
    "VersionStages": [
        "AWSCURRENT",
        "VERSION7"
    ],
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG"
}

VERSION7AWSCURRENTとして作成されました。以前のバージョン、VERSION4/5も残っています。

$ aws secretsmanager list-secret-version-ids --secret-id test
{
    "Name": "test",
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:test-1O5wUG",
    "Versions": [
        {
            "VersionId": "87b38f9f-5422-4e7f-8fa3-0857c0905b22",
            "VersionStages": [
                "VERSION4"
            ],
            "LastAccessedDate": 1523059200.0,
            "CreatedDate": 1523092955.717
        },
        {
            "VersionId": "2625bf18-971d-44ec-abc9-46a600a85673",
            "VersionStages": [
                "VERSION5"
            ],
            "CreatedDate": 1523094151.125
        },
        {
            "VersionId": "422a96da-9790-4081-819c-4d123c3c96ed",
            "VersionStages": [
                "VERSION6",
                "AWSPREVIOUS"
            ],
            "CreatedDate": 1523094223.278
        },
        {
            "VersionId": "cc824ce3-e79b-44ad-bd15-83f03d06d364",
            "VersionStages": [
                "AWSCURRENT",
                "VERSION7"
            ],
            "CreatedDate": 1523094955.779
        }
    ]
}

まとめ

以上です。

新しいサービスであるAWS Secrets Managerのシークレットを手動で更新していくことで、その管理の仕組みを理解できました。ステージラベルをうまく使うことで、世代の管理や以前の情報をコントロールしていくことができそうです。

なお、実運用上は利用するアプリケーションと管理対象のシステムのパスワード変更などが同期して動作する必要があります。そのため、変更管理には提供されるLambdaを使ったローテーションをベースに使っていくのがよいでしょう。