Repository navigation
ci(release): generate provenance in an isolated reusable workflow (SLSA L3) - #26
Merged
Merged
Conversation
…SA L3) Move the binary-checksums and container-image PROVENANCE attestations out of the build jobs into a new reusable workflow (attest.yml, workflow_call). A reusable workflow runs in its own context with its own OIDC identity that the build steps cannot reach — the SLSA Build L3 isolation requirement (in-job artifact attestations are L2). Provenance stays on GitHub's attestation API, so `gh attestation verify` still works; the signer-workflow is now attest.yml. - attest.yml: actions/attest (binary checksums, via an uploaded artifact) + attest-build-provenance (image, by name+digest), keyed on inputs; reuses the action SHAs already pinned in the repo. - release.yml: binary-release-assets drops in-job attest and uploads checksums.txt as an artifact; container-image-release drops in-job attest-build-provenance (keeps keyless cosign sign + syft SBOM attestation); new attest-binaries + attest-image jobs call attest.yml; the summary depends on them and points gh-attestation verify at attest.yml (cosign verify still points at release.yml, since the cosign signer is unchanged). - ghd.toml signer_workflow, stage_ghd_release_assets.py expected_signer (+ its test fixture), and release-dry-run.yml expected_signer follow the new provenance signer so ghd verification stays consistent. - README/DELETE_ME prose updated (also fixes a stale "BuildKit provenance" line left over from the melange/apko migration). SBOM attestation and the cosign image signature stay in the build job — they are separate controls, not the SLSA provenance. The tag-triggered attest path runs only on a real tag; validate with a throwaway prerelease tag before a release. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.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
Reaches SLSA Build L3 by isolating provenance generation from the build, while keeping GitHub's attestation API (
gh attestation verify) — the explicitly chosen tradeoff overslsa-github-generator(which would move provenance off GitHub's API). Follow-up to the mise (#24) and melange/apko (#25) PRs.Why this is L3
L3 over L2 requires that the signing material be unreachable by the build's user-defined steps (run isolation + signing-key isolation; it does not require hermetic builds). Today the build and
attest*run in the same job → L2. Moving the attestation into a reusable workflow (attest.yml,workflow_call) gives it its own execution context and OIDC identity that the build steps can't inject into — GitHub's documented L3 path.What changed
.github/workflows/attest.yml(new, reusable) — does the provenance signing in isolation:actions/attestfor the binary checksums (downloaded as an artifact) andactions/attest-build-provenancefor the image (byname+digest).release.yml—binary-release-assetsdrops its in-jobactions/attestand uploadschecksums.txtas an artifact;container-image-releasedrops its in-jobattest-build-provenance(keeps keyless cosign sign + syft SBOM attestation); two newattest-binaries/attest-imagejobs callattest.yml; the summary now verifies provenance againstattest.yml(cosign verify still points atrelease.yml— the signer there is unchanged).ghd.tomlsigner_workflow,stage_ghd_release_assets.pyexpected_signer(+ its unit test), andrelease-dry-run.ymlexpected_signerall move toattest.ymlsoghdverification stays consistent.Scope notes
slsa-verifier-recognized builder ID — the deliberate trade to keepgh attestation verify.Verification
stage_ghd_release_assets.pyunit tests pass with the new signer.release-dry-runon this branch (build path + the inline ghd-signer check) — green there means the restructure is sound.attest.ymlreusable workflow only runs on a realrelease.ymlinvocation (tag/dispatch), so the live attest path is validated by the throwaway prerelease-tag rehearsal we owe before the first real release — that single rehearsal now covers the melange/apko publish, cosign signing, and the L3 attestation at once.🤖 Generated with Claude Code