Introduction :
This guide details the steps to set up Packer on an EC2 instance in AWS to build images across multiple AWS accounts without using static credentials. Instead, it uses IAM roles for secure access.
Prerequisites :
-
AWS Accounts :
- Source AWS Account: The account where the EC2 instance running Packer will be hosted.
- Target AWS Account(s): The account(s) where AMIs will be created.
-
AWS IAM Permissions :
- Administrative or equivalent permissions in both the source and target AWS accounts to create and manage IAM roles, policies, and EC2 instances.
-
EC2 Instance :
- Launch an EC2 instance in the source AWS account.
- Ensure the instance has internet access to download and install Packer.
- Appropriate security group settings to allow necessary traffic.
- HCP Account : HCP account is required here so that the user can use HCP Packer registry to store Packer image metadata, thereby enabling the user to track image lifecycle.
Step-by-Step Guide :
1. Launch EC2 Instance and Install Packer
Launch an EC2 instance in the source AWS account and install Packer. Refer to the official Packer installation guide here.
2. Create and Assign IAM Role to EC2 instance
Create an IAM role with the necessary permissions and assign it to the EC2 instance hosted on source AWS account. Ensure the "Trusted entity type" is set to AWS Service and the "Service or use case" is EC2.
IAM Role Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PackerIAMPassRole",
"Effect": "Allow",
"Action": [
"iam:PassRole",
"iam:GetInstanceProfile",
"ec2:DescribeImages"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<TARGET-ACCOUNT-NO>:role/<TARGET-ACCOUNT-ROLENAME>"
}
]
}
3. Configure IAM Role on Target AWS Account
Ensure the target AWS account has the IAM role created with administrative privileges. Modify the "Trust relationships" section to allow the source account to assume this role.
Trust Relationship Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<source-aws-account-no>:root"
},
"Action": "sts:AssumeRole"
}
]
}
Replace <source-aws-account-no> with the account number of the source AWS account.
4. Set Environment Variables for HCP Packer Registry
On the EC2 instance where Packer is installed, export the following environment variables to push metadata to your HCP Packer registry. Refer this :
export HCP_CLIENT_ID=xxxxxxxx
export HCP_CLIENT_SECRET=xxxxxxxxx
export HCP_PROJECT_ID=xxxxxxxxxxxx
Refer to the HCP documentation given here for creating and managing these service principals.
5. Build Images Using Packer
Navigate to your directory where you have kept packer configuration file for eg "aws.pkr.hcl" on the EC2 machine of the source AWS account and run the below commands
packer init .
packer fmt .
packer build aws.pkr.hcl
Your AMIs will be created in the target AWS account, and the artifacts will be visible in the HCP Packer registry.
6. Example Packer Configuration
Below is a sample packer configuration file to build AMIs in multiple regions. The configuration file given below builds AMIs in the us-west-1 and us-east-2 regions :
packer {
required_plugins {
amazon = {
version = ">= 1.0.1"
source = "github.com/hashicorp/amazon"
}
}
}
variable "version" {
type = string
default = "1.0.0"
}
data "amazon-ami" "ubuntu-focal-east" {
region = "us-east-2"
filters = {
name = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"
}
most_recent = true
owners = ["099720109477"]
}
source "amazon-ebs" "basic-example-east" {
assume_role {
role_arn = "arn:aws:iam::<TARGET-ACCOUNT-NO>:role/<TARGET-ACCOUNT-ROLENAME>"
session_name = "packer"
}
iam_instance_profile = "<TARGET-ACCOUNT-ROLENAME>"
region = "us-east-2"
source_ami = data.amazon-ami.ubuntu-focal-east.id
instance_type = "t2.small"
ssh_username = "ubuntu"
ssh_agent_auth = false
ami_name = "packer_AWS_{{timestamp}}_v${var.version}"
}
data "amazon-ami" "ubuntu-focal-west" {
region = "us-west-1"
filters = {
name = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"
}
most_recent = true
owners = ["099720109477"]
}
source "amazon-ebs" "basic-example-west" {
assume_role {
role_arn = "arn:aws:iam::<TARGET-ACCOUNT-NO>:role/<TARGET-ACCOUNT-ROLENAME>"
session_name = "packer"
}
iam_instance_profile = "<TARGET-ACCOUNT-ROLENAME>"
region = "us-west-1"
source_ami = data.amazon-ami.ubuntu-focal-west.id
instance_type = "t2.small"
ssh_username = "ubuntu"
ssh_agent_auth = false
ami_name = "packer_AWS_{{timestamp}}_v${var.version}"
}
build {
hcp_packer_registry {
bucket_name = "learn-packer-ubuntu"
description = <<EOT
Some nice description about the image being published to HCP Packer Registry.
EOT
bucket_labels = {
"owner" = "platform-team"
"os" = "Ubuntu",
"ubuntu-version" = "Focal 20.04",
}
build_labels = {
"build-time" = timestamp()
"build-source" = basename(path.cwd)
}
}
sources = [
"source.amazon-ebs.basic-example-east",
"source.amazon-ebs.basic-example-west"
]
}
Note: The
owners
field in the Packer configuration file given above is used to filter AMIs based on the owner account ID. Specifically, the value ["099720109477"]
represents the AWS account ID that owns the AMIs you are interested in. In this case, 099720109477
is the official AWS account ID for Canonical, the makers of Ubuntu. By specifying this account ID, you ensure that Packer retrieves only the official Ubuntu images provided by Canonical.Conclusion :
Following these steps ensures secure and efficient image building across multiple AWS accounts using Packer.
This article provides a comprehensive guide for setting up and using Packer with IAM roles for cross-account image building, ensuring security and efficiency.
Additional References :