feat(bundler): add headless OIDC paths for bundle --attest#707
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
Coverage Report ✅
Coverage BadgeMerging this branch changes the coverage (1 decrease, 1 increase)
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. |
28ed036 to
65d37c3
Compare
65d37c3 to
6c5056d
Compare
6c5056d to
2de8cc2
Compare
2de8cc2 to
5e45c12
Compare
5e45c12 to
501f2b3
Compare
dd2d8b1 to
07ee015
Compare
mchmarny
left a comment
There was a problem hiding this comment.
Solid refactor — pulling source-precedence logic into attestation.ResolveAttester and keeping pkg/cli as a thin shim is the right shape, and the resolver tests cover the four-tier precedence well. CI is fully green.
One medium concern: the new selectAttester returns resolver errors as-is, dropping the previous "; remove --attest to skip" guidance — worth restoring at the CLI layer so headless users who hit a 5-min device-flow timeout know the escape hatch.
Other findings are low/nit: secret-via---identity-token flag visible in ps, chainsaw verification-prompt grep coupling the smoke test to live Sigstore reachability, and a couple of construction/timing-constant nits in oidc.go. Nothing blocks merge once the medium item is addressed (or explicitly punted).
07ee015 to
a3f0b60
Compare
Summary
Add two non-breaking OIDC paths to
bundle --attestso it works on headless hosts:--identity-token(withCOSIGN_IDENTITY_TOKENenv) for pre-fetched tokens, and--oidc-device-flow(withAICR_OIDC_DEVICE_FLOWenv) for the OAuth 2.0 Device Authorization Grant.Motivation / Context
Today
bundle --attestresolves OIDC via exactly two paths: ambient GitHub Actions credentials, or an interactive browser callback bound tolocalhost:<random-port>. The interactive flow is unusable on remote build boxes, bastions, or air-gapped runners — the OIDC provider redirects tolocalhoston the laptop where the user logs in, never on the host runningaicr. Existing workarounds (SSH port-forwarding the random callback port, or runningaicron the laptop) are gymnastics.This change introduces two cosign-aligned, non-breaking auth paths so
attestation is reachable on any host. Selection precedence:
--identity-token/COSIGN_IDENTITY_TOKEN--oidc-device-flow/AICR_OIDC_DEVICE_FLOWCloses: #682
Related: N/A
Type of Change
Component(s) Affected
cmd/aicr,pkg/cli)cmd/aicrd,pkg/api,pkg/server)pkg/recipe)pkg/bundler,pkg/component/*)pkg/collector,pkg/snapshotter)pkg/validator)pkg/errors,pkg/k8s)docs/,examples/)tests/chainsaw/cli/bundle-headless-oidc-ci/)Implementation Notes
pkg/bundler/attestation/oidc.goFetchDeviceCodeOIDCTokenwraps sigstore's already-vendoredNewDeviceFlowTokenGetterForIssuer(RFC 8628). User sees a verification URL plus short code on stdout — fully headless.oauthflow.OIDConnect-with-context-deadline logic intorunOIDCConnect. BothFetchInteractiveOIDCTokenand the new device-code helper share the same goroutine/select shape.pkg/cli/bundle.go--identity-token(StringFlag,Sources: cli.EnvVars("COSIGN_IDENTITY_TOKEN")).--oidc-device-flow(BoolFlag,Sources: cli.EnvVars("AICR_OIDC_DEVICE_FLOW")).selectAttesterto take*bundleCmdOptionsand walk the four-tier precedence above.Flag naming.
--oidc-device-flow(not--headless) names the mechanism, not the use case. Two paths in this PR are both headless — calling either of them--headlesswould create ambiguity. The--oidc-*namespace also matches cosign and leaves room for future--oidc-issuer/--oidc-client-id.Testing
# Commands run (prefer `make qualify` for non-trivial changes) make qualifyRisk Assessment
Rollout notes:
Checklist
make testwith-race)make lint)git commit -S) — GPG signing info