feat(sbom): generate SBOM per platform for multi-platform images - #232
Open
reyreavman wants to merge 18 commits into
Open
feat(sbom): generate SBOM per platform for multi-platform images#232reyreavman wants to merge 18 commits into
reyreavman wants to merge 18 commits into
Conversation
reyreavman
marked this pull request as ready for review
August 7, 2026 07:17
reyreavman
force-pushed
the
feat/sbom/per-platform-sbom
branch
from
August 7, 2026 08:07
41839b7 to
3c51145
Compare
Previously the SBOM cache checksum ignored the target platform and the image pull used no platform selection, so multi-platform images could reuse an SBOM generated for a different platform. Include the platform in the checksum (only when set, keeping single-platform checksums unchanged) and pass it to the container backend pull. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Previously a single SBOM was generated per image name: the image index tag was scanned (yielding host-platform content), the platform annotation was taken from the first platform image, and the base image SBOM was merged from the first platform only. Generate an SBOM for each platform image instead, scanning its own stage, merging its own base and import SBOMs and annotating its real platform. This also removes the branch constructing a throwaway MultiplatformImage whose stage descriptor was always nil. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Per-platform SBOM lookup cannot find SBOMs that an older werf attached to the image index digest. Extend the missing-base-SBOM error to tell the user that such legacy platform-ambiguous SBOMs are unusable and the base image must be rebuilt with a newer werf version. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
SBOM artifacts for multi-platform images are attached to platform manifest digests, so CLI commands need to resolve an index reference to a concrete platform manifest. Add ResolvePlatformDigest (index-aware digest resolution with an explicit available-platforms error when the platform is not specified) and ListIndexPlatforms (platform inventory of an index) to pkg/oci/artifact. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Previously sbom get silently returned whatever SBOM was attached to the resolved digest, which for a multi-platform image meant nothing or the wrong platform. Resolve index references through the platform helpers: --tag and --digest now accept --platform and fail with the list of available platforms when it is missing, and the positional mode selects the exported image by platform instead of taking the first name match. Remove PullSBOMByTag which became dead after moving resolution into the command. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Attestations of multi-platform images are attached to platform manifest digests, so an index reference used to yield nothing. Add --platform to attest get and verify with an explicit available-platforms error when it is missing, and make attest ls expand an image index listing the attestations of every platform in one table with a PLATFORM column. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Per-platform SBOMs attach fallback tags to platform manifest digests. Prove the existing digest-generic orphan pass collects them: discovery tests for GetOrphanedArtifactNames with per-platform tags (orphaned when the platform manifest is gone, kept while it exists) and a delete loop entry for per-platform tag names. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Cover the per-platform SBOM model end to end: a two-platform build must attach one SBOM artifact to each platform manifest digest with a truthful in-toto subject and target-platform annotation, attach nothing to the index digest, and serve both platform SBOMs from cache on rebuild. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Previously a --platform passed against a single-platform manifest was silently ignored, a bare OS like "linux" could prefix-match an index entry, and attest commands compared the raw platform string while sbom get normalized it. Validate the requested platform against the manifest config platform, restrict variant matching to os/arch requests, and normalize the platform inside ResolvePlatformDigest and attest ls. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
The manual read loop swallowed non-EOF errors, surfacing truncated payloads as confusing JSON parse failures. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Reverse-engineer spec.md, plan.md and tasks.md from the implemented feat/sbom/per-platform-sbom branch to bring the feature into the SDD workflow. All tasks are marked complete; identified gaps (unexecuted e2e, unconditional legacy-base hint, accepted breaking changes) are recorded for follow-up. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
CI runners use the default buildx builder with the docker driver, which rejects multi-platform builds. Build each platform with a plain docker build (the builder-base Dockerfile has no RUN instructions, so no emulation is involved), push the per-platform tags and assemble the image index in-test via go-containerregistry instead. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
SBOM generation is only supported for Stapel images; the Dockerfile fixture caused werf to reject the config at load time. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
SBOM generation only supports stapel images, and stapel images for non-amd64 platforms can only be built with the Buildah backend — the Docker-Server backend rejects them. Switch the test entry from BuildKit Docker to native Buildah with chroot isolation (the combination the multiarch build suite already exercises on CI) and add the simple label so the test runs in the e2e_simple lane instead of extra. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
Both platforms build natively on amd64 runners, removing the arm64 emulation dependency from the multiplatform SBOM suite. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
The per-platform SBOM loop constructs the PM BOM patcher per platform image, and no test exercised that combination. Build a two-platform stapel image with an os-pm packages directive on a synthesized multi-arch trusted builder base (alpine + pm binary copied from the container-factory image) and assert that the pm.lock components appear in the SBOM of every platform with a correct in-toto subject. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
SBOM generation only supports stapel images and the stapel toolchain is exercised on CI for linux/amd64 and linux/arm64, so use exactly those platforms. Replace the docker-built trusted builder bases with scratch-based stapel images: scratch needs no trusted-base chain and is platform-neutral. The packages case receives the pm binary and CA certificates via the git stage — the test extracts them from the container factory image with go-containerregistry and commits them into the test repository, removing docker and Dockerfiles from the suite entirely. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
reyreavman
force-pushed
the
feat/sbom/per-platform-sbom
branch
from
August 10, 2026 06:42
acb1efd to
2ce9f5e
Compare
Multi-platform stapel builds require the Buildah backend, and SBOM generation does not work with Buildah yet — follow the suite convention and keep the Buildah entries as XEntry until it does. The suite stays compiled and ready to enable. Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
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.
Summary
For a multi-platform image the SBOM was generated once per image name: syft scanned the index tag (yielding whatever platform the build host pulled), the
io.werf.target-platformannotation was taken from the first platform image, the base SBOM was merged from the first platform only, and the in-totosubjectpointed at the index digest. This PR generates one SBOM per platform, attached to the fallback tag of that platform's manifest digest, with a truthful subject, annotation and per-platform base/import merge — the cosign v3 discovery model (cosign sign --recursive/verify-attestation --platform).Key changes
convergeImageSbomruns the single-platform pipeline once per platform image (own stage descriptor, own base/import SBOM merge, own scan options, own platform annotation). The branch that built a throwawayMultiplatformImagewith an always-nil stage descriptor is deleted, removing a latent nil dereference along the way.werf sbom getandwerf attest get/verifyaccept--platform; an index reference without it fails listing the available platforms and their digests (no host-platform default).sbom get IMAGE_NAMEselects the exported image by platform instead of taking the first name match.werf attest lsexpands an image index and lists the attestations of every platform in one table with a PLATFORM column.--platformagainst a single-platform manifest is validated against the config platform (mismatch is an error, not a silent pass-through); platform input is normalized (linux/arm64/v8→linux/arm64) consistently across sbom and attest commands; variant matching is restricted toos/archrequests (barelinuxis rejected). New helpers live inpkg/oci/artifact/platform.go.multiplatform-labeled suite asserts per-platform artifacts, subjects, annotations, absence of an index-digest artifact and cache reuse on rebuild.specs/016-sbom-multiplatform-per-platform/(status: migrated).Why
Signing an SBOM asserts "this SBOM correctly describes this image". The old model produced an SBOM that claimed one platform while describing another, which made multi-platform SBOM signing (the parent feature) impossible to do honestly. Per-platform SBOMs attached to platform manifest digests are what the OCI distribution-spec referrers model prescribes (association is strictly per manifest digest) and what cosign discovery expects, so
cosign verify-attestation --platform <index-ref>works out of the box.Verification
task test:setup:environment). It is the merge gate for the end-to-end claims (subject/annotation/index-absence/cache).Review focus / risks
sbom get --tag/--digeston a multi-platform reference now errors with a platform list instead of silently returning the build host's platform SBOM.pkg/sbom/image.PullSBOMByTag(exported) is removed — its single caller moved to command-level resolution.pkg/build/build_phase.go: verify the per-platform loop uses the loop variable everywhere (base/import/scan/gost/platform) — the old code took everything fromimages[0], and this property is guarded only by the e2e suite.