Revoke an image and its descendants using inherited revocation
If one of your machine images has a vulnerability, you may need to revoke it to prevent infrastructure deployments from using it. If Packer builds use the image as a parent or source image, you may need to revoke its descendants too. HashiCorp Cloud Platform (HCP) Packer lets you revoke an image iteration and, optionally, all of its descendant images.
In this tutorial you will build parent and child images, and store metadata about their relationship in HCP Packer. You will then deploy the child images to AWS using Terraform Cloud, revoke a parent image and all its descendants, and observe the downstream impact to the Terraform Cloud workflow, enforced by an HCP Packer run task.
Note
Terraform Cloud Free Edition includes one run task integration that you can apply to up to ten workspaces. Refer to Terraform Cloud pricing for details.
In an ideal world, you would rarely revoke an image iteration, and instead "fail forward" by building a new image and launching new infrastructure from it. However, building new images takes time, and often the first priority in a security incident is to reduce the impact of a vulnerable image. In those situations, you may want to revoke an image to prevent new deployments while you work on a resolution.
Prerequisites
This tutorial assumes that you are familiar with the workflows for Packer and HCP Packer. If you are new to Packer, complete the Get Started tutorials first. If you are new to HCP Packer, complete the Get Started HCP Packer tutorials first.
This tutorial also assumes that you are familiar with the workflows for Terraform and Terraform Cloud. If you are new to Terraform, complete the Get Started tutorials first. If you are new to Terraform Cloud, complete the Terraform Cloud Get Started tutorials.
For this tutorial, you will need:
- Packer 1.7.10+ installed locally
- An HCP account with an HCP Packer Registry
- Terraform v1.3+ installed locally
- a Terraform Cloud account and organization
- Terraform Cloud locally authenticated
Now, create a new HCP service principal and set the following environment variables locally.
Environment Variable | Description |
---|---|
HCP_CLIENT_ID | The client ID generated by HCP when you created the HCP Service Principal |
HCP_CLIENT_SECRET | The client secret generated by HCP when you created the HCP Service Principal |
HCP_ORGANIZATION_ID | Find this in the URL of the HCP Overview page, https://portal.cloud.hashicorp.com/orgs/ORGANIZATION_ID/projects/xxxx |
HCP_PROJECT_ID | Find this in the URL of the HCP Overview page, https://portal.cloud.hashicorp.com/orgs/xxxx/projects/PROJECT_ID |
You will also need an AWS account with credentials set as local environment variables.
Environment Variable | Description |
---|---|
AWS_ACCESS_KEY_ID | The access key ID from your AWS key pair |
AWS_SECRET_ACCESS_KEY | The secret access key from your AWS key pair |
Set your Terraform Cloud organization name as an environment variable too.
Environment Variable | Description |
---|---|
TF_CLOUD_ORGANIZATION | The name of your Terraform Cloud organization |
Clone example repository
Clone the example repository, which contains the Packer templates and Terraform configuration used in this tutorial.
Change into the repository directory.
Build images
To save time, this tutorial uses a shell script to build several Packer images and assign them to HCP Packer channels.
Open packer/build-and-assign.sh
in your editor. The script first checks that you have set the necessary environment variables.
The script then declares a function that assigns the latest iteration in a bucket to the specified HCP Packer channel. The function creates the channel if it does not exist.
Next, the script authenticates with the HCP API using the HCP_CLIENT_ID
and HCP_CLIENT_SECRET
environment variables, and stores the returned bearer token in the bearer
variable for future API calls.
Then, it initializes Packer, builds both parent images in parallel, and waits for both to finish before proceeding.
After Packer finishes building the parent images, the script assigns them to their respective production
channels. Then it builds the child image and assigns the iteration to the child bucket's production
channel.
Change into the packer
directory.
Run the script. It may take up to 20 minutes to finish building. Continue with the tutorial while it runs.
Review packer templates
While the images build, open packer/parent-east.pkr.hcl
in your editor to review the first parent image template.
The template declares an amazon-ami
data source which returns the latest Ubuntu 22.04 AMI in the us-east-2
region.
The amazon-ebs
source block uses the Ubuntu AMI as the source for the build.
Packer then records the image's metadata in the learn-revocation-parent-us-east-2
HCP Packer bucket.
The parent-west.pkr.hcl
file follows the same pattern, but for the us-west-2
region.
This tutorial uses separate Packer templates for each of the parent image regions. However, the child template builds images in each region using a single template. While you could define both parent images in a shared template as well, this tutorial defines them separately for the purposes of demonstration. Later in the tutorial you will review how revoking just one of the parent images cascades to the child image.
Now, open and review packer/child.pkr.hcl
.
First, the template uses the hcp-packer-iteration
and hcp-packer-image
data sources to fetch metadata about both parent images from HCP Packer. The metadata includes AWS AMI IDs for the us-east-2
and us-west-2
regions.
The amazon-ebs
source blocks use the respective AMIs as the sources for the build.
Finally, Packer records the child image metadata in the learn-revocation-child
bucket.
Review Terraform configuration
Now, open terraform/main.tf
. This configuration creates two virtual machines using your child image.
First, the configuration uses the hcp_packer_iteration
data source to fetch image metadata from the learn-revocation-child
bucket's production
channel.
It then uses the hcp_packer_image
data source to query the iteration for the us-east-2
AMI ID.
Next, it uses the AWS VPC module to create a VPC, subnets, and a route table in the us-east-2
region.
Finally, the configuration creates a virtual machine from the us-east-2
child AMI.
The configuration then defines the same resources for the us-west-2
region.
Review builds and channel assignments
After Packer finishes building the images, visit the HCP Packer Overview page in HCP.
Review the Iterations pages for the learn-revocation-parent-us-east-2
, learn-revocation-parent-us-west-2
, and learn-revocation-child
buckets you created. Notice that the script assigned the latest iteration to the production
channel of each bucket.
Configure Terraform Cloud
Now, prepare your Terraform Cloud workspace to deploy infrastructure.
First, change to the terraform
directory.
Now, initialize your Terraform Cloud workspace.
Create HCP Packer run task
Now, create a Terraform Cloud Run Task for HCP Packer, which blocks terraform apply
s that would create new infrastructure using revoked images.
Navigate to the HCP Packer dashboard, open the Integrate with Terraform Cloud menu, and copy the Endpoint URL and HMAC Key values.
In your Terraform Cloud Organization's Settings, create a run task named HCP-Packer
. Configure it with the Endpoint URL and HMAC key values from the HCP Packer dashboard. For more detailed instructions, refer to our run task tutorial.
After you create the run task, associate it with your workspace. Go to Settings for the learn-hcp-packer-revocation
workspace, then select Run Tasks. Select HCP-Packer from the list of Available Run Tasks, then choose the Post-plan stage, and the Mandatory enforcement level. Click Create.
Configure workspace variables
Next, navigate to the learn-hcp-packer-revocation
workspace's Variables page.
Set the following workspace-specific variables. Be sure to use the environment variable type and mark the secrets as sensitive.
Type | Variable name | Description | Sensitive |
---|---|---|---|
Environment variable | AWS_ACCESS_KEY_ID | The access key ID from your AWS key pair | No |
Environment variable | AWS_SECRET_ACCESS_KEY | The secret access key from your AWS key pair | Yes |
Environment variable | HCP_CLIENT_ID | The client ID generated by HCP when you created the HCP Service Principal | No |
Environment variable | HCP_CLIENT_SECRET | The client secret generated by HCP when you created the HCP Service Principal | Yes |
Deploy infrastructure
Apply the Terraform configuration to create infrastructure that uses the child images. Respond yes
to the prompt to confirm the operation.
Revoke parent image and descendants
Imagine that you find a vulnerability in one of the parent images. If you have time you could avoid disrupting downstream teams by reassigning the channels to secure images before revoking the vulnerable ones. (Those secure images could be newly-patched or previous-good versions depending on your workflow.) But, since resolving vulnerabilities can take a long time and the incident might require an immediate response, you may need to revoke vulnerable images before you have safe replacements, to prevent new deployments of the image.
In this tutorial, you will revoke an image without building a replacement or reassigning channels to a known-good iteration, to explore how revocation can impact downstream teams' Terraform workflows.
Warning
Revoking an image does not modify or replace infrastructure that uses it.
To revoke an image iteration, you must first remove it from all channels.
In HCP Packer, navigate to the learn-revocation-parent-us-east-2
bucket, then to its Channels.
Hover over the production channel and click the ... menu that appears, then click Change assigned iteration.
Select Choose an iteration from the dropdown menu to unassign the iteration. Click Update channel.
Now navigate to Iterations, open the latest iteration's ... menu, and click Revoke Iteration.
Select Revoke immediately if your organization purchased the HCP Packer Plus tier. Then, enter a reason for the revocation, and click Next.
On the next page, select Revoke all descendants, type REVOKE, and click Revoke. HCP Packer revoked this image, but it may take a few minutes for the revocation to cascade to its descendants.
Open the HCP Packer dashboard. Locate the learn-revocation-parent-us-east-2
and learn-revocation-child
images. After a few minutes, the Status column for each shows Revoked.
Open the learn-packer-child
bucket. Under Image details, HCP Packer lists the newest iteration as Revoked.
Navigate to the bucket's Iterations, then click the ID of the revoked iteration. The banner lists the revocation date, reason, and which user triggered it.
Modify infrastructure using the revoked image
The child image's production
channel still references a revoked iteration, which will prevent Terraform from replacing or creating new EC2 instances.
Open terraform/main.tf
and change the instance_type
of the aws_instance.west
resource to t3.small
.
Apply the configuration change. Respond yes
to the prompt to confirm the operation.
The HCP Packer run task identified two resources using revoked images but did not block the apply. The run task prevents the creation of new resources, but will not block operations on existing infrastructure.
Now, modify the configuration to trigger a resource replacement.
In terraform/main.tf
, change the subnet of EC2 instance, which is a destructive change.
Now, attempt to apply the configuration change. The HCP Packer run task blocks the change because it creates a new resource using a revoked image.
You could also use custom conditions in your Terraform configuration to check the revoke_at
attribute of the hcp_packer_iteration
or hcp_packer_image
data sources. But, custom conditions are easy to remove and require that all configuration authors use them. The HCP Packer run task is a more robust way to prevent using revoked images since it automatically applies to all configuration in the workspace.
Destroy infrastructure and clean up
In the terraform
directory, destroy the infrastructure you created in this tutorial. Respond yes
to the prompt to confirm the operation.
Clean up Terraform Cloud resources
Navigate to your learn-packer-revocation
workspace in Terraform Cloud and delete the workspace.
Clean up HCP Packer
Navigate to the HCP Packer dashboard.
Locate the learn-revocation-child
image and open the ... menu. Select Delete image bucket.
Repeat for the learn-revocation-parent-us-east-2
and learn-revocation-parent-us-west-2
buckets.
Delete AWS machine images
Your AWS account still has machine images and their respective snapshots, which you may incur charges.
In the us-east-2
AWS region, deregister the learn-revocation AMIs
by selecting them, clicking the Actions button, then the Deregister AMI
option. Finally, confirm by clicking the Deregister AMI button in the
confirmation dialog.
Delete the learn-revocation snapshots by selecting the snapshots, clicking on the Actions button, then the Delete snapshot option, and finally confirm by clicking the Delete button in the confirmation dialog.
Repeat the above steps for the us-west-2
region.
Next Steps
In this tutorial you used HCP Packer to revoke a parent image and all descendant images built from it. You also used the HCP Packer run task to prevent new deployments of revoked images and reviewed how revocation can impact team workflows.
For more information on topics covered in this tutorial, check out the following resources.
- Complete the Build a Golden Image Pipeline with HCP Packer tutorial to build a sample application image with a golden image pipeline, and deploy it to AWS using Terraform.
- Complete the Schedule Image Iteration Revocation for Compliance tutorial to learn how to schedule image revocations and use preconditions to prevent use of revoked images outside of Terraform Cloud.
- Review the Standardize Machine Images Across Multiple Cloud Providers tutorial to learn how to build consistent machine images across cloud providers.