Verify a Built Package
Purpose: For security officers and platform engineers, runs the integrity and policy checks that a Zarf package must pass before being moved across the air-gap boundary.
Prerequisites
-
The package file
dist/zarf-package-opencenter-airgap-amd64-<version>.tar.zst. -
Its
.sha256sidecar (always written by the build). -
Its
…-sbom.jsonSBOM (written by the build whenzarfproduces the package). -
The Cosign public key that pairs with the signing key, if the package was signed.
-
sha256sum,jq, and (optionally)cosignon$PATH.
Quick check (one command)
Run the helper script in hack/scripts/:
hack/scripts/verify-package.sh dist/zarf-package-*.tar.zst .secrets/signing-key.pub
Exit codes:
| Code | Meaning | |------|---------| | 0 | All checks passed. | | 1 | Bad invocation. | | 2 | Checksum failed. | | 3 | Cosign signature check failed. | | 4 | SBOM policy violation (mutable tag or HIGH/CRITICAL CVE). |
The script is the canonical workflow. The sections below explain what each step does so you can run them by hand or adapt them to your CI pipeline.
1. Checksum
sha256sum -c dist/zarf-package-*.tar.zst.sha256
# zarf-package-opencenter-airgap-amd64-1.0.0-rc2.tar.zst: OK
Failure means the file was modified or corrupted in transit. Do not deploy.
2. Cosign signature
cosign verify-blob \
--key .secrets/signing-key.pub \
--signature dist/zarf-package-*.tar.zst.sig \
dist/zarf-package-*.tar.zst
Failure means the file was modified after signing or was signed with a different key. Do not deploy.
If you do not have a key yet, generate one with opencenter-airgap keygen. The CLI writes the keypair to .secrets/signing-key.{key,pub}, sets 0600 on the private key, and adds .secrets/ to .gitignore if a git repo is present.
3. SBOM policy
The SBOM lists every artifact the package contains. You should reject the package if it contains mutable image tags or HIGH/CRITICAL CVEs.
SBOM=dist/zarf-package-opencenter-airgap-amd64-1.0.0-rc2-sbom.json
# Reject mutable tags.
jq '[.artifacts[]?
| select(.type == "image")
| select(.version == "latest" or .version == null)] | length' "$SBOM"
# expected: 0
# Reject HIGH/CRITICAL CVEs (only present if the build ran a scanner).
jq '[.vulnerabilities[]?
| select(.severity == "CRITICAL" or .severity == "HIGH")] | length' "$SBOM"
# expected: 0
hack/scripts/verify-package.sh runs both jq queries and exits 4 if either is non-zero.
4. Spot-check the contents (optional)
zarf package inspect dist/zarf-package-*.tar.zst | head -30
zarf package inspect dist/zarf-package-*.tar.zst --sbom-out /tmp/sbom-out
zarf package inspect prints the package metadata and component list. With --sbom-out, Zarf writes the SBOM out to a directory you can compare against your policy.
CLI alternative
opencenter-airgap verify <package> runs the integrity checks built into src/opencenter_build/verifier.py:PackageVerifier (checksum + signature). It does not enforce SBOM policy today, which is why hack/scripts/verify-package.sh exists. Use the CLI when you only need integrity, the script when you need policy gating.
opencenter-airgap verify dist/zarf-package-*.tar.zst \
--manifest dist/artifact-manifest.json
--manifest cross-checks every artifact in the package against the manifest the build wrote at the same time, and flags missing or extra entries.
Troubleshooting
-
checksum sidecar missing— the.sha256file did not travel with the package. Re-copy fromdist/. -
signature verification failed— wrong key, corrupted signature, or a re-signed package. Confirm with the publisher; do not deploy. -
N image(s) use mutable or missing tags— the build picked up an image without a pinned version. Find it by reading the failing line from the script and pin the version inconfig/components.yamlorconfig/versions.env. -
N HIGH/CRITICAL vulnerabilities reported— the SBOM scanner flagged CVEs. Patch the underlying images or pin to a fixed version.