Skip to content

feat: UBI 9 template content (chisel->UBI9 program A2) - #1

Merged
NWarila merged 2 commits into
mainfrom
feat/ubi9-template-content
Jun 2, 2026
Merged

feat: UBI 9 template content (chisel->UBI9 program A2)#1
NWarila merged 2 commits into
mainfrom
feat/ubi9-template-content

Conversation

@NWarila

@NWarila NWarila commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Program phase A2 — UBI 9 template content

Lands the full Red Hat UBI 9 image-repo template into this repo (created empty at G2), replacing the Ubuntu-chiseled design. python tools/verify.py ci is green locally across all 14 targets.

Coupled core (one consistent contract)

File Change
containers/Dockerfile ubi-minimal builder (dnf --installroot=/rootfs, keeps /var/lib/rpm+/var/lib/dnf) → ubi-micro runtime; USER 65532; entrypoint unchanged
contracts/image-manifest.schema.json + examples/image-manifest.json schema v2: base.{builder,runtime}@sha256 + dnf.packages (drops chisel/ubuntu_series); optional application.build for from-source FIPS
tools/{generate_build_args,check_image_manifest,verify}.py kept in lockstep (UBI_MINIMAL_IMAGE/UBI_MICRO_IMAGE/DNF_PACKAGES/DNF_REPOS); rpmdb-preservation guard
tests/runtime-hardening.sh forbids shells + dnf/microdnf/rpm/yum/curl/wget; asserts rpmdb present + UBI CA bundle (/etc/pki/tls/certs/ca-bundle.crt, symlink-safe); setuid/world-writable scans; parameterized entrypoint
reusable-chisel-image-build.yamlreusable-ubi-image-build.yaml + ci.yaml uses-line

Release + evidence

  • publish-image.yaml (per-image frozen; cosign keyless SAN unchanged): cosign sign/verify --recursive; OpenSCAP DISA RHEL9 STIG (SSG v0.1.81 built from the SHA512-pinned source); Trivy + Grype (--ignore-unfixed, 0 fixable HIGH/CRITICAL); runtime-hardening; anonymous public-pull check. All uses: SHA-pinned; scanners pinned-version + checksum-verified.
  • Compliance: check_compliance_checklist.py + docs/compliance/rhel-9-stig-v2r8-applicability.md446 DISA RHEL9 STIG V2R8 requirements parsed from the primary XCCDF; EXPECTED_SOURCE_HASH=41885597…0cc518, all 4 decision classes covered.
  • renovate: UBI base digests (redhat versioning) + golang <1.26 GOFIPS140 fail-closed guard.
  • ADRs: template 0001 (adopt UBI9 / retire chisel), 0002 (compliance gate), 0003 (publish-image per-image cosign identity).

Verification

python tools/verify.py ci → all 14 targets ok (incl. new publish-workflow + compliance-checklist). Constants acquired from primary sources (DISA cyber.mil, NIST CMVP, ComplianceAsCode) and adversarially re-verified.

Gate

Image content only; no chiseled repo touched. After CI is green (actionlint, markdownlint, template-verify, and the image build + hardening self-test that actually builds the example UBI9 image), this merges. Then A3 instantiates ubi9-hashicorp-vault and ubi9-aws-signing-helper from this template.

🤖 Generated with Claude Code

Transforms the template from Ubuntu-chiseled (FROM scratch) to UBI 9
(ubi-minimal builder -> ubi-micro runtime): digest-pinned bases, the rpm
database preserved for scanners, and OpenSCAP RHEL9 STIG + Trivy + Grype gates.

Coupled core (edited as one consistent contract; verify.py is the oracle):
- containers/Dockerfile: ubi-minimal builder (dnf --installroot=/rootfs,
  keeps /var/lib/rpm + /var/lib/dnf) -> ubi-micro runtime; USER 65532; entrypoint unchanged.
- manifest schema v2: base.{builder,runtime}@sha256 + dnf.packages; drops
  chisel/ubuntu_series; optional application.build for from-source FIPS images.
- generate_build_args.py / check_image_manifest.py / verify.py kept in lockstep
  (UBI_MINIMAL_IMAGE/UBI_MICRO_IMAGE/DNF_PACKAGES/DNF_REPOS).
- tests/runtime-hardening.sh: forbids shells + dnf/microdnf/rpm/yum/curl/wget;
  asserts the rpmdb is present and the UBI CA bundle is populated (symlink-safe);
  setuid + world-writable scans; entrypoint parameterized.
- reusable-chisel-image-build.yaml -> reusable-ubi-image-build.yaml (+ ci.yaml).

Release + evidence:
- publish-image.yaml (frozen per-image; cosign keyless SAN unchanged):
  cosign sign/verify --recursive; OpenSCAP DISA RHEL9 STIG (SSG v0.1.81 built
  from the SHA512-pinned source tarball); Trivy and Grype (--ignore-unfixed,
  0 fixable HIGH/CRITICAL); runtime-hardening; anonymous public-pull check.
- check_compliance_checklist.py + docs/compliance/rhel-9-stig-v2r8-applicability.md:
  446 DISA RHEL9 STIG V2R8 requirements parsed from the primary XCCDF;
  EXPECTED_SOURCE_HASH pinned to the DISA zip.
- renovate: UBI base digests (redhat versioning) + golang <1.26 GOFIPS140 guard.
- template ADRs 0001 (adopt UBI9), 0002 (compliance gate), 0003 (publish-image identity).

`python tools/verify.py ci` green locally across all 14 targets.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Comment thread containers/Dockerfile
@@ -0,0 +1,106 @@
# syntax=docker/dockerfile:1.7
…pection

The CI image-build self-test caught two real issues; both fixed and re-validated
locally with a full `docker buildx` build + runtime-hardening run:

- Dockerfile rpm-rootfs: ubi9/ubi-minimal has microdnf, not dnf (the build
  failed with `dnf: command not found`). Switch to `microdnf install
  --installroot=/rootfs` with the setopts microdnf requires for an installroot
  (--config/--noplugins/reposdir/varsdir/cachedir, --nodocs,
  install_weak_deps=0). Verified it installs ca-certificates (+deps), writes
  /rootfs/var/lib/rpm/rpmdb.sqlite (38 pkgs scanner-visible), and populates the
  CA bundle. verify.py dockerfile marker updated to `microdnf install ...`.
- tests/runtime-hardening.sh: inspect the `docker export` tar in place
  (tar -tvf for the manifest + permission scan, tar -xOf for single-file
  contents) instead of extracting the whole rootfs. Full extraction is
  unnecessary and not portable (recreating the rootfs symlinks fails off-Linux),
  while in-place inspection is identical on CI and workstations. rpmdb-present,
  symlink-safe CA-bundle, setuid, and world-writable checks all preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NWarila
NWarila merged commit 77816ba into main Jun 2, 2026
17 checks passed
@NWarila
NWarila deleted the feat/ubi9-template-content branch June 2, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants