London, UK 
6 Snow Hill, London, EC1A 2AY, UK

+442081331119

The Hague, The Netherlands 
WTC The Hague, 
Prinses Beatrixlaan 582 
2595 BM Den Haag

+31 (0) 70 240 0021

Sofia, Bulgaria 
141 Tsarigradsko Shose Blvd, VIP Security Building, Floor 2, Sofia 1784, Bulgaria

  • YouTube
  • Black Facebook Icon
  • Black Twitter Icon

© 2019 HeleCloud™

Overcome AWS Copy AMI boundaries – share encrypted AMIs with Packer – follow up

November 6, 2019

By Nikolay Bunev, Cloud Consultant at HeleCloud

 

Introduction

 

Back in March, we wrote a detailed explanation on how to overcome AWS Copy AMI boundaries by utilizing Hashicorp’s Packer. The solution outlined is still valid and working great – if you have it implemented, there is no need to revise it. 

However, back in May AWS have changed their APIs and now it’s possible to actually share an encrypted AMI with another account without copying and re-encrypting the AMI. They also wrote a nice blog-post  on their own to accompany the availability of a single step sharing, which is worth reading if you are going to use the AWS Console ot AWS CLI to achieve that goal. But if you are a fan of automation as we at HeleCloud are, in the next lines we will explain how to update the solution from our previous post in order to achieve the same. 

 

The Prerequisites

 

Before we do so, let’s get back to the AWS announcement and see what the requirements are for sharing AMIs encrypted with customer managed KMS keys (CMKs) with another account. In essence, you need:

  • To grant explicit launch permissions to the respective account number on the receiving account (the iam role used by codebuild should has ModifyImageAttribute)

To grant access to the receiving account in the CMKs resource policy with which you have encrypted the AMI (example policy below)

{

            "Sid": "Allow use of the ami key",

            "Effect": "Allow",

            "Principal": {

                "AWS": [

                    "arn:aws:iam::acc_id_1:root",

                    "arn:aws:iam::acc_id_2:root",

                    "arn:aws:iam::acc_id_3:root"

                ]

            },

            "Action": [

                "kms:Decrypt",

                "kms:ReEncrypt*",

                "kms:CreateGrant",

                "kms:DescribeKey"

            ],

            "Resource": [

"arn:aws:kms:eu-west-1:<originating_account_id>:key/<ami_encryption_key_id>"

     ]

}

 

 

The Solution

 

The new functionality simplifies the encrypted AMI sharing process and we can now:

  • remove the “Distribute AMI” stage from our previous CI/CD and replace it with a simple sharing

  • have a single packer build instead of a two-phase build (one un-encrypted plus one encrypted).

The new simplified diagram looks like:

 

The Code

 

Let’s see what we need to change in the code in order to use the new sharing option. 

  • ami_regions (array of strings) - A list of regions to copy the AMI to. Tags and attributes are copied along with the AMI. AMI copying takes time depending on the size of the AMI, but will generally take many minutes.

  • ami_users (string) – A list of account IDs that have access to launch the resulting AMI(s). By default no additional users other than the user creating the AMI has permissions to launch it.

 

To sum it up, we still utilize the ami_regions EBS Packer Builder configuration option, but we need to add the ami_users as well, in order to share the image with the accounts with which we want to do so.

As pointed out before, most of the configuration options are dynamically inherited in Packer as input variables from CodeBuild:

{
  "variables"{
    "keep_input_artifact""true",
    "vpc": "{{env `vpc_id`}}",
    "subnet": "{{env `subnet_id`}}",
    "aws_region": "{{env `AWS_REGION`}}",
    "os_type": "{{env `os_type`}}",
    "app_type": "{{env `app_type`}}",
    "ami_name": "{{env `ami_name`}}",
    "kms_key": "{{env `kms_key`}}",
    "ami_id": "{{env `ami_id`}}",

    "account_ids": "{{env `account_ids`}}"
  },
  "builders": [{
    "type": "amazon-ebs",
    "region": "{{user `aws_region`}}",
    "source_ami": "{{user `ami_id`}}",
    "ami_block_device_mappings": [
      {
        "delete_on_termination": "true",
        "device_name": "/dev/sda1"
      }
    ],
    "instance_type""t2.medium",
    "user_data_file""windows/bootstrap_win.txt",
    "communicator""winrm",
    "winrm_username""administrator",
    "ami_name""{{user `ami_name`}}",
    "encrypt_boot""true",
    "kms_key_id""{{user `kms_key`}}",

    "ami_users": {{ "user `account_ids`" }},
    "ami_regions": [ "eu-west-1", "eu-west-2" ],
    "region_kms_key_ids": {
      "eu-west-1""KMS_KEY_IN_EU_WEST_1",

      "eu-west-2""KMS_KEY_IN_EU_WEST_2",
    },
    "tags": {
      "Name""{{user `ami_name`}}",
      "ami_base_id""{{.SourceAMI}}",
      "ami_base_name""{{.SourceAMIName}}",
    },
    "ami_description""{{user `os_type`}} {{user `app_type`}}",
    "associate_public_ip_address""false",
    "vpc_id": "{{user `vpc`}}",
    "subnet_id": "{{user `subnet`}}"
  }]
}

 

Outcome

 

The encrypted AMI built in the originating account will be shared with all accounts listed as input to the ami_users and the AMI will be visible under “Private Images” in each region supplied to ami_regions, with one caveat (any tags that you may have on the originating AMI are not available, however the AMI Name is still present, as visible on the screenshot below)

 

 

Final Thoughts

 

As already pointed out, our old solution is still a valid approach, especially if you want to have a separate AMI copy in each account encrypted with its own key. However, managing all those copies in different regions and accounts, even automated could become cumbersome. 

This revised option will allow you to keep a single copy in the originating account while you are still able to use encrypted AMIs across your AWS account estate. 

Please get in touch if we can help with AWS solution designs, or any other aspect of the AWS platform.

 

Links

 

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIEncryption.html

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html

https://aws.amazon.com/blogs/security/simplify-granting-access-to-your-aws-resources-by-using-tags-on-aws-iam-users-and-roles/

https://aws.amazon.com/blogs/devops/how-to-create-an-ami-builder-with-aws-codebuild-and-hashicorp-packer/

https://www.packer.io/docs/builders/amazon-ebs.html

Share on Facebook
Share on Twitter
Please reload

Featured Posts
Archive
Please reload