AWS Security Blog

How to Create a Custom AMI with Encrypted Amazon EBS Snapshots and Share It with Other Accounts and Regions

August 31, 2021: AWS KMS is replacing the term customer master key (CMK) with AWS KMS key and KMS key. The concept has not changed. To prevent breaking changes, AWS KMS is keeping some variations of this term. More info.


An Amazon Machine Image (AMI) provides the information required to launch an instance (a virtual server) in your AWS environment. You can launch an instance from a public AMI, customize the instance to meet your security and business needs, and save configurations as a custom AMI. With the recent release of the ability to copy encrypted Amazon Elastic Block Store (Amazon EBS) snapshots between accounts, you now can create AMIs with encrypted snapshots by using AWS Key Management Service (KMS) and make your AMIs available to users across accounts and regions. This allows you to create your AMIs with required hardening and configurations, launch consistent instances globally based on the custom AMI, and increase performance and availability by distributing your workload while meeting your security and compliance requirements to protect your data.

In this blog post, I walk through the process of starting with a public AMI, creating a custom encrypted AMI from the public AMI, and then sharing the custom AMI with encrypted EBS snapshots across accounts and regions. This approach allows you to launch Amazon EC2 instances globally from multiple accounts by using the same base-encrypted AMI.  Note: This post does not apply to Windows AMIs and other AMIs from the AWS Marketplace that have a billingProduct code associated with them.

Solution overview

The following diagram illustrates the solution discussed in this blog post.

Solution diagram

This is an overview of the solutions steps:

  1. In the source account, create an EBS-backed custom AMI starting from a public AWS AMI in the source region.
  2. Add your encrypted EBS snapshots to the custom AMI, and give the target account access to the KMS encryption keys.
  3. Share your encrypted snapshots with the target account.
  4. Copy the snapshots to the target region and reencrypt them using the target account’s KMS encryption keys in the target region.
  5. Have the target account create an AMI using the encrypted EBS snapshots in the target region.

Prerequisites

For this walkthrough, you need two AWS accounts:

  1. The source account in which you build a custom AMI and encrypt the associated EBS snapshots.
  2. The target account in which you launch instances using the shared custom AMI with encrypted snapshots.

In this example, I will use fictitious account IDs 111111111111 and 999999999999 for the source account and the target account, respectively. As you go through this post, be sure to change these account IDs to match your own. In addition, you will create a KMS customer master key (CMK) in the source account in the source region as well as a KMS CMK in the target account in the target region. When you create a CMK for the target account, select the region where you plan to launch EC2 instances using the custom AMI. It is important to note that KMS keys are never transmitted outside the AWS regions in which they were created. For simplicity, I created two KMS CMKs, cmkSource under account 111111111111 in us-east-1, and cmkTarget under account 999999999999 in eu-west-1.

Note: You cannot share snapshots encrypted with your default EBS CMK with another account. Resources encrypted under a service default CMK can only be shared within the same account. If you are starting with snapshots encrypted under the default EBS CMK (with the key alias, aws/ebs), copy those snapshots and reencrypt them under a custom CMK you created in KMS. You will then be able to modify the key policy on the custom CMK to be able to grant access to the key to any number of external accounts.

The IAM user or role in the source account needs permission to build a custom AMI and perform the EC2 ModifySnapshotAttribute operation. This IAM user or role also needs to be able to perform the KMS DescribeKey, CreateGrant, GenerateDataKey and ReEncypt operations on the source account’s KMS CMK, cmkSource.

The source account’s IAM user or role policy

The following JSON policy document shows an example of the permissions an IAM user or role policy needs to have. For the KMS permissions to take effect in this IAM policy, the key policy document for cmkSource must delegate permission to the source account. This delegation happens by default when you create a KMS key. However, if you have made custom edits to the key policy for cmkSource, you may need to go back and reenable delegation to the account. See the KMS Developer Guide for more details.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [         
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:CreateGrant",
                "kms:DescribeKey*"
            ],
            "Resource": [
                "arn:aws:kms:us-east-1:111111111111:key/Key-ID of cmkSource"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:ListKeys",
                "kms:ListAliases"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:RunInstances",
                "ec2:StartInstances",
                "ec2:CreateImage",
                "ec2:CopyImage",
                "ec2:ModifySnapshotAttribute",
                "ec2:CreateSecurityGroup",
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:Describe*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

The IAM user or role in the target account needs permission to create an AMI. In addition, the IAM user or role in the target account needs to be able to perform the KMS DescribeKey, CreateGrant, and Decrypt operations on the source account’s cmkSource key so that the encrypted snapshots in the shared AMI can be decrypted. The target account’s user or role must also be able to perform the KMS CreateGrant, Encrypt, Decrypt, DescribeKey, and GenerateDataKeyWithoutPlaintext operations on the target account’s cmkTarget key in order to create a new copy of the AMI’s snapshots that are protected under KMS keys that are controlled by the target account.

The following steps give the target account permission to use cmkSource for decrypting the snapshots, you need to add the target account’s ID to the cmkSource key policy:

  1. From the IAM console, click Encryption Keys in the left pane and click the source account’s CMK, cmkSource, as shown in the following image.
    Screenshot showing cmkSource
  2. Look for the External Accounts subsection, click Add External Account, and type the target account ID, 999999999999.
    Screenshot showing addition of an external account

For more information about sharing custom encryption keys between accounts, see Share Custom Encryption Keys More Securely Between Accounts by Using AWS Key Management Service.

The target account’s IAM user or role policy

The following JSON policy document shows an example of the permissions that the IAM user or role policy needs. For the KMS permissions to take effect in this IAM policy, the key policy document for cmkSource and cmkTarget must delegate permission to the account. This delegation happens by default when you create a KMS key. However, if you have made custom edits to the key policy for cmkSource or cmkTarget, you may need to go back and reenable delegation to the account. See the KMS Developer Guide for more detail.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kms:DescribeKey",
                "kms:CreateGrant",
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:us-east-1:111111111111:key/key-id of cmkSource"
            ]                                                    
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:CreateGrant",
                "kms:Encrypt",
                "kms:Decrypt", 
                "kms:DescribeKey",
                "kms:GenerateDataKeyWithoutPlaintext"
            ],
            "Resource": [
                "arn:aws:kms:eu-west-1:999999999999:key/key-id of cmkTarget"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:ListKeys",
                "kms:ListAliases"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:ModifySnapshotAttribute",
                "ec2:CreateImage",
                "ec2:CopyImage",
                "ec2:RegisterImage",
                "ec2:CopySnapshot",
                "ec2:Describe*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Deploying the solution

Step 1: Create an EBS-backed custom AMI from a public AMI

To create an EBS-based custom AMI from a public AMI:

  1. Launch an EC2 instance from an EBS-backed public AMI that is similar to the custom AMI that you want to create. I am using Amazon Linux AMI (HVM) for this walkthrough, as shown in the following screenshot. For more information, see Launching an Instance.
    Screenshot of choosing Amazon Linux AMI (HVM)
  2. Now you can connect to the EC2 instance, customize the instance with your software and applications, harden the instance, and copy custom data. After you have customized your instance, you can create an AMI from the EC2 console. Click Instances in the left pane and select the EC2 instance that you customized. Click Actions and select Create Image to save the configuration as a custom AMI.
    Screenshot of creating the image

For a more detailed overview of creating EBS-backed AMIs, see Creating an Amazon EBS-Backed Linux AMI and Creating an Amazon EBS-Backed Windows AMI.

Step 2: Create a custom AMI with encrypted snapshots

Now, you will create a custom AMI that makes use of an encrypted boot volume:

  1. From the EC2 console, click AMIs in the left pane, select the custom AMI that you created in Step 1, click Actions, and then select Copy AMI. This creates an AMI with encrypted snapshots from an AMI with unencrypted snapshots.
  2. As shown in the following screenshot, select the destination region, US East (N. Virginia), and the source account’s KMS Master Key, cmkSource, which is used to encrypt the snapshots. For more information, see AMIs with Encrypted Snapshots.
    Screenshot showing the specification of destination region and Master Key

A custom AMI with encrypted snapshots is created, as shown in the following screenshot.

Screenshot of custom AMI with encrypted snapshots

Step 3: Share your encrypted snapshots with the target account

You cannot share an AMI with encrypted snapshots between accounts directly. Instead, you must copy the underlying encrypted snapshot to another account individually, and then recreate the AMI in the target account. This is required because the encrypted snapshots could potentially be encrypted under different KMS master keys, and each snapshot copy/decrypt/reencrypt operation needs to happen independently.

To share your encrypted snapshots with the target account:

  1. From the EC2 console, click Snapshots in the left pane and select Owned By Me. Use the AMI ID (as shown in the following image) to locate the EBS snapshot that is associated with the custom AMI that you created in Step 2.
    Screenshot of specifying AMI ID
  2. Click Actions and select Modify Permissions. Type the target account number in the AWS Account Number box.
    Screenshot showing specification of target account number

Step 4: Copy the snapshots to the target region and reencrypt them using the target account’s KMS encryption keys in the target region

To copy the snapshots to the target region and reencrypt them using the target account’s KMS encryption keys in the target region:

  1. Sign in to the target AWS account, go to the EC2 console’s Snapshots tab and select Private Snapshots. Locate the snapshot that was copied from the source account via Snapshot ID, as highlighted in the following screenshot.
    Screenshot of locating the snapshot that was copied from the source account
  2. Click Actions and select Copy from the drop-down list. Select EU (Ireland) for the Destination Region, and cmkTarget for the target account’s Master Key, as shown in the following image. You are reencrypting the EBS snapshot from the source account’s KMS CMK, cmkSource, to the target account’s KMS CMK, cmkTarget. This protects you if the owner of cmkSource revokes the key for any reason, which could cause users in the target account to lose access to the volume you created.
    Screenshot showing specification of destination region and Master Key

Step 5: Have the target account create an AMI using the encrypted EBS snapshot in the target region

To create an AMI in the target account using the encrypted EBS snapshot in the target region:

  1. Change your console’s region to the target region. In this solution, you copied the EBS snapshot to the EU (Ireland) Region in Step 4.
  2. Click the Snapshots tab in the EC2 console, and click Owned By Me. Locate the snapshots via Snapshot ID, as shown in the following image.
    Screenshot of locating the Snapshot ID
  3. Select the EBS snapshot, click Actions, and then select Create Image.
    Screenshot of choosing Create Image
  4. Choose the same virtualization type (highlighted in the following image) as the public AMI you used to create the custom AMI in Step 1.
    Screenshot of specifying Virtualization type
  5. Click AMIs in the left pane, and locate the custom AMI from the encrypted EBS snapshot that you created.
    Screenshot of locating the custom AMI

Now you can use the custom AMI that you copied from the source account in us-east-1 to launch EC2 instances in eu-west-1 using the target account. The custom AMI makes use of the configurations that you customized in the source account, and all stored data is encrypted end to end.

Conclusion

In this post, I have shown how to copy a custom AMI with encrypted snapshots across accounts and regions. This enables you to launch consistent instances globally based on your approved AMI, in order to meet your security and compliance requirements, while improving your agility and availability by distributing your workload. To learn more, see:

If you have comments about this post, submit them in the “Comments” section below. If you have questions about or issues implementing this solution, please start a new thread on the EC2 forum.

– Eugene

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.