Description
aicr bundle --attest currently supports exactly two OIDC paths:
- Ambient via GitHub Actions env vars (
ACTIONS_ID_TOKEN_REQUEST_URL
ACTIONS_ID_TOKEN_REQUEST_TOKEN) — CI only.
- Interactive browser via
oauthflow.DefaultIDTokenGetter — prints
a pasteable URL but uses a redirect-callback on an ephemeral
localhost:<random-port>. After the user logs in on a laptop, the
OIDC provider tries to hit localhost:<port> on the laptop — never
on the headless box where aicr runs.
No COSIGN_IDENTITY_TOKEN / --identity-token flag, no device-code
flow, no cloud workload-identity providers.
Impact
Medium — blocks --attest on headless hosts (bastions, remote build
boxes, air-gapped runners). Workarounds exist (SSH port-forward the
random callback; run on the laptop) but all are gymnastics.
Reproduction
# On a headless box (no DISPLAY, no browser)
ssh some-headless-host
unset DISPLAY
aicr bundle --recipe recipe.yaml --output ./b --attest
# Hangs at the OAuth callback (sigstore InteractiveOIDCTimeout = 5min).
# No path forward without leaving the box.
Where
pkg/cli/bundle.go:510 — selectAttester
pkg/bundler/attestation/oidc.go
- sigstore device-code helper already vendored:
vendor/github.com/sigstore/sigstore/pkg/oauthflow/interactive.go:134
(NewDeviceFlowTokenGetterForIssuer)
Proposed Fix
Pick one or both (both are non-breaking):
A. Expose sigstore's device-code flow behind a flag/env var.
Lowest friction for new users:
// selectAttester gains a new branch before the interactive fallback:
if useDeviceFlow() {
oidcToken, err := attestation.FetchDeviceCodeOIDCToken(ctx)
...
}
User sees Go to URL ... Enter code XXXX-XXXX — fully headless.
B. Accept a pre-fetched token via COSIGN_IDENTITY_TOKEN /
--identity-token. Simpler to plumb; matches cosign upstream ergonomics.
Scope
Dedicated PR. Not stable-blocking unless scope allows — workarounds
exist. Add tests for both code paths in
pkg/bundler/attestation/oidc_test.go.
Description
aicr bundle --attestcurrently supports exactly two OIDC paths:ACTIONS_ID_TOKEN_REQUEST_URLACTIONS_ID_TOKEN_REQUEST_TOKEN) — CI only.oauthflow.DefaultIDTokenGetter— printsa pasteable URL but uses a redirect-callback on an ephemeral
localhost:<random-port>. After the user logs in on a laptop, theOIDC provider tries to hit
localhost:<port>on the laptop — neveron the headless box where
aicrruns.No
COSIGN_IDENTITY_TOKEN/--identity-tokenflag, no device-codeflow, no cloud workload-identity providers.
Impact
Medium — blocks
--atteston headless hosts (bastions, remote buildboxes, air-gapped runners). Workarounds exist (SSH port-forward the
random callback; run on the laptop) but all are gymnastics.
Reproduction
Where
pkg/cli/bundle.go:510—selectAttesterpkg/bundler/attestation/oidc.govendor/github.com/sigstore/sigstore/pkg/oauthflow/interactive.go:134(
NewDeviceFlowTokenGetterForIssuer)Proposed Fix
Pick one or both (both are non-breaking):
A. Expose sigstore's device-code flow behind a flag/env var.
Lowest friction for new users:
User sees
Go to URL ... Enter code XXXX-XXXX— fully headless.B. Accept a pre-fetched token via
COSIGN_IDENTITY_TOKEN/--identity-token. Simpler to plumb; matches cosign upstream ergonomics.Scope
Dedicated PR. Not stable-blocking unless scope allows — workarounds
exist. Add tests for both code paths in
pkg/bundler/attestation/oidc_test.go.