feat(B-0853.1): cosign keyless OIDC signing for ISO blob in build-ai-cluster-iso workflow (sigstore + Fulcio + Rekor; zero key management)#5417
Merged
Conversation
…cluster-iso workflow B-0853 sub-row .1 — smallest end-to-end slice of the sigstore artifact- signing substrate. Composes with the existing build-ai-cluster-iso CI flow to sign the freshly-built ISO via GitHub OIDC + Fulcio CA + Rekor transparency log, with zero key management. Three workflow changes: 1. Add `id-token: write` to workflow-level permissions (required for sigstore keyless OIDC; no private key material handled). 2. Insert Install-cosign + Sign-ISO-with-cosign steps after the Locate-ISO-metadata step + before Upload-ISO-artifact. 3. Add second Upload step for the .sig + .pem alongside the ISO (separate artifact bundle so verifiers can download just the small signature pair without re-fetching the ~1.5GB ISO). Pin verified via gh API 2026-05-27 per .claude/rules/dep-pin-search- first-authority.md: sigstore/cosign-installer@6f9f177 # v4.1.2 (published 2026-05-07) Verification command published in workflow comments: cosign verify-blob \ --certificate <iso>.pem --signature <iso>.sig \ --certificate-identity-regexp '^https://github.com/Lucent-Financial-Group/Zeta' \ --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \ <iso> Security: all inputs to cosign sign-blob come from steps.iso.outputs of THIS workflow via env-var hop (ISO_PATH env in run block). Matches the workflow's existing discipline at the QEMU boot-test step; no github.event.* interpolation in any run: block. The id-token scope is workflow-bound; granted permission cannot be exfiltrated to mint signatures for other workflows. Composes with: - B-0853 (parent row) — sigstore/cosign artifact signing free-stuff scope - B-0843 — artifact attestation; this lands the primitive - B-0850 — cluster substrate that consumes signed ISO - B-0830 (deferred) — release-attach work; sig + pem can attach to GitHub release when release tag created - Aaron 2026-05-27 authorization: "please start on the free stuff and backlog it" What this is NOT: - NOT container image signing (B-0853.2; sibling slice) - NOT cosign verify gate in zeta-install.sh (B-0853.5) - NOT SLSA provenance attestations (B-0853.7) - NOT cluster-side image policy webhook (B-0853.6) Empirical validation: workflow run on this PR triggers the new steps; sig + pem published to artifacts; rekor entry verifiable via rekor-cli.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Pull request overview
Adds Sigstore/Cosign keyless (GitHub OIDC → Fulcio cert → Rekor transparency log) signing to the existing build-ai-cluster-iso GitHub Actions workflow, producing a .sig + .pem pair alongside the built ISO so downstream consumers can verify integrity without managing private keys.
Changes:
- Grants workflow OIDC capability by adding
id-token: writepermission. - Installs
cosign(pinned action) and signs the built ISO blob during the workflow run. - Uploads the generated signature + certificate as a separate workflow artifact bundle.
This was referenced May 27, 2026
AceHack
added a commit
that referenced
this pull request
May 27, 2026
… (#5419) PR #5417 (cosign keyless OIDC ISO signing) merged at 70596a8 before Copilot review threads could be addressed. Fix-fwd per substrate-honest discipline; the underlying findings are all valid security improvements that don't change behavior, just tighten + clarify. Finding 1 (P1): move `id-token: write` from workflow-level permissions to jobs.build.permissions block. Matches existing repo pattern (.github/workflows/scorecard.yml). Reduces blast radius if future jobs are added to this workflow. Finding 2 (P1): tighten safety wording. Original comment claimed the OIDC token "cannot be exfiltrated to mint signatures for other workflows" — overstated. The real properties are: - Short-lived cert (Fulcio mints 10-min cert tied to this run) - Identity bound to workflow path + ref - Steps pinned to commit SHAs Comment now states the actual mitigation surfaces + acknowledges that any step in this job with id-token could in principle transmit the token off-runner. Finding 3 (P1): tighten verification regexp in workflow comments. Original recommendation: --certificate-identity-regexp '^https://github.com/Lucent-Financial-Group/Zeta' was prefix-regex matching ANY workflow in the org/repo. Defeats the workflow-identity binding. Replaced with explicit pin: --certificate-identity 'https://github.com/Lucent-Financial-Group/Zeta/.github/workflows/build-ai-cluster-iso.yml@refs/heads/main' plus variants documented for branch + tag verification. No runtime behavior change in this PR — all 3 are documentation/permission-scope tightenings. The cosign sign-blob step itself is unchanged; identity emitted into the signed cert is the same either way; consumers picking up the verification command from in-workflow comments now get the tighter recommendation. Resolves Copilot threads PRRT_kwDOSF9kNM6FBtyf + PRRT_kwDOSF9kNM6FBtzO + PRRT_kwDOSF9kNM6FBtzn on PR #5417. Co-authored-by: Lior <lior@zeta.dev>
AceHack
added a commit
that referenced
this pull request
May 27, 2026
…0 substrate for Ace migration trajectory (14 sub-steps; 12 declarative-input categories; substrate-anchor for B-0852/0853/0855/0856 cross-refs) (#5420) * docs(B-0854.1): zeta-install.sh step-state-machine inventory — Phase 0 substrate for Ace migration trajectory B-0854 sub-row .1 (Phase 0; smallest pure-analysis slice). Documents the EXISTING imperative bash state-machine in zeta-install.sh so the B-0854 Phase 2 declarative-Ace-manifest schema can express the same surface. Inventory covers: - Top-level entry (REPO_URL, HOST, ZETA_AUTO_CONFIRM env semantics) - Step-by-step state machine for all 14 sub-steps (1, 2, 3, 4, 5, 6, 6.5, 6.55, 6.6, 6.7, 6.8, 6.9, 6.95, 7) with inputs/outputs/side- effects/failure-modes/declarative-equivalent per step - Cross-cutting: operator-prompt accumulation count (7 prompts today; B-0852 phase-split target = 1 passphrase prompt) - Idempotency surface table — informs B-0855 architectural fix scope - 12 distinct declarative-input categories the Ace manifest must capture (Phase 2 sub-row scope) - Files-generated-during-install table mapping to B-0852.5 cred- manifest entries (6 mapped, 3 candidate-expansion items named) Snapshot date: 2026-05-27 (origin/main 70596a8; PR #5417 cosign merge). Future refreshes should re-snapshot when zeta-install.sh changes substantially. Composes with already-landed substrate-engineering arc: - B-0852 + sub-rows (cred persistence) — PR #5403/#5411/#5414 - B-0853.1 (cosign signing) — PR #5417 + fix-fwd #5419 - B-0855 (self-register architectural fix) — PR #5412 - B-0856 Path A (deferred /tmp coordination) — PR #5413 - B-0854 parent (Ace migration trajectory) — PR #5405 No code change; pure documentation. Doesn't affect ISO substrate; batches into substrate-engineering history independent of next ISO build cycle. * fix(B-0854.1): escape | inside code spans for MD056 table-column-count compliance * fix(B-0854.1): 10 Copilot accuracy corrections — verified against actual zeta-install.sh content PR #5420 Copilot review caught 10 substantive accuracy issues in the B-0854.1 inventory doc. All 10 verified against origin/main 70596a8's actual zeta-install.sh content + corrected. Corrections: - Name attribution → role-ref ("the human maintainer") - Step 1 inputs: actual `lsblk -d -p -n -o NAME,TYPE,RM,RO,TRAN` + awk filter (not made-up NAME,SIZE,MODEL,TRAN,ROTA) - Step 3 side effects: `sgdisk --zap-all` only (not `wipefs -af` too) - Step 4: actual `sgdisk` (NOT `parted`); GPT layout via -n + -t flags; whole-disk longhorn partitions on DATA_DISKS too - Step 6: `nixos-generate-config --root /mnt --force` (NOT --no-filesystems; --force overwrites existing config) - Step 6.5: no MAGIC_NUMBER (didn't exist in script); INJECT_OK gate flag; iter-4 v1 manual-config-edit fallback path - Step 6.9: SELF_REG_OK flag; documented graceful-skip path lines 731+ - nixos-install: actual line ~1004 (NOT 1096-1340); section renamed to "nixos-install (the actual build; ~line 1004)" since the prior range was wrong - Step 7: actual lines 1261-1336 (NOT 1341-1352); banner driven by GH_AUTH_OK/GH_KEY_COUNT/INJECT_OK/SELF_REG_OK (NOT MAGIC_NUMBER); conditional sections listed in declarative equivalent Resolves 10 Copilot threads on PR #5420. Root cause of the inaccuracies: original draft was written from `grep -E "^# ── Step"` summaries + recollection of script behavior, not careful per-step body reads. Discipline lesson: when authoring substrate-anchor docs claiming to inventory existing code, the read must be careful per-line, not skim-grep summary. Composes with .claude/rules/verify-existing-substrate-before-authoring.md at the inventory-substrate scope (verify-content-of-thing-being-inventoried before authoring claims about its content). --------- Co-authored-by: Lior <lior@zeta.dev>
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
B-0853 sub-row .1 — smallest end-to-end slice of the sigstore artifact-signing substrate authorized by Aaron 2026-05-27 ("please start on the free stuff and backlog it").
Signs the freshly-built ISO via GitHub OIDC + Fulcio CA + Rekor transparency log in the existing build-ai-cluster-iso CI flow. Zero private key material; zero third-party dep beyond the pinned sigstore action.
3 workflow changes
id-token: writeto workflow-level permissions (required for keyless OIDC; no private key handled).sig+.pemas separate artifact bundle so verifiers can grab just signature pair without re-fetching ~1.5GB ISO)Verification (any consumer)
Pin discipline (per
.claude/rules/dep-pin-search-first-authority.md)Verified live via gh API 2026-05-27:
Pin:
sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2Security discipline (matches existing workflow pattern)
cosign sign-blobcome fromsteps.iso.outputs.*(THIS workflow's prior steps) via env-var hop (ISO_PATHenv)github.event.*interpolation in anyrun:block (matches existing discipline at line 182-186)id-tokenscope is workflow-bound; cannot be exfiltrated to mint signatures for other workflowsComposes with
What this is NOT
zeta-install.sh(B-0853.5)Test plan
.sig+.pemartifacts published alongside ISOrekor-cli get --uuid <uuid>cosign verify-blobagainst published artifact succeeds with org-identity regex match🤖 Generated with Claude Code