Skip to content

build: generate per-image SBOMs (CycloneDX 1.6 + SPDX 2.3)#1133

Open
bhouse-nexthop wants to merge 1 commit into
opencomputeproject:onie-modernization-2026from
bhouse-nexthop:bhouse.sbom
Open

build: generate per-image SBOMs (CycloneDX 1.6 + SPDX 2.3)#1133
bhouse-nexthop wants to merge 1 commit into
opencomputeproject:onie-modernization-2026from
bhouse-nexthop:bhouse.sbom

Conversation

@bhouse-nexthop

Copy link
Copy Markdown

Targets onie-modernization-2026. Independent — not stacked on any other modernization PR. It depends only on the CI workflow already present on onie-modernization-2026 (from #1114), applies cleanly, and its gen-sbom.py/sbom-vuln-scan.py run under python3 directly (they need python3 on the build host, not the ONIE python2→python3 port).

What this does

Adds a per-image SBOM subsystem:

  • scripts/gen-sbom.py — machine-agnostic; introspects make --eval for the enabled source-built fragments (plus boot/runtime: kernel, uClibc-ng, GCC runtime, shim, u-boot) and emits CycloneDX 1.6 (source of truth) → SPDX 2.3. Each component hash is computed from the actual downloaded tarball.
  • make/sbom.make — wires make MACHINE=<m> sbom, folded into all.
  • scripts/install-sbom-tools.sh — pins (with checksums) and self-provisions askalono / cyclonedx-cli / grype into build/sbom-tools/bin (no root; degrades gracefully offline).
  • scripts/sbom-vuln-scan.py — grype + OpenVEX (patch-mined CVEs) → Markdown table; CI runs make sbom-vuln-scan post-build and appends it to the run summary (non-gating).
  • conf/sbom/{cpe,license}-overrides.json, README.sbom, and a small build-onie.yml step.

Independence note

The SBOM hashing is deliberately independent of the sha1→sha512 checksum PR (#1132): gen-sbom.py hashes the downloaded tarball in $(DOWNLOADDIR) directly, not upstream/*.sha*.

Testing

Validated in the prior stack (CI-green: builds the SBOM and appends the vuln table to the run summary).

Emit a Software Bill of Materials alongside every image describing the
third-party software compiled from source and installed into that
machine's rootfs/initramfs, plus the boot/runtime components (kernel,
uClibc-ng, GCC runtime, bootloader).

scripts/gen-sbom.py is machine-agnostic: it introspects the build system
(make --eval) to enumerate the enabled SYSROOTDIR-installing fragments
and their final versions/tarballs/source URLs, pins each by sha256,
records applied patches as CycloneDX pedigree, and detects licenses from
the already-extracted sources via askalono (with deterministic overrides
in conf/sbom/license-overrides.json for genuinely multi-license or
hard-to-detect components).  CycloneDX 1.6 is the source of truth; SPDX
2.3 is produced from it via cyclonedx-cli (run in invariant-globalization
mode so it needs no ICU package).

make/sbom.make wires `make MACHINE=<m> sbom` and folds the SBOM into
`all`, so it is always produced.  The required tools (askalono,
cyclonedx-cli, and grype for the vulnerability scan) are pinned +
sha256-verified by scripts/install-sbom-tools.sh; when they are not
already on PATH the build provisions them into a writable build-local
prefix (build/sbom-tools/bin) without root, so a full-fidelity SBOM is
produced in any environment.  If provisioning fails (e.g. no network) the
generator degrades gracefully to a CycloneDX-only, NOASSERTION SBOM.

scripts/sbom-vuln-scan.py scans the SBOM with grype, suppresses CVEs
already fixed by ONIE patches via OpenVEX, and renders a Markdown table
(report only -- always exits 0).  The CI workflow runs `make
sbom-vuln-scan` after the build and publishes the table to the job log
and the run summary.

README.sbom documents the feature.

Signed-off-by: Brad House <bhouse@nexthop.ai>
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.

1 participant