132. Secrets Managerのローテーションは4段階の手続きである — createSecret・setSecret・testSecret・finishSecretとAWSCURRENT/AWSPENDING/AWSPREVIOUS
これまでのアプリ認証編は「IAMのAWSアクセスキー」を扱ってきましたが、今回は主題を「DBパスワードのようなアプリ自身の秘密」のライフサイクルに移します。Secrets Managerがパスワードを自動で入れ替えるとき、内部では公式に定められた4段階の手続きが順に呼ばれ、3つのラベルが版を渡り歩きます。その様子を図で追っていきます。
① そもそも「シークレットの版」とラベルという道具立て
- 公式は各版のラベルの割り当てをdescribe-secretの出力であるVersionIdsToStagesで確認できると述べる。ラベルは版そのものではなく「どの版を指すか」を表す。
シークレットは版を積み重ねられ、AWSCURRENT/AWSPENDING/AWSPREVIOUSという3つのラベルがどの版を指すかだけで「現在」「作りかけ」「一つ前」が決まります。値を上書きするのではなく、参照(ラベル)を動かして切り替える設計です。
② 4段階の手続き — ローテーションLambdaが順に呼ぶ
- createSecretはget_secret_valueで同じClientRequestTokenの版が既にないか確認し、なければcreate_secretで新規作成してからget_random_passwordで新値を生成、put_secret_valueでAWSPENDINGラベルを付けて保存する。
- 「Storing the new secret value in AWSPENDING helps ensure idempotency. If rotation fails for any reason, you can refer to that secret value in subsequent calls.」——先にAWSPENDINGへ保存するのは冪等性のためで、途中で失敗しても後続の呼び出しが同じ値を参照できる。
①で新値を「作りかけ(AWSPENDING)」として用意し、②で初めてDB本体を書き換え、③で新値の接続を検証し、④でラベルを付け替えて確定する。①〜③が終わるまで、アプリが取得するAWSCURRENTは旧値のままで、動作は途切れません。
③ finishSecret — 1回のAPI呼び出しでラベルが版を渡り歩く
- 引用: "moves the label AWSCURRENT from the previous secret version to this version, which also removes the AWSPENDING label in the same API call"
- 公式の注意: "Don't remove AWSPENDING before this point, and don't remove it by using a separate API call, because that can indicate to Secrets Manager that the rotation did not complete successfully"。この時点より前に、あるいは別のAPI呼び出しでAWSPENDINGを外すと、Secrets Managerはローテーション未完了とみなす。
- 成功後、AWSPENDINGはAWSCURRENTと同じ版に付くか、どの版にも付かないかのいずれか。もしAWSPENDINGがAWSCURRENTと違う版に残っていると、次回のローテーションは「前回がまだ進行中」と判断してエラーを返す。
finishSecretは1回のupdate_secret_version_stageで、AWSCURRENTを旧版から新版へ移し、同じ呼び出しでAWSPENDINGを外し、旧版には自動でAWSPREVIOUSが付きます。だからロールバックは「AWSPREVIOUSが指す版に戻す」だけで済む——最後の既知の正常版が常に残されているからです。
④ ローテーション戦略は2種類 — single userとalternating users
- single userは公式で"This is the simplest rotation strategy, and it is appropriate for most use cases"と明記。開いているデータベース接続はローテーションでも切断されないが、DB側のパスワード変更とシークレット側の更新の間には短いタイムラグがあり、その間は新しい認証情報を使った呼び出しがdenyされる低リスクがある(適切なリトライ戦略で緩和可能)、と公式は述べる。
- alternating usersは"applications that require high availability"に適し、ローテーション中にアプリが取得しても"still gets a valid set of credentials"、"After rotation, both user and user_clone credentials are valid"。公式は"even less chance of applications getting a deny than single user rotation"とも明記。
- クローンユーザーの作成にはsuperuserの認証情報を別シークレットで用意する必要があり、クローンは元ユーザーと同じ権限で作成されるため、元ユーザーの権限を後から変更した場合はクローン側の権限も変更する必要がある。クローンが元ユーザーと同じ権限を持たない場合、および一時的・対話的ユーザーの認証情報にはsingle userを推奨。
single userは1ユーザーのパスワードを毎回入れ替える最も単純な戦略で、大半の用途に適します。alternating usersはオリジナルとクローンを交互に更新するため、ローテーションの最中でもどちらかが常に有効で、高可用性が要る場面に向きます。
⑤ 既習事項との接続 — 「実体は追加、参照を動かして切り替える」の再登場
- コンテナ編で見た「タスク実行ロールがSecrets Managerから秘密を取得する」構図の、その秘密自身がどう更新されているかの内側の解剖にあたる。取得側(アプリ)は常にAWSCURRENTを引くだけで、裏で版とラベルが動いていることを意識しなくてよい。
Lambdaのバージョン+エイリアスが「実体は不変、参照だけ動かす」だったのと同じく、Secrets Managerのローテーションも「版を追加し、AWSCURRENTという参照を付け替える」だけ。この一貫した原則を知っていれば、ロールバックがなぜ「AWSPREVIOUSに戻すだけ」で済むのかが自然に腑に落ちます。