Securing the Machine Image Supply Chain with Packer, SBOMs, and Signing
Golden images are the most trusted and least scrutinized artifacts in a fleet. Add provenance, SBOMs, scanning, and signing to your Packer pipeline that fail closed.
- #iac
- #ai
- #packer
- #supply-chain
- #sbom
- #signing
- #security
We spent the last few years applying supply-chain rigor to container images — SBOMs, vulnerability scanning, signatures, provenance — and somehow left machine images out of the conversation. Yet a golden AMI is one of the most trusted artifacts in any fleet: once it’s blessed, hundreds of instances boot from it without a second look. That combination of high trust and low scrutiny is exactly the profile attackers and accidental drift exploit. If you can’t answer “what’s in this image and who built it” months later, you have a blind spot in the most-replicated part of your infrastructure.
The good news is that Packer slots cleanly into a supply-chain pipeline. With a few post-processors and a CI flow that fails closed, every image becomes attributable, scannable, and verifiable before any instance boots from it. This guide walks through provenance, SBOM generation, scan gating, and signing.
Capture provenance at build time
The first gap is attribution. A typical Packer build produces an image with no record of what went into it. Fix that by writing build metadata into the image tags — the source image digest, the Packer version, the git commit of the build config, the timestamp, and the builder identity:
source "amazon-ebs" "base" {
source_ami_filter {
filters = { name = "al2023-ami-*-x86_64" }
owners = ["amazon"]
most_recent = true
}
ami_name = "golden-base-${var.git_sha}-${formatdate("YYYYMMDDhhmm", timestamp())}"
tags = {
SourceAMI = "{{ .SourceAMI }}"
GitCommit = var.git_sha
PackerVersion = packer.version
BuiltAt = timestamp()
Builder = var.ci_identity
}
}
Now, six months later, you can trace any running instance back to the exact commit and base image that produced its AMI. That’s the difference between an incident investigation that takes an hour and one that takes a week of guessing.
Generate an SBOM and gate on scan results
Provenance tells you what you intended; an SBOM tells you what’s actually there. Add post-processors that generate a software bill of materials and scan it, failing the build when findings exceed your threshold:
build {
sources = ["source.amazon-ebs.base"]
provisioner "shell" {
inline = ["sudo dnf update -y", "sudo dnf install -y nginx"]
}
# Generate an SBOM from the built image's filesystem.
post-processor "shell-local" {
inline = ["syft scan dir:/mnt/image-root -o spdx-json > sbom-${var.git_sha}.json"]
}
# Scan and FAIL CLOSED on high/critical findings.
post-processor "shell-local" {
inline = [
"grype sbom:sbom-${var.git_sha}.json --fail-on high --config grype-allowlist.yaml"
]
}
}
The --fail-on high flag is the load-bearing part. Generating an SBOM that nobody reads is theater; failing the build when a high-severity CVE is present is a control. The allowlist config handles documented exceptions — but treat every allowlist entry as a liability with an expiry date, an owner, and a justification. An allowlist without expiry dates is how a “temporary” exception for a critical vulnerability quietly becomes permanent across every image you ship.
Sign the artifact so consumers can verify
Provenance and SBOMs are useless if anyone can publish an image into your registry. Signing closes the loop: sign the published image and let consumers refuse anything that didn’t come from your pipeline.
# Sign the image's identifier/digest with a key from KMS (never a local file).
cosign sign --key awskms://alias/image-signing "$IMAGE_REF"
# Consumers verify before deploying:
cosign verify --key awskms://alias/image-signing "$IMAGE_REF"
The signing key is the crown jewel here. Keep it in a KMS or HSM, or issue short-lived credentials via CI OIDC — never bake a key into the Packer config or commit it to the repo. A signing key in a repo is worse than no signing at all, because it lets an attacker forge the exact authenticity stamp your consumers trust.
The pipeline order matters: fail closed
Sequence is the whole design. The pipeline must be build, then SBOM, then scan-gate, then sign, then publish — and it must fail closed at the gate, meaning a scan failure stops everything before signing and publishing. If signing happens before the gate, you’ve certified a vulnerable image. The correct flow only ever signs and publishes artifacts that passed the gate.
Drafting the pipeline with AI, keeping judgment human
This is a strong fit for AI assistance, with a clear human checkpoint. A prompt:
You are a platform-security engineer. Add SBOM generation (syft), vulnerability scanning (grype), and cosign signing to this Packer HCL2 build. The pipeline must fail closed on high/critical findings and only sign after the gate passes. Keep signing keys in KMS. Show the CI step order.
The model returned a solid pipeline and added the caveat that keeps a human in the loop:
I wired build -> SBOM -> scan -> sign -> publish, failing closed at the scan step. One decision for you: I set
--fail-on high, but your base AMI already ships with two medium-severity CVEs that have no fix available upstream. If you tighten to--fail-on mediumlater, you’ll need allowlist entries for those — and I’d recommend a human reviews the scan output before each release rather than auto-signing, since “no fix available” is a risk-acceptance call, not a technical one.
That’s exactly the right division of labor. The model built the pipeline and flagged that some CVE decisions are risk-acceptance calls a person must own. Never auto-sign on a green scan without a human glancing at what got accepted.
Trust, but make it verifiable
Golden images deserve the same supply-chain discipline as containers, and Packer makes it straightforward to add. Provenance answers “who built this,” SBOMs answer “what’s in it,” scanning answers “is it safe,” and signing answers “did it come from us.” Together they turn your most-trusted artifact from a leap of faith into a verifiable chain.
For generating the pipeline, see our Packer build provenance and signing prompt, and pair it with the Goss image compliance testing prompt to verify the image’s runtime configuration. The Infrastructure as Code category covers the rest of the image-pipeline toolchain. Build the gate first and make it fail closed — a scanner that warns is a scanner that gets ignored.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.