Sharing Default AWS KMS Key Encrypted RDS Snapshot

There was a point where I needed to share my PostgreSQL RDS snapshots between my Production and Backup Accounts, for the worst case scenario which is losing the Production Account somehow. I know this is snowball’s chance in hell, but the solution covers almost any failure with my precious, beloved, dearest Production account.

When I look at my Production Account occasionally

Back to the case, it was the point when I realised I created all RDS Instances with Default AWS KMS Key. Like every other “I reduced the frustration between Ops and Devs”, “I improved the deployment process” and “I increased reliability of our servers just like our customers want” guys (Author is talking about DevOps folks here), I started to research about snapshot sharing.

Oh no… I don’t want to extend the intro but I remember looking at the screen like a rabbit caught in the headlights, making circles non-stop in my office. That was because of this statement in AWS Docs:(https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ShareSnapshot.html)

You can’t share a snapshot that has been encrypted using the default AWS KMS encryption key of the AWS account that shared the snapshot.
Self Approval

What am I going to do? Do I need to terminate all my RDS to boot them again with CMK? This is physical pain! I calmed myself and start to think about a workaround. Then it came to my mind, can’t I just copy the default AWS KMS Key encrypted snapshot with a CMK and then share that copy? I approved myself like Joaqim Phoenix did magnificently and then I was on cloud nine with this idea! (Did you witness what I did there? I mixed an idiom including clouds with Cloud Industry)


Okey, let’s start our engines!

We have two accounts, one of them is our main account(123456789012) and the other one is our backup account(456789012345) which we are trying to share the snapshot with. For your information, I have edited sensitive information in screenshots for obvious reasons. Let’s investigate our RDS victim.

Encryption details of our RDS

Notice that in RDS Details frame, our RDS is encrypted with default AWS KMS Key. Now, let’s take a snapshot of it.

Snapshot of our RDS

Let’s see what happens when we try to share this snapshot.

AWS doesn’t allow us to share default AWS KMS Key encrypted snapshots

Gosh darn it! We can’t share this snapshot with another account. Now, let’s try copying this snapshot with a CMK(Customer Master Key) in the same region.

Copying the first snapshot with our CMK

Nice, back to our sharing with the recently copied snapshot…

The error message is now gone

Lovely! So, the error message is gone. That means we can now share this snapshot with our backup account(456789012345). Proceed and share it by adding other accounts ID(456789012345).

Side note here, we also need to share the CMK with the other account to allow it to use the encrypted snapshot. You can do this by Visual Editor or by modifying the JSON attached to CMK in our main account(123456789012).

{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "EnableIAMUserPermissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "AllowAccessForKeyAdministrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/MainAccountUser"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "AllowUseOfTheKey",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:user/MainAccountUser",
"arn:aws:iam::456789012345:root"
]
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "AllowAttachmentOfPersistentResources",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::456789012345:root"
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}

Another side note here, we need to attach an inline policy for allowing a role/user/group to use the shared CMK in our backup account(456789012345). For example, if you are using a Deployer user to provision your IaC, this needs to be done. Also, a user with Administrator access can use the key since it includes these permissions by itself.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowUseOfTheKey",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": [
"arn:aws:kms:eu-central-1:123456789012:key/${our_custom_key_id}"
]
},
{
"Sid": "AllowAttachmentOfPersistentResources",
"Effect": "Allow",
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": [
"arn:aws:kms:eu-central-1:123456789012:key/${our_custom_key_id}"
],
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": true
}
}
},
{
"Sid": "AllowReencryptionOfNewCMK",
"Effect": "Allow",
"Action": [
"kms:ReEncryptTo*",
"kms:ReEncryptFrom*"
],
"Resource": "*"
}
]
}

Now, let’s switch to our backup account(456789012345) and see if we can see the shared snapshot.

We can see our shared snapshot under “Shared With Me”

Voila! This is perfect. We have just shared the default AWS KMS Key encrypted RDS snapshot.

Although, if you want to restore this shared snapshot into backup account(456789012345), there is one more thing that needs to be doing. AWS doesn’t allow us to restore a shared snapshot. Thus, we need to copy this shared snapshot. While writing this, I realized there are so many steps. But don’t give up, we are so close!

After copying the shared snapshot, click on “Actions” button and as you can see, you can now restore this snapshot!

Let me end this with an analogy. AWS provides you with Lego parts and you are responsible for piecing them together.

Thanks for your time!