Each Amazon Machine Image (AMI) holds information of the volumes and snapshots of those volumes that should be attached to instances created from that AMI. To protect the data on those snapshots, you can choose to encrypt them using KMS. Encrypting your data at rest is generally a good idea, though many companies choose to avoid encrypting their snapshots, because sharing such snapshots between different AWS accounts (for example, Test and Production accounts) can be difficult. That’s why I’m sharing details on how to make this as easy as possible (and automated!).
Intro
First of all, to clear up any confusion: the AMIs are not encrypted. An AMI is simply a bit of metadata, which stores information like machine architecture, virtualisation type and a list of snapshots and volumes to be created from those snapshots. None of that data is sensitive in any way. The snapshots themselves, which actually hold the data, can (and should) be encrypted.
AWS allows you to share an AMI with non-encrypted snapshots with other AWS accounts. Other accounts do not actually have to “store” a copy of that AMI. Your “source account” (the owner of the AMI) can grant “launch permissions” to other accounts, which will let them launch EC2 instances from the granted AMI, without actually holding the data. This has impact from billing perspective, since the owner account will be charged for snapshot storage, but the other accounts will not. If the owner account deletes the AMI, however, it will disappear for other accounts (though any already running instances will not be terminated!). If required, a full-blown copy of the AMI (with all the snapshot data) can be created for another account - simply select the AMI and choose “Copy AMI” in the Console. This will preserve the AMI on other accounts, even if it’s deleted on the original one, but both accounts will now be charged for snapshot storage.
With encryption, this gets a bit more complicated. For AWS-known reasons, launch permissions cannot be granted on AMIs with encrypted snapshots. That means the “target” account needs to get the copy of the original snapshots in order to use them (i.e. will be billed for storage of those as well). To add to this, “Copy AMI” feature (which would be an easy solution) cannot be used with AMIs which use encrypted snapshots. Instead, you need to share the actual snapshot, create a copy from it on the target account and re-create the AMI (which is, again, essentially just a bunch of metadata, so not hard to replicate).
Prerequisite - Use custom KMS key for your snapshot
Each snapshot is encrypted with a KMS key. By default, when you first try to encrypt something, AWS will create a " default" key for that service. To see the list of your KMS keys, go to AWS Console, IAM and click on “Encryption keys” at the bottom of the menu on the left hand side (check the region at the top of the list). Any key starting with " aws/" (for example “aws/ebs”) is the default KMS key for that service. It will also have the orange AWS cube next to it.
In order for a snapshot to be shareable, it needs to be encrypted with a non-default KMS key. That is because, this key needs to be shared with the target account (so it can decrypt the data!). It would be generally a bad idea to share the default key with anyone, therefore you need to create another one. When creating a key, you can share it immediately with the other account - in the Console, Step 4 : Define Key Usage Permissions allows you to put in account ID of any other AWS account that should have access to this key. You can also add those later, by selecting the key and scrolling down to External Accounts.
Once you have the non-default key, use it to encrypt your snapshots.
Let’s share!
Once you have an AMI with snapshots encrypted using the non-default key (and the key is shared with the target account), you can copy it to the target account. The general steps are as follow:
- Grant “create volume” permissions to the target account
- Create an owned copy of the snapshot on the target account
- Create a new AMI using the newly copied snapshot
That’s it!
Automating
In general, this process is annoying to perform manually, so it’s best to automate it. The script below performs the above steps (and a couple of optional ones) for you.
|
|
This script assumes that your default AWS credentials are configured to work with the source account and that an IAM
Role is created on the target account that can be assumed from the source account. You can also modify the code
to replace the target_session
with a separate connection, for example using a different configured profile. If you do
want to use the code as is, create a role on the target account: Console - IAM - Roles - Create role - Another AWS
Account - input the ID of the source account. You can use the following policy to grant the necessary permissions to the
role:
|
|
Don’t forget to also adjust the settings (role name, region, target account id) on the top of the script. The code will
create a basic 64-bit AMI using HVM and a single (root) volume from the copied snapshot. If you want to use a different
architecture or all more volumes, you can adjust the code as needed - modify the new_image = target_ec2.register_image
, possible options are listed
in boto3 documentation.