Repository navigation
Keyless OIDC push signing for thv skill push #6307
Copy link
Copy link
Closed
Labels
enhancementNew feature or requestNew feature or requestgoPull requests that update go codePull requests that update go codeskillsSkills lifecycle managementSkills lifecycle management
Description
Summary
thv skill push can only sign with a file-based cosign key. Keyless (OIDC → Fulcio) signing returns ErrKeyRequired, and has since the signer landed. This is the last real gap in the publish story: every artifact ToolHive consumes from the catalog is keyless-signed by GitHub Actions OIDC, and the verify path handles that fine — we just can't produce one.
Deferred from v1 in #5740 and tracked as a bullet in #5899 (now closed); this gives it a home.
Why it is not just "call the keyless API"
Signing happens server-side. thv skill push is a pure HTTP client; the thv serve process does the signing. That shapes the whole design:
- A CI publisher has an ambient OIDC token, but it belongs to the job, not to the long-lived server process the CLI talks to.
- A human at a laptop gets a token through an interactive browser flow, which a daemon cannot reasonably initiate on their behalf.
- The same split already surprises people with key signing:
COSIGN_PASSWORDmust be set on the server's environment, not the user's shell. Keyless makes that sharper, because a token is short-lived and request-scoped rather than a static value an operator can export once.
So the design question is not "which sigstore API" but how a request-scoped credential reaches the signer. Options worth weighing, none obviously right:
- Forward an OIDC token from the CLI in the push request. Simple, but puts a bearer credential in an API body.
- Have the server acquire its own token from ambient credentials. Works in CI, not for a laptop.
- Sign client-side and have the server only attach. Splits the signer, but keeps the credential where it belongs.
Scope
- Keyless signing path in
container/signer(toolhive-core) — see the note below on where the code should live. - Whatever credential plumbing the chosen option needs, in
thv skill pushand the push API. - E2E against Sigstore staging, which was always paired with this in the deferral. Unit tests must stay network-free; the existing suite uses embedded TUF roots and test keys.
Notes before starting
pkg/skills/signer(toolhive) andcontainer/signer(toolhive-core) are duplicates right now. Core is the intended home and Add container/signer for cosign key-based OCI signing toolhive-core#230 merged it there; deleting the local copy is blocked only on a core release. New signing work should almost certainly go to core — confirm before writing code, it changes the shape of the work.sigstore-go/pkg/signis already a direct dependency of core and supports keyless.- Signature attachment must append to the existing
.sigmanifest, never replace it, and dedupe by verifying against the public key — ECDSA is randomised, so byte comparison never matches. See toolhive-core#230. SignOCIreturns*Result{Bundle, PayloadDigest}; the payload digest is not the artifact digest.- Interop is verified by signing with
thvand verifying with the stock cosign CLI against a localregistry:2. Our verifier accepting our own bundles proves less than it looks — that gap previously hid a bug where--keycould not read anycosign generate-key-pairoutput.
Acceptance criteria
-
thv skill pushcan sign keylessly, and the resulting artifact verifies withcosign verify --certificate-identity ... --certificate-oidc-issuer ... - The credential path is documented, including what happens when no OIDC token is available (must fail with a clear message, never silently push unsigned)
- Existing key-based signing is unchanged
- E2E against Sigstore staging; unit tests remain network-free
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestgoPull requests that update go codePull requests that update go codeskillsSkills lifecycle managementSkills lifecycle management
Activity
Push skills unsigned until keyless signing lands (#6334)
Push skills unsigned until keyless signing lands (stacklok#6334)
Plumb an identity token through skill push for keyless signing
Plumb an identity token through skill push for keyless signing
Plumb an identity token through skill push for keyless signing (#6385)
Add CLI identity-token acquisition for keyless skill push
Add CLI identity-token acquisition for keyless skill push (#6390)