AWS Organizationsで新しいアカウント構成を作り直した際、旧アカウントのAuroraデータをそのまま新アカウントへ移行する必要がありました。
旧アカウントのAuroraはAWSマネージドキー(aws/rds)で暗号化されていたのですが、調べてみるとaws/rdsはクロスアカウント共有ができず、そのままスナップショットをコピーして新アカウントへ移行することができないということが発覚しました...
そのため、新旧の各アカウントでカスタマー管理キー(CMK)を作成して、旧アカウントでスナップショットをCMKで再暗号化した上で、新アカウントへのコピー・復元を行いました。
KMSポリシーなどで地味に詰まったので、備忘録として手順をまとめます。
全体の流れ
| ステップ | 実施アカウント | 内容 |
|---|---|---|
| 1 | 旧 | スナップショット暗号化用CMKを作成 |
| 2 | 旧 | Auroraスナップショットを作成 |
| 3 | 旧 | 作成したスナップショットをCMKで再暗号化コピー |
| 4 | 旧 | 新アカウントへCMK暗号化スナップショットを共有 |
| 5 | 新 | 新アカウント用のCMKを作成 |
| 6 | 新 | 旧アカウントから共有されたスナップショットを新アカウントのCMKで再暗号化コピー |
| 7 | 新 | CMK暗号化スナップショットからAuroraを復元 |
構成
手順
1. 旧アカウントでスナップショット暗号化用CMKを作成
まず、Auroraクラスターと同じリージョンに、スナップショットを再暗号化するためのCMKを作成します。
以下が、クロスアカウントでスナップショットを共有するためのキーポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowOldAccountAdmin",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<OLD_ACCOUNT_ID>:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "AllowUseFromOldAccountViaRDS",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<OLD_ACCOUNT_ID>:root"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncryptFrom",
"kms:ReEncryptTo",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "rds.<REGION>.amazonaws.com"
}
}
},
{
"Sid": "AllowUseFromNewAccountViaRDS",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<NEW_ACCOUNT_ID>:root"
},
"Action": [
"kms:Decrypt",
"kms:ReEncryptFrom",
"kms:DescribeKey",
"kms:CreateGrant"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "rds.<REGION>.amazonaws.com"
}
}
}
]
}
補足1: ReEncryptFrom/ReEncryptToが必要な理由
Auroraスナップショットをクロスアカウントで共有するには、暗号化を「aws/rds → 旧CMK → 新CMK」と段階的に包み替え(ReEncrypt)する必要があります。
ReEncryptFromは元の鍵で暗号化されたデータを取り出すための権限で、今回のクロスアカウントコピーでは以下のステップでそれぞれ使われます。
-
AllowUseFromOldAccountViaRDS(aws/rdsで暗号化されたスナップショットからデータを取り出す) → ステップ2 -
AllowUseFromNewAccountViaRDS(旧CMKで暗号化されたスナップショットからデータを取り出す) → ステップ6
また、ReEncyptToは別の鍵で暗号化し直すための権限で、以下のステップで使われます。
-
AllowUseFromOldAccountViaRDS(aws/rds→ 旧CMKに暗号化し直す) → ステップ2
補足2: コンソールからCMKを作成する場合
以下のスクリーンショットを参考にしてみてください。
2. Auroraスナップショットを作成
マネジメントコンソールかCLIから手動で作成します。
aws rds create-db-cluster-snapshot \
--db-cluster-snapshot-identifier <snapshot> \
--db-cluster-identifier <cluster>
3. 作成したスナップショットをCMKで再暗号化コピー
旧アカウントでスナップショットをコピーし、ステップ1で作成したCMKで再暗号化します。
aws rds copy-db-cluster-snapshot \
--source-db-cluster-snapshot-identifier arn:aws:rds:REGION:OLD_ACCOUNT:cluster-snapshot:my-snap \
--target-db-cluster-snapshot-identifier my-snap-cmk \
--kms-key-id arn:aws:kms:REGION:OLD_ACCOUNT:key/<CMK-old>
4. 新アカウントへCMK暗号化スナップショットを共有
作成したスナップショットを、新アカウントへ共有します。
aws rds modify-db-cluster-snapshot-attribute \
--db-cluster-snapshot-identifier my-snap-cmk \
--attribute-name restore \
--values-to-add NEW_ACCOUNT_ID
共有が成功すると、新アカウントでスナップショットを確認できます。
5. 新アカウントでCMKを作成
旧アカウントから共有されたスナップショットと同じリージョンに、新CMKを作成します。
新CMKでスナップショットを再暗号化するため、キーポリシーにはReEncryptTo権限を付与します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<NEW_ACCOUNT_ID>:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow rds.amazonaws.com to use the key",
"Effect": "Allow",
"Principal": {
"Service": "rds.amazonaws.com"
},
"Action": [
"kms:ReEncryptTo",
"kms:GenerateDataKey*",
"kms:Encrypt",
"kms:DescribeKey",
"kms:Decrypt",
"kms:CreateGrant"
],
"Resource": "*"
}
]
}
6. 旧アカウントから共有されたスナップショットを新アカウントのCMKで再暗号化コピー
新CMKでスナップショットを再暗号化コピーします。
内部では、旧CMKのReEncryptFromで暗号化データを取り出し、新CMKのReEncryptToでデータを再暗号化しています。
aws rds copy-db-cluster-snapshot \
--source-db-cluster-snapshot-identifier arn:aws:rds:REGION:OLD_ACCOUNT:cluster-snapshot:my-snap-cmk \
--target-db-cluster-snapshot-identifier my-snap-new \
--kms-key-id arn:aws:kms:REGION:NEW_ACCOUNT:key/<CMK-new>
7. 新アカウントでスナップショットからAuroraクラスターを復元
後は作成したスナップショットからAuroraクラスターを復元します。
Terraformで復元する場合は以下のような記述となります。
resource "aws_rds_cluster" "example" {
cluster_identifier = "example-cluster"
snapshot_identifier = "arn:aws:rds:REGION:NEW_ACCOUNT:cluster-snapshot:my-snap-new"
kms_key_id = aws_kms_key.db.arn
engine = "aurora-mysql"
}
resource "aws_rds_cluster_instance" "example_instances" {
count = 2
identifier = "example-cluster-${count.index}"
cluster_identifier = aws_rds_cluster.example.id
instance_class = "db.r8g.large"
engine = aws_rds_cluster.example.engine
}
さいごに
シングルアカウントからマルチアカウントへ移行する見通しがあるなら、最初からCMKを使ったほうが楽ですね。お金はかかりますが、今回のような移行作業や将来の運用コストを考えると、十分回収できると思いました。











