Repository navigation
build: assemble the image from verified local bundles - #13
Merged
Merged
Conversation
Replace the builder-stage DNF resolution with installation of the exact locked RPM closure. `scripts/build-image.sh` re-verifies the acquired bundle, preloads the digest-pinned UBI bases, and builds with `--pull=never` and `--network none`; `scripts/install-rpm-bundle.sh` imports the approved keys, checks every digest, signature, signer, and NEVRA, and compares the installed inventory with the lock-derived manifest. Add negative evidence: `tests/rpm-bundle-negative.py` mutates isolated copies of the real bundle to prove rejection of tampering, signature removal, signer mismatch, wrong version, wrong architecture, and missing or extra RPMs, and `tests/hermetic-build-negative.sh` proves the build rejects a wrong lock identity and an unavailable base. Native CI now builds with Podman and transfers the result into Docker by local archive for the existing compatibility smoke and scanner steps.
…assembly # Conflicts: # Containerfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the remaining Package 2 build items: consume verified local bundles
with networking and pulling disabled, and prove rejection of invalid bundles.
What changes
The builder stage no longer resolves anything. It installs the exact locked
RPM closure from a verified local bundle supplied as a named build context:
scripts/build-image.shre-verifies the bundle, explicitly preloads the twodigest-pinned UBI bases, confirms they are present, and invokes Podman with
--pull=never,--network none, and the bundle as a named context.PULL_BASES=0requires the bases to be present already, for a disconnectedbuild.
scripts/install-rpm-bundle.shimports only the approved keys, checks everydigest, signature, signer key ID, and NEVRA, installs with
rpm --root, thencompares the installed inventory against the lock-derived manifest and fails
closed on any difference. It embeds the verified manifest into the image.
the closure, so the runtime has no package manager and no repo definitions.
compose.yamlno longer builds; the image is built by the script.Negative evidence
tests/rpm-bundle-negative.pymutates isolated copies of the real acquiredbundle and proves rejection of byte tampering, signature removal, signer
mismatch, wrong version, wrong architecture, missing RPMs, and extra RPMs.
It needs
rpmsign, so it runs in the native jobs rather than the unit suite.tests/hermetic-build-negative.shproves the build rejects a wrong lockidentity and cannot fetch an unavailable base.
CI
The native jobs replace the buildx build: acquire, verify, reject-invalid,
hermetic Podman build, hermetic negative checks, native Podman smoke, then
podman save/docker loadinto Docker for the existing compatibility smokeand scanner steps. That transfer performs no build and no registry pull.
Why this matters more than it looked
PR #12 found that the buildx pipeline had been green only because a cached
dnf installlayer was masking a package set the repositories no longeroffered — the pinned
nginx-corebuild had been superseded and removed, andnothing detected it. This build cannot fail that way: the lock enumerates every
RPM with its digest, installation compares the result against that lock, and
assembly runs with no network at all. A superseded upstream package becomes an
explicit validation failure instead of a silent cache hit.
This is also the first run that exercises the refreshed locks end to end —
acquire and verify through hermetic build, then Grype against the real
hermetic image.
🤖 Generated with Claude Code