feat(cli): warn before keyless signing publishes identity to public log#1300
Conversation
Warn before keyless signing publishes the signer's identity to the public Fulcio/Rekor transparency log. Add a shared --yes/--assume-yes flag to bypass the interactive confirmation for validate, evidence publish, and bundle.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Enterprise Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR adds a CLI-layer disclosure gate and documentation for keyless OIDC signing that publishes the signer's identity to Rekor. It introduces a shared Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
mchmarny
left a comment
There was a problem hiding this comment.
LGTM. Clean, well-tested, well-documented CLI-only change adding an informed-consent gate before keyless signing publishes an identity to the public Rekor log. Verified the core claims: keylessOIDCPathIsInteractive correctly mirrors ResolveOIDCToken/ResolveAttesterLazy precedence, the TTY handling matches the existing confirmOverwrite pattern, ambient OIDC fields are populated in both resolve-options helpers (so CI ambient runs bypass the gate), and none of the three commands read primary input from stdin so the scanner is safe. CI is fully green. Two non-blocking nits inline (resolver lock-step coupling, fail-open vs fail-closed asymmetry) — neither blocks merge.
…te in sync Replace the hand-mirrored OIDC source precedence in the keyless-signing disclosure gate with a shared bundleattest.SelectOIDCSource classifier (the same one ResolveOIDCToken switches on). The gate now delegates to OIDCSource.Interactive() and only adds the KMS short-circuit, so a new non-interactive source added to the resolver is reflected automatically instead of silently drifting.
Summary
Add an interactive identity-disclosure gate before keyless evidence signing: when
aicris about to open a browser/device-code OIDC login, it prints an endpoint-aware banner explaining that the signer's identity (email + issuer) will be published permanently to the public Rekor transparency log, and on a TTY pauses fory/Nconfirmation. A--yes/AICR_ASSUME_YESbypass is added for interactive automation.Motivation / Context
The evidence-signing paths (
aicr validate --emit-attestation --push,aicr evidence publish --push,aicr bundle --attest) can fall through to an interactive OIDC login that mints a Fulcio cert from the user's identity. With public-good Sigstore, that identity — typically the signer's email plus the OIDC issuer — is written to the public, immutable Rekor log (permanently searchable, cannot be deleted) and attached to the pushed OCI artifact. Previously the only hint was a couple ofslog.Infolines; there was no warning and no confirmation before the browser opened. This adds informed consent at the point of action plus the supporting docs.Fixes: #1257
Related: N/A
Type of Change
Component(s) Affected
cmd/aicr,pkg/cli)docs/,examples/)Implementation Notes
pkg/cli/signing_disclosure.go:keylessOIDCPathIsInteractivemirrorsbundleattest.ResolveOIDCToken's source precedence exactly, so the gate fires on every interactive path (browser/device-code) and never on a non-interactive one (pre-fetched--identity-token, ambient GitHub Actions OIDC, KMS--signing-key).buildKeylessSigningBanneris endpoint-aware: it names the Fulcio/Rekor URLs in effect and only claims "public, permanent, globally searchable" when the public-good Rekor is the destination; private endpoints get a softer, accurate message.confirmKeylessSigningDisclosure: on a TTY it promptsy/N(default no, clean abort — no browser, non-zero exit, mirroring the existingconfirmOverwriteTTY pattern); on non-interactive stdin it emits the banner and proceeds (fail-safe so CI/scripts are never wedged).pkg/cli(business-logic packages stay non-interactive). It runs before the browser opens in all three commands: beforeselectAttesterinbundle(lazy attester), beforeattestation.Emitinvalidate(only when--push), beforeattestation.Publishinevidence publish(always — push is required).--yes(alias--assume-yes, envAICR_ASSUME_YES) suppresses the prompt while still printing the banner.ErrCodeUnavailable, matching how the OIDC helpers classify a user-canceled login, so aborting at the consent prompt and aborting at the browser produce the same exit code.ResolveOptionsliteral inselectAttesterinto a sharedbundleOIDCResolveOptionsso the gate and the real attester reason about identical token-source inputs (no drift).Testing
pkg/clitests pass with-race; lint clean; full module builds/vets.--yesbypass, non-interactive token sources never gate, device-flow gating, and public-vs-private endpoint-aware banner. New file is ~98% covered.pkg/bundler/attestationTestNewKeyVerificationIdentity_PEMfails in my local env on a blockedtuf-repo-cdn.sigstore.devfetch — a network/environment issue unrelated to and untouched by this change.Risk Assessment
Rollout notes: Backwards compatible. CI and scripted signing (which use ambient/non-personal identities or pre-fetched tokens) never hit the gate. Interactive workstation signers see a one-time
y/Nprompt;--yes/AICR_ASSUME_YESrestores the old no-prompt behavior.Checklist
make testwith-race)make lint)git commit -S)