
Secrets Managerがクロスアカウントレプリケーションをサポートしたので試してみた
はじめに
2026年11月13日、AWS Secrets Manager がクロスアカウントレプリケーションに対応しました。
この機能は、プライマリのシークレットを別アカウントのレプリカへ同期します。レプリカにはレプリカ側の KMS キーが使われるため、プライマリ側のシークレットや KMS キーが利用できない場合でも、レプリカを参照できます。
今回、2つのアカウントで、レプリケーションの設定、プライマリの更新の反映、プライマリ側 KMS キーの権限を外したときの動作、解除と昇格を試しました。
設定
AWS CLI 2.40.3 を使いました。リージョンは ap-northeast-1 です。2つのアカウントはどちらもメンバーアカウントで、関連付けには --replica-restriction NoRestriction を指定しました。プライマリのシークレットは、プライマリ側アカウントのカスタマーマネージドキー(CMK)で暗号化しています。
| 設定する場所 | 設定内容 | 無いときの結果 |
|---|---|---|
| レプリカ側 CMK のキーポリシー | プライマリ側アカウントに kms:Encrypt を許可 | 関連付けが AccessDeniedException で拒否される |
| プライマリ側 CMK のキーポリシー | レプリケーションロールに kms:Decrypt を許可 | プライマリを更新すると複製が Failed になる |
| レプリカのリソースポリシー | Secrets Manager が自動で付ける(自分では書かない) | — |
レプリカ側
レプリカ側アカウントで、CMK を作ります。作成時のキーポリシーは、アカウントルートに kms:* を許可する1文だけにして、replica-key-policy-initial.json に保存しました。
aws --profile replica --region ap-northeast-1 kms create-key --description xacct-demo\ replica --tags TagKey=Name\,TagValue=xacct-demo-replica --policy file://replica-key-policy-initial.json
次に、--cross-account-primary-arn にプライマリの ARN を指定してレプリカを作ります。作成時にシークレットの値は渡しません。
aws --profile replica --region ap-northeast-1 secretsmanager create-secret --name xacct-demo-replica-secret --cross-account-primary-arn arn:aws:secretsmanager:ap-northeast-1:111122223333:secret:xacct-demo-primary-secret-AbCdEf --kms-key-id arn:aws:kms:ap-northeast-1:123456789012:key/abcd1234-ab12-cd34-ef56-abcdef123456 --tags Key=Name\,Value=xacct-demo-replica
関連付ける前のレプリカは、複製状態が Pending で値を持ちません。
レプリカのリソースポリシーは、create-secret の時点で Secrets Manager が付けていました。ポリシー名 cross-account-replication を指定して get-resource-policy を実行すると、本文が返ります。
aws --profile replica --region ap-northeast-1 secretsmanager get-resource-policy --secret-id xacct-demo-replica-secret --policy-name cross-account-replication
ResourcePolicy の文字列は、エスケープを展開して JSON として読める形にしています。
{
"Version" : "2012-10-17",
"Statement" : [ {
"Sid" : "CrossAccountReplication",
"Effect" : "Allow",
"Principal" : {
"AWS" : "arn:aws:iam::111122223333:root"
},
"Action" : "secretsmanager:AcceptCrossAccountReplication",
"Resource" : "*",
"Condition" : {
"ForAnyValue:StringEquals" : {
"aws:InvokedBy" : "secretsmanager.amazonaws.com"
},
"ArnEquals" : {
"secretsmanager:CrossAccountPrimaryARN" : "arn:aws:secretsmanager:ap-northeast-1:111122223333:secret:xacct-demo-primary-secret-AbCdEf"
}
}
} ]
}
最後に、レプリカ側 CMK のキーポリシーに、プライマリ側アカウントへの kms:Encrypt の許可を足します。条件にレプリカの ARN を書くので、レプリカを作った後に実行します。put-key-policy はキーポリシー全体を置き換えるため、replica-key-policy.json にはアカウントルートの許可も含めます。
replica-key-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnableIAMPolicies",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:root" },
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "AllowCrossAccountReplication",
"Effect": "Allow",
"Principal": "*",
"Action": "kms:Encrypt",
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "111122223333",
"kms:EncryptionContext:SecretARN": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:xacct-demo-replica-secret-GhIjKl"
}
}
}
]
}
aws --profile replica --region ap-northeast-1 kms put-key-policy --key-id arn:aws:kms:ap-northeast-1:123456789012:key/abcd1234-ab12-cd34-ef56-abcdef123456 --policy-name default --policy file://replica-key-policy.json
プライマリ側
プライマリ側アカウントで、レプリケーションロールを作ります。ロールの権限ポリシーはレプリカ側 CMK への kms:Encrypt だけを許可し、kms:Decrypt の許可はプライマリ側 CMK のキーポリシーだけに置きました。
レプリケーションロールの定義
role-trust.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "secretsmanager.amazonaws.com" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": { "aws:SourceAccount": "111122223333" }
}
}
]
}
role-permissions.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EncryptReplicaSecretKey",
"Effect": "Allow",
"Action": "kms:Encrypt",
"Resource": "arn:aws:kms:ap-northeast-1:123456789012:key/abcd1234-ab12-cd34-ef56-abcdef123456",
"Condition": {
"StringEquals": { "kms:EncryptionContext:SecretARN": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:xacct-demo-replica-secret-GhIjKl" }
}
}
]
}
aws --profile primary --region ap-northeast-1 iam create-role --role-name xacct-demo-replication-role --assume-role-policy-document file://role-trust.json
aws --profile primary --region ap-northeast-1 iam put-role-policy --role-name xacct-demo-replication-role --policy-name replication --policy-document file://role-permissions.json
プライマリ側 CMK のキーポリシーに、ロールへの kms:Decrypt の許可を足します。ここでもアカウントルートの許可を含めた全文で置き換えます。
primary-key-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnableIAMPolicies",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "AllowReplicationRoleDecrypt",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/xacct-demo-replication-role" },
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"StringEquals": { "kms:EncryptionContext:SecretARN": "arn:aws:secretsmanager:ap-northeast-1:111122223333:secret:xacct-demo-primary-secret-AbCdEf" }
}
}
]
}
aws --profile primary --region ap-northeast-1 kms put-key-policy --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab --policy-name default --policy file://primary-key-policy.json
関連付け
関連付けは、プライマリ側アカウントから associate-cross-account-replica で実行します。操作者に必要な IAM 権限は API リファレンスに記載があります。この記事では管理者権限で実行しました。
aws --profile primary --region ap-northeast-1 secretsmanager associate-cross-account-replica --secret-id xacct-demo-primary-secret --cross-account-replica-arn arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:xacct-demo-replica-secret-GhIjKl --replication-role-arn arn:aws:iam::111122223333:role/xacct-demo-replication-role --replica-restriction NoRestriction
実行すると、関連付けが始まりました。
"ReplicationStatus": "InProgress"
値を読む前に、両側の describe-secret で InSync になったことを確かめます。
プライマリ側:
"CrossAccountReplicas": [
{
"ReplicaSecretARN": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:xacct-demo-replica-secret-GhIjKl",
"ReplicationRoleARN": "arn:aws:iam::111122223333:role/xacct-demo-replication-role",
"ReplicationStatus": "InSync"
}
]
レプリカ側:
"CrossAccountPrimary": {
"PrimarySecretARN": "arn:aws:secretsmanager:ap-northeast-1:111122223333:secret:xacct-demo-primary-secret-AbCdEf",
"ReplicationStatus": "InSync"
}
InSync になった後、レプリカ側アカウントで get-secret-value を実行すると値が返りました。VersionId は、プライマリの作成時に返った VersionId と同じです。
"VersionId": "EXAMPLE-VERSION-V1",
"SecretString": "value-v1",
1つのプライマリに関連付けられるレプリカは1つです。
複製の動作
更新の反映
プライマリを put-secret-value で更新し、レプリカ側アカウントの get-secret-value が新しい値を返すまでの時間を2回測りました。起点は put-secret-value の呼び出し直前、終点はレプリカが新しい値を返した時刻です。どちらも最初の読み取りで新しい値が返ったため、表の値は反映にかかった時間の上限です。
| 更新 | 起点 | 終点 | 起点から終点まで |
|---|---|---|---|
| value-v2 | 11:53:00.383Z | 11:53:01.393Z | 約1.01秒 |
| value-v3 | 11:53:09.431Z | 11:53:10.389Z | 約0.96秒 |
プライマリ側 CMK の権限を外したとき
プライマリ側 CMK のキーポリシーからレプリケーションロールへの kms:Decrypt の許可を外し、アカウントルートの許可だけの状態(primary-key-policy-initial.json)に戻しました。
aws --profile primary --region ap-northeast-1 kms put-key-policy --key-id arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab --policy-name default --policy file://primary-key-policy-initial.json
その状態でプライマリを value-v4 に更新し、複製状態とレプリカの値を見ました。
| 時点 | 複製状態 | レプリカの get-secret-value |
|---|---|---|
| 許可を外した直後 | レプリカ InSync | value-v3 |
| value-v4 へ更新して約15秒後 | 両側 Failed | value-v3 |
| 許可を戻して関連付けを再実行して約5秒後 | プライマリ InSync | value-v4 |
許可を外しても、プライマリへの put-secret-value とレプリカの get-secret-value は成功しました。失敗したのは複製だけで、プライマリ側の StatusMessage は次のとおりです。
"StatusMessage": "Replication failed: User: arn:aws:sts::111122223333:assumed-role/xacct-demo-replication-role/SecretsManagerCrossAccountReplication-123456789012 is not authorized to perform: kms:Decrypt on resource: arn:aws:kms:ap-northeast-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab because no identity-based policy allows the kms:Decrypt action (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: <Request ID>; Proxy: null)"
レプリカ側の StatusMessage は Replication failed in the primary account でした。
解除と昇格
操作ごとの状態
レプリケーションの解除には、プライマリ側の disassociate-cross-account-replica と、レプリカ側の stop-replication-to-replica があります。
aws --profile primary --region ap-northeast-1 secretsmanager disassociate-cross-account-replica --secret-id xacct-demo-primary-secret --cross-account-replica-arn arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:xacct-demo-replica-secret-GhIjKl
aws --profile replica --region ap-northeast-1 secretsmanager stop-replication-to-replica --secret-id xacct-demo-replica-secret-2
各操作は InSync のレプリカに実行し、結果を次の表にまとめました。1つのプライマリに関連付けられるレプリカは1つなので、プライマリ側の解除後に2つ目のレプリカを作って関連付け、レプリカ側の操作を試しました。
| 確認した項目 | プライマリ側 disassociate-cross-account-replica | レプリカ側 stop-replication-to-replica |
|---|---|---|
| プライマリの describe-secret | CrossAccountReplicas が消える | CrossAccountReplicas に Detached と Replication removed by the replica secret が残る |
| レプリカの describe-secret | Detached と Replication removed by the primary secret | CrossAccountPrimary が消える |
| レプリカの put-secret-value | 拒否される | 成功する |
どちらの操作でも、その後のプライマリの更新はレプリカへ届きません。
昇格後の状態
プライマリ側の解除で Detached になった1つ目のレプリカで stop-replication-to-replica を実行すると、レプリカは昇格しました。昇格後の get-secret-value は value-v4 を返し、put-secret-value は成功しました。複製用のリソースポリシーも無くなりました。
レプリカ側から昇格した場合、プライマリには Detached のレプリカの記録が残ります。記録を消すには、プライマリ側で disassociate-cross-account-replica を実行します。
aws --profile primary --region ap-northeast-1 secretsmanager disassociate-cross-account-replica --secret-id xacct-demo-primary-secret --cross-account-replica-arn arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:xacct-demo-replica-secret-2-MnOpQr
まとめ
Secrets Manager のクロスアカウントレプリケーションを設定し、レプリカの動作を確認できました。
プライマリ側アカウントのシークレットや CMK がランサムウェアの被害を受けて参照できなくなった場合でも、クロスアカウントレプリケーションがあれば、シークレットを復元できる可能性があります。
aws-samples のリポジトリでは、Lambda と EventBridge でシークレットをコピーする仕組みが公開されていましたが、今回 Secrets Manager の機能として使えるようになりました。
Secrets Manager の自動ローテーションなどを使っていると、ローテーション後の値は他から再現できません。シークレットにアクセスできなくなるリスクへの備えとして、ご活用ください。








