When we rebuilt our AWS Organizations account structure, we needed to migrate the Aurora data from the old account to the new one as-is.
However, the Aurora cluster in the old account was encrypted using the AWS-managed key (aws/rds). After some investigation, we learned that aws/rds cannot be shared across accounts, meaning we couldn’t simply copy the snapshot to the new account...
To address this, we created customer-managed keys (CMKs) in both the old and new accounts, re-encrypted the snapshot using the CMK in the old account, and then copied/restored it to the new account.
We ran into several subtle issues with KMS key policies, so here is a complete step-by-step record for future reference.
Overall Flow
| Step | Account | Description |
|---|---|---|
| 1 | Old | Create CMK for snapshot encryption |
| 2 | Old | Create Aurora snapshot |
| 3 | Old | Copy snapshot with re-encryption using old CMK |
| 4 | Old | Share CMK-encrypted snapshot with new account |
| 5 | New | Create CMK for re-encryption in new account |
| 6 | New | Re-encrypt copied snapshot with new CMK |
| 7 | New | Restore Aurora from CMK-encrypted snapshot |
Architecture
Steps
1. Create a CMK for snapshot encryption in the old account
Create a CMK in the same region as the Aurora cluster.
Here is the key policy required for cross-account snapshot sharing.
{
"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"
}
}
}
]
}
Note 1: Why ReEncryptFrom / ReEncryptTo are required
To share Aurora snapshots across accounts, encryption must transition through multiple layers.
aws/rds → old CMK → new CMK
ReEncryptFrom is needed to decrypt the existing key, and is used during.
-
AllowUseFromOldAccountViaRDS→ decrypting snapshot encrypted withaws/rds -
AllowUseFromNewAccountViaRDS→ decrypting snapshot encrypted with old CMK
ReEncryptTo is needed to encrypt data with the new key.
- Used during Step 3 to re-encrypt with old CMK
Note 2: Creating a CMK via the AWS Console
Refer to the following screenshots.
2. Create an Aurora snapshot
From console or CLI.
aws rds create-db-cluster-snapshot \
--db-cluster-snapshot-identifier <snapshot> \
--db-cluster-identifier <cluster>
3. Copy and re-encrypt snapshot using the old account’s 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. Share the CMK-encrypted snapshot with the new account
aws rds modify-db-cluster-snapshot-attribute \
--db-cluster-snapshot-identifier my-snap-cmk \
--attribute-name restore \
--values-to-add NEW_ACCOUNT_ID
Once shared successfully, the new account should see the snapshot.
5. Create a new CMK in the new account
This CMK will be used to re-encrypt the snapshot again.
To re-encrypt the snapshot using the new CMK, you need to grant the ReEncryptTo permission in the key policy.
Key policy example.
{
"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. Copy and re-encrypt the shared snapshot using the new CMK
You then copy the snapshot again using the new CMK.
Internally, the encrypted data is extracted using the old CMK’s ReEncryptFrom permission, and then re-encrypted using the new CMK’s ReEncryptTo permission.
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. Restore Aurora from the re-encrypted snapshot in the new account
After that, restore the Aurora cluster from the snapshot you created.
If you are restoring it using Terraform, the configuration will look like this.
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
}
Conclusion
If you foresee migrating from a single-account setup to a multi-account structure, it’s much easier to use a CMK from the beginning. While it does cost more, it can save a huge amount of migration and operational effort later — making it well worth the investment.












Top comments (0)