How to share a custom AMI to other accounts

Hi everyone 🙂, I am Manshu Sharma and today we are going to discuss an interesting topic that will help us to share custom private AMI in all accounts & regions. In this post first, create a custom encrypted AMI from the public AMI, and then share 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.

Requirments

  1. We need two AWS accounts i.e SourceAccount & DestinationAccount
  2. Have a basic knowledge of AWS services
  3. SourceAccount:- In which you build a custom AMI and encrypt the associated EBS snapshots.
  4. DestinationAccount:- In which you launch instances using the shared custom AMI with encrypted snapshots.
Note:- While writing this blog post I am considering two imaginary AWS account ids 111111111111  with region us-east-1 for  SourceAccount & 999999999999  with us-east-1 for DestinationAccount so be sure you replace this account id with your original account id.

Start with SourceAccount
In the SourceAccount,  We first going to create  AWS CMK & call it cmkSource. Remember while creating cmkSource you also need to give the AWS DestinationAccount id in the "Others AWS account" section.

Thereafter we create an IAM policy for the cmkSource. This delegate permission to the SourceAccount. I call it cmkSourcePolicy.
{
    "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/KEYID 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": [
                "*"
            ]
        }
    ]
}

In the DestinationAccount
Now in the DestinationAccount IAM user or role in the DestinationAccount needs permission to create an AMI.
So similarly we need to create  AWS CMK  & call it cmkTarget. 

Note:- This time you don't need to give the AWS DestinationAccount id in the "Others AWS account" section.



Now add the following JSON policy document that shows an example of the permissions that the IAM user or role policy needs in the DestinationAccount. 
{
    "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": [
                "*"
            ]
        }
    ]
}

Share custom AMI to other regions/accounts
Step 1 Go to SourceAccount and launch an instance from a public AMI:- Launch an EC2 instance from an EBS-backed public AMI in SourceAccount. I am using Amazon Linux 2 AMI (HVM) for this walkthrough, as shown in the following screenshot.



Step 2 Create a custom image from the instance:- Go into your newly created instance and customize according to your need then right-click on the newly created instance and select Image and template then select  Create image  thereafter click on the create image button to save the configuration as a custom AMI




Step 3 Create a copy of newly custom AMI:- The reason for doing this is because the default Master key aws/ebs will not allow to share encrypted EBS AMI to other accounts and regions. To copy an AMI right-click on the custom AMI you created and select Copy AMI.


Thereafter select the destination region North Virginia (my region)  and select Master key cmkSource and check the Encrypt target EBS snapshots.



Note:- I didn't change the AMI name and In-destination region I  select the same SourceAccount's region.
A custom AMI with encrypted snapshots is created, as shown in the following screenshot.


Step 4 Share a custom AMI with the target account:- Now select the newly generated copied AMI and click on the Actions button and select Modify Image Permission and Type the target account number in the AWS Account Number box and click save.

Step 5 Check AMI comes in DestinationAccount :- Now go to the destination account in EC2 select AMI from the navigation bar, you can see Our custom AMI will appear in the console.


Comments

Popular posts from this blog

MySQL Multi Source Master Slave Replication using GTID

Access and modify all the resources of our Wiki.js using WikiJS API

How to pass parameters in webhook?