Skip to content

feat(bundle): KMS-backed signing via --signing-key (#407)#1205

Merged
lockwobr merged 2 commits into
mainfrom
feat/kms-backed-signing
Jun 8, 2026
Merged

feat(bundle): KMS-backed signing via --signing-key (#407)#1205
lockwobr merged 2 commits into
mainfrom
feat/kms-backed-signing

Conversation

@lockwobr

@lockwobr lockwobr commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds aicr bundle --attest --signing-key <kms-uri> to sign bundles with a cloud-KMS-backed key (AWS / GCP / Azure KMS) instead of keyless OIDC, for CI/CD environments that have no OIDC token.

Motivation / Context

CI environments without OIDC (Jenkins, TeamCity, internal pipelines) cannot attest bundles via keyless Fulcio signing. This adds a key-based signing path and is the foundation issue of the closed-supply-chain epic: it unblocks air-gapped signing (#409), server-side /v1/bundle signing (#1150), and KMS verification (#1152).

Fixes: #407
Related: #1149 (epic), #409, #1150, #1152

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)
  • Build/CI/tooling

Component(s) Affected

  • CLI (cmd/aicr, pkg/cli)
  • API server (cmd/aicrd, pkg/server)
  • Recipe engine / data (pkg/recipe)
  • Bundlers (pkg/bundler, pkg/component/*)
  • Collectors / snapshotter (pkg/collector, pkg/snapshotter)
  • Validator (pkg/validator)
  • Core libraries (pkg/errors, pkg/k8s)
  • Docs/examples (docs/, examples/)

Implementation Notes

Signing is decomposed into two orthogonal, composable axes consumed by a new SignStatementWith primitive in pkg/bundler/attestation:

  • SigningIdentity (identity.go): supplies the signing keypair and, for keyless, the Fulcio certificate provider. keylessIdentity uses an ephemeral key + Fulcio; kmsIdentity uses a KMS key and returns no certificate.
  • TransparencyPolicy (transparency.go): selects the Rekor transparency log, or none (the no-tlog policy is reserved for offline signing, feat(bundle): air-gapped signing with --tlog-upload=false for restricted networks #409).

SignStatement (keyless) now delegates to SignStatementWith with no behavioral change; KMSAttester pairs a KMS identity with Rekor. Key points:

  • KMS-signed bundles carry public-key verification material (no Fulcio certificate) and upload to Rekor by default, mirroring keyless.
  • The KMS keypair adapts a sigstore/sigstore KMS SignerVerifier to sigstore-go's sign.Keypair; signing passes a precomputed SHA-256 digest via options.WithDigest so there is no double-hashing (the signature verifies over sha256(data)).
  • Supported schemes: awskms://, gcpkms://, azurekms://. HashiCorp Vault (hashivault://) is intentionally excluded because its client libraries are MPL-2.0, which the project license policy disallows. (Vault/OpenBao can be supported later via sigstore's out-of-process KMS plugin, which keeps the binary MPL-free.)
  • --signing-key is mutually exclusive with --identity-token, --oidc-device-flow, and --fulcio-url; --rekor-url may be combined with it (KMS + private Rekor).
  • kms.Get failures are classified: unknown scheme (kms.ProviderNotFoundError) → ErrCodeInvalidRequest; provider init/auth/network failure → ErrCodeUnavailable (matters for the future server path, feat(server): bundle attestation for /v1/bundle (non-interactive signing) #1150).

Verification today is via cosign verify ... --key <kms-uri>; native aicr verify --key is tracked in #1152. The new sigstore KMS provider dependencies are vendored in a separate commit.

Testing

make qualify

make qualify passes (test -race, lint, e2e, scan, repo checks; 0 failed tests). New tests are fully offline (local ECDSA signer + no-tlog policy; no network/cloud/cluster):

  • pkg/bundler/attestation: 78.1% coverage; every new exported function/method covered (the key-only/no-tlog path is asserted end-to-end to produce public-key verification material with no tlog entries; classifyPublicKey fails closed on non-P256 / non-2048 keys).
  • Project-wide make test-coverage: 75.9% vs the 75% floor.
  • make scan: no new findings from the KMS provider deps. (Grype reports two pre-existing k8s.io/kubernetes advisories that arrived via the rebase onto main, unrelated to this change.)

Risk Assessment

  • Low — Isolated change, well-tested, easy to revert
  • Medium — Touches multiple components or has broader impact
  • High — Breaking change, affects critical paths, or complex rollout

Rollout notes: Additive and opt-in behind a new --signing-key flag. The keyless signing path is unchanged (it now delegates to the shared composer with identical behavior). No migration required.

Checklist

  • Tests pass locally (make test with -race)
  • Linter passes (make lint)
  • I did not skip/disable tests to make CI green
  • I added/updated tests for new functionality
  • I updated docs if user-facing behavior changed
  • Changes follow existing patterns in the codebase
  • Commits are cryptographically signed (git commit -S)

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Coverage Report ✅

Metric Value
Coverage 76.3%
Threshold 75%
Status Pass
Coverage Badge
![Coverage](https://img.shields.io/badge/coverage-76.3%25-green)

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/NVIDIA/aicr/pkg/bundler/attestation 78.40% (+9.33%) 👍
github.com/NVIDIA/aicr/pkg/cli 63.08% (+0.20%) 👍

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/NVIDIA/aicr/pkg/bundler/attestation/doc.go 0.00% (ø) 0 0 0
github.com/NVIDIA/aicr/pkg/bundler/attestation/identity.go 0.00% (ø) 0 0 0
github.com/NVIDIA/aicr/pkg/bundler/attestation/keylessidentity.go 88.89% (+88.89%) 9 (+9) 8 (+8) 1 (+1) 🌟
github.com/NVIDIA/aicr/pkg/bundler/attestation/kms.go 85.71% (+85.71%) 14 (+14) 12 (+12) 2 (+2) 🌟
github.com/NVIDIA/aicr/pkg/bundler/attestation/kmsidentity.go 75.00% (+75.00%) 20 (+20) 15 (+15) 5 (+5) 🌟
github.com/NVIDIA/aicr/pkg/bundler/attestation/kmskeypair.go 84.85% (+84.85%) 33 (+33) 28 (+28) 5 (+5) 🌟
github.com/NVIDIA/aicr/pkg/bundler/attestation/resolver.go 79.49% (+2.34%) 39 (+4) 31 (+4) 8 👍
github.com/NVIDIA/aicr/pkg/bundler/attestation/signing.go 88.31% (+23.45%) 77 (+3) 68 (+20) 9 (-17) 🌟
github.com/NVIDIA/aicr/pkg/bundler/attestation/transparency.go 100.00% (+100.00%) 6 (+6) 6 (+6) 0 🌟
github.com/NVIDIA/aicr/pkg/cli/bundle.go 54.55% (+2.14%) 198 (+11) 108 (+10) 90 (+1) 👍
github.com/NVIDIA/aicr/pkg/cli/consts.go 0.00% (ø) 0 0 0

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.

@lockwobr lockwobr force-pushed the feat/kms-backed-signing branch from fd706e2 to 38f3bcb Compare June 5, 2026 21:44
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Looking for one thing? Review this PR in Change Stack to search files, summaries, diffs, and code without losing your place.

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds KMS-backed signing support to bundle attestation as an alternative to keyless OIDC-based signing. It introduces SigningIdentity and TransparencyPolicy abstractions that separate credential acquisition (ephemeral keypair + Fulcio certificate vs. KMS-backed key) from transparency-log policy (Rekor vs. offline). The implementation includes a keyless identity that manages OIDC token and Fulcio certificate provision, a KMS identity that resolves AWS/Azure/GCP KMS URIs and adapts remote signers to Sigstore's keypair interface with strict key-type validation, and a KMSAttester that orchestrates KMS-backed attestation bundles. The signing pipeline is refactored to accept injected identities and policies, enabling reuse across keyless and key-based flows. The ResolveAttester and ResolveAttesterLazy functions short-circuit to KMS when SigningKey is provided in options. A new --signing-key CLI flag enables KMS URIs with mutual-exclusivity enforcement against keyless OIDC flags, and documentation is updated with KMS examples, applicability notes, and explicit mention that HashiCorp Vault is not supported.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • NVIDIA/aicr#1158: Both PRs extend attestation-resolver integration to thread signing configuration (RekorURL in #1158 vs. SigningKey for KMS routing here) through the attester selection logic.

Suggested reviewers

  • mchmarny
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(bundle): KMS-backed signing via --signing-key (#407)' is concise, clear, and accurately summarizes the main change—adding KMS-backed signing capability via a new CLI flag. It is directly related to the changeset's primary objective.
Description check ✅ Passed The description is comprehensive and closely related to the changeset. It explains the motivation (CI/CD without OIDC), architectural design (SigningIdentity and TransparencyPolicy), implementation details, testing approach, and risk assessment. All content is relevant to the PR's objectives and changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/kms-backed-signing

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/user/cli-reference.md (1)

1137-1143: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update --attest prerequisite text to match KMS support.

Line 1137 still states --attest requires OIDC, which conflicts with the new --signing-key KMS path documented in Line 1143 and later sections. Please reword to “requires keyless OIDC or --signing-key KMS signing material.”

As per coding guidelines, documentation should clearly reflect current behavior and avoid ambiguity.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/user/cli-reference.md` around lines 1137 - 1143, Update the `--attest`
flag description to reflect that attestation can use either keyless OIDC or a
KMS-backed key by changing the prerequisite text from "requires OIDC
authentication" to something like "requires keyless OIDC or `--signing-key` KMS
signing material"; ensure references to related flags (`--signing-key`,
`--identity-token`, `--oidc-device-flow`, `--fulcio-url`, `--rekor-url`) remain
consistent with the new wording so the doc no longer implies OIDC is the only
option.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/bundler/attestation/kmsidentity.go`:
- Around line 61-90: Wrap the remote KMS I/O in kmsIdentity.Keypair with a
bounded context using context.WithTimeout (use the default timeout from
pkg/defaults, e.g. defaults.DefaultIOTimeout), ensure you call cancel() with
defer, and use that derived ctx for both kms.Get(k.keyURI, ...) and for
sv.PublicKey(options.WithContext(...)); keep the existing error-wrapping logic
but replace uses of the incoming ctx for I/O with the new timed context to
prevent indefinite hangs.

In `@pkg/bundler/attestation/signing.go`:
- Around line 125-133: The call to id.Keypair(ctx) happens before creating the
bounded signCtx, so keypair resolution can block past
defaults.SigstoreSignTimeout; change the code to derive the timeout context
first (use context.WithTimeout(ctx, defaults.SigstoreSignTimeout) to create
signCtx and defer cancel) and pass signCtx into id.Keypair(...) so both key
resolution and subsequent Fulcio/Rekor calls honor the same deadline (keep
existing cancel defer and use the same signCtx for later operations).
- Around line 115-140: SignStatementWith currently dereferences the id and tlog
interfaces (calling id.Keypair, id.CertProvider and tlog.Logs) without guarding
for nil, which can cause a panic; add nil checks at the start of
SignStatementWith to validate id and tlog (and any values returned by
id.CertProvider() if applicable) and return a structured invalid-request error
(errors.New(errors.ErrCodeInvalidRequest, "...")) when they are nil instead of
proceeding to call Keypair, CertProvider or Logs. Ensure the checks reference
the same symbols (SignStatementWith, id, tlog, Keypair, CertProvider, Logs) so
the logic runs before any method invocation.

In `@pkg/cli/bundle.go`:
- Around line 348-350: The handler currently only uses cmd.IsSet(flagSigningKey)
to detect presence but doesn’t reject an explicitly provided empty signing key;
update the logic around flagSigningKey in the function that reads the flag (the
block using cmd.IsSet(flagSigningKey)) to also check the flag value (e.g., value
:= cmd.Flag(flagSigningKey).Value.String() or equivalent) and return a non-nil
error when the flag is set but the value is empty, instead of silently falling
back to keyless resolution; ensure the error message references the
--signing-key flag for clarity.

---

Outside diff comments:
In `@docs/user/cli-reference.md`:
- Around line 1137-1143: Update the `--attest` flag description to reflect that
attestation can use either keyless OIDC or a KMS-backed key by changing the
prerequisite text from "requires OIDC authentication" to something like
"requires keyless OIDC or `--signing-key` KMS signing material"; ensure
references to related flags (`--signing-key`, `--identity-token`,
`--oidc-device-flow`, `--fulcio-url`, `--rekor-url`) remain consistent with the
new wording so the doc no longer implies OIDC is the only option.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 15766973-4079-494b-9d2d-7028d22cf8a9

📥 Commits

Reviewing files that changed from the base of the PR and between 6d2c2bf and 38f3bcb.

⛔ Files ignored due to path filters (277)
  • go.sum is excluded by !**/*.sum
  • vendor/cloud.google.com/go/.gitignore is excluded by !vendor/**
  • vendor/cloud.google.com/go/.release-please-manifest-individual.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/.release-please-manifest-submodules.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/.release-please-manifest.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/CHANGES.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/CODE_OF_CONDUCT.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/CONTRIBUTING.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/LICENSE is excluded by !vendor/**
  • vendor/cloud.google.com/go/README.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/RELEASING.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/SECURITY.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/CHANGES.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/LICENSE is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/README.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/auth.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/compute.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/detect.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/doc.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/filetypes.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/aws_provider.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/executable_provider.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/externalaccount.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/file_provider.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/info.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/programmatic_provider.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/url_provider.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/x509_provider.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/externalaccountuser/externalaccountuser.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/gdch/gdch.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/impersonate/idtoken.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/impersonate/impersonate.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/internal/stsexchange/sts_exchange.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/credentials/selfsignedjwt.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/grpctransport/dial_socketopt.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/grpctransport/directpath.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/grpctransport/pool.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/httptransport/httptransport.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/httptransport/transport.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/compute/compute.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/compute/manufacturer.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/compute/manufacturer_linux.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/compute/manufacturer_windows.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/credsfile/credsfile.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/credsfile/filetype.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/credsfile/parse.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/internal.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/jwt/jwt.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/retry/retry.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/transport/cba.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/transport/cert/default_cert.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/transport/cert/enterprise_cert.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/transport/cert/secureconnect_cert.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/transport/cert/workload_cert.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/transport/s2a.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/transport/transport.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/trustboundary/external_accounts_config_providers.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/trustboundary/trust_boundary.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/internal/version.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/oauth2adapt/CHANGES.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/oauth2adapt/LICENSE is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/oauth2adapt/oauth2adapt.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/auth/threelegged.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/CHANGES.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/LICENSE is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/README.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/log.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/metadata.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/retry.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/retry_linux.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/syscheck.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/syscheck_linux.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/compute/metadata/syscheck_windows.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/debug.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/doc.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/iam/.repo-metadata.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/iam/CHANGES.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/iam/LICENSE is excluded by !vendor/**
  • vendor/cloud.google.com/go/iam/README.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/iam/apiv1/iampb/iam_policy.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/iam/apiv1/iampb/iam_policy_grpc.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/iam/apiv1/iampb/options.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/iam/apiv1/iampb/policy.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/iam/apiv1/iampb/resource_policy_member.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/iam/iam.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/LICENSE is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/.repo-metadata.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/autokey_admin_client.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/autokey_client.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/auxiliary.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/auxiliary_go123.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/doc.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/ekm_client.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/gapic_metadata.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/helpers.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/hsm_management_client.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/iam.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/key_management_client.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/autokey.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/autokey_admin.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/autokey_admin_grpc.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/autokey_grpc.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/ekm_service.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/ekm_service_grpc.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/hsm_management.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/hsm_management_grpc.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/resources.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/service.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/kmspb/service_grpc.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/kms/apiv1/version.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/kms/internal/version.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/CHANGES.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/LICENSE is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/README.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/.repo-metadata.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/auxiliary.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/auxiliary_go123.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/doc.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/from_conn.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/gapic_metadata.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/helpers.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/info.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/longrunningpb/operations.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/longrunningpb/operations_grpc.pb.go is excluded by !**/*.pb.go, !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/operations_client.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/autogen/version.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/internal/version.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/longrunning.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/longrunning/tidyfix.go is excluded by !vendor/**
  • vendor/cloud.google.com/go/migration.md is excluded by !vendor/**
  • vendor/cloud.google.com/go/release-please-config-individual.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/release-please-config-yoshi-submodules.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/release-please-config.json is excluded by !vendor/**
  • vendor/cloud.google.com/go/testing.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/LICENSE.txt is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/README.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_type.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy/policy.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/pipeline.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_register_rp.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_trace_namespace.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/runtime.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud/cloud.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/errors.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/etag.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/pipeline.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log/log.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/fake/fake.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/poller.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/log.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/errors.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_header.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_include_response.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_key_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_request_id.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_sas_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_telemetry.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_other.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_wasm.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_http_client.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming/progress.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/to/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/to/to.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing/constants.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing/tracing.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/.gitignore is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/LICENSE.txt is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/authentication_record.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_developer_cli_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_pipelines_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_powershell_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util_nonwindows.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util_windows.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/cache.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed-identity-matrix.json is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/on_behalf_of_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-post.ps1 is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-pre.ps1 is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/LICENSE.txt is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/diag/diag.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/diag/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo/errorinfo.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/exported/exported.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/log/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/log/log.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/poller/util.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/temporal/resource.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/uuid/doc.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/uuid/uuid.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/CHANGELOG.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/LICENSE.txt is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/MIGRATION.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/README.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/TROUBLESHOOTING.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/assets.json is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/build.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/ci.yml is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/client.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/constants.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/custom_client.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/models.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/models_serde.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/options.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/platform-matrix.json is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/responses.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/test-resources-post.ps1 is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/test-resources.json is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/time_unix.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/tsp-location.yaml is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys/version.go is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal/CHANGELOG.md is excluded by !vendor/**
  • vendor/github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal/LICENSE.txt is excluded by !vendor/**
📒 Files selected for processing (23)
  • .claude/skills/creating-slide-decks/skeleton.html
  • cmd/gate/chainsaw-config.yaml
  • docs/user/cli-reference.md
  • go.mod
  • pkg/bundler/attestation/doc.go
  • pkg/bundler/attestation/identity.go
  • pkg/bundler/attestation/keylessidentity.go
  • pkg/bundler/attestation/keylessidentity_test.go
  • pkg/bundler/attestation/kms.go
  • pkg/bundler/attestation/kms_test.go
  • pkg/bundler/attestation/kmsidentity.go
  • pkg/bundler/attestation/kmsidentity_test.go
  • pkg/bundler/attestation/kmskeypair.go
  • pkg/bundler/attestation/kmskeypair_test.go
  • pkg/bundler/attestation/resolver.go
  • pkg/bundler/attestation/resolver_test.go
  • pkg/bundler/attestation/signing.go
  • pkg/bundler/attestation/signing_test.go
  • pkg/bundler/attestation/transparency.go
  • pkg/bundler/attestation/transparency_test.go
  • pkg/cli/bundle.go
  • pkg/cli/bundle_test.go
  • pkg/cli/consts.go

Comment thread pkg/bundler/attestation/kmsidentity.go
Comment thread pkg/bundler/attestation/signing.go
Comment thread pkg/bundler/attestation/signing.go Outdated
Comment thread pkg/cli/bundle.go Outdated
@lockwobr lockwobr force-pushed the feat/kms-backed-signing branch from 38f3bcb to 09f273f Compare June 5, 2026 22:05

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/user/cli-reference.md`:
- Line 2001: The attestation step list currently presents OIDC token acquisition
as unconditional; update the documentation around the five-step signing flow to
make the OIDC/Keyless step conditional: when using default keyless signing (no
--signing-key flag) include the OIDC token acquisition + Sigstore/Fulcio/Rekor
steps, and when --signing-key is supplied show an alternative KMS-backed signing
flow that omits OIDC acquisition and references the --signing-key flag and the
"KMS-Backed Signing" section; also adjust nearby cross-reference to `aicr
verify` to remain valid for both flows.

In `@pkg/bundler/attestation/kmskeypair.go`:
- Around line 110-136: Update classifyPublicKey to provide a clearer hint about
supported and future RSA sizes when rejecting keys: when rsa.PublicKey size
check fails in classifyPublicKey, change the returned error text (or add a debug
log before returning) to explicitly list supported size(s) ("only 2048-bit
supported") and mention common alternatives (e.g., "RSA-3072 and RSA-4096 are
not supported but may be considered in future versions") so users know why it
failed and that larger RSA sizes exist; similarly, make the ECDSA error message
from the *ecdsa.PublicKey case explicitly state "only P-256 supported" and
include a short hint to consult docs for supported key types/sizes using the
same error/logging path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: aa5038f3-68bc-4bdb-a344-f86fa4e4a7fa

📥 Commits

Reviewing files that changed from the base of the PR and between 38f3bcb and 09f273f.

📒 Files selected for processing (22)
  • .claude/skills/creating-slide-decks/skeleton.html
  • cmd/gate/chainsaw-config.yaml
  • docs/user/cli-reference.md
  • pkg/bundler/attestation/doc.go
  • pkg/bundler/attestation/identity.go
  • pkg/bundler/attestation/keylessidentity.go
  • pkg/bundler/attestation/keylessidentity_test.go
  • pkg/bundler/attestation/kms.go
  • pkg/bundler/attestation/kms_test.go
  • pkg/bundler/attestation/kmsidentity.go
  • pkg/bundler/attestation/kmsidentity_test.go
  • pkg/bundler/attestation/kmskeypair.go
  • pkg/bundler/attestation/kmskeypair_test.go
  • pkg/bundler/attestation/resolver.go
  • pkg/bundler/attestation/resolver_test.go
  • pkg/bundler/attestation/signing.go
  • pkg/bundler/attestation/signing_test.go
  • pkg/bundler/attestation/transparency.go
  • pkg/bundler/attestation/transparency_test.go
  • pkg/cli/bundle.go
  • pkg/cli/bundle_test.go
  • pkg/cli/consts.go

Comment thread docs/user/cli-reference.md
Comment thread pkg/bundler/attestation/kmskeypair.go
@lockwobr lockwobr force-pushed the feat/kms-backed-signing branch from 09f273f to 1d4857f Compare June 5, 2026 22:33

@mchmarny mchmarny left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean refactor — the SigningIdentity × TransparencyPolicy split keeps keyless behaviorally unchanged while making KMS a single composition apart, and the error classification at kms.Get (InvalidRequest vs Unavailable) is right for the future server path. Fail-closed key-type validation (P-256 / RSA-2048 only) with explicit ed25519/RSA-4096 test coverage is solid.

A few non-blocking observations inline: two unrelated copyright-header additions worth splitting out, a dead _ string parameter on NewKeylessIdentity, per-Attest KMS RPC re-resolution worth caching before #1150, hardcoded HasRekorEntry() that #409 will want driven from tlog, and a Usage-string nit about verification still needing cosign verify --key. None block merge.

Comment thread .claude/skills/creating-slide-decks/skeleton.html
Comment thread pkg/bundler/attestation/keylessidentity.go
Comment thread pkg/bundler/attestation/kmsidentity.go
Comment thread pkg/bundler/attestation/kmsidentity.go
Comment thread pkg/cli/bundle.go Outdated
Comment thread pkg/bundler/attestation/kms.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/bundler/attestation/doc.go (1)

48-49: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Package docs still overstate certificate presence for all signing modes.

These lines state every .sigstore.json includes a certificate, but KMS signing is documented above as key-based without Fulcio cert. Please make this wording mode-agnostic.

Suggested wording
-//   - Sigstore bundle (.sigstore.json) packaging the signed envelope,
-//     certificate, and Rekor inclusion proof
+//   - Sigstore bundle (.sigstore.json) packaging the signed envelope,
+//     verification material (Fulcio certificate for keyless, public-key
+//     material for KMS), and Rekor inclusion proof

As per coding guidelines, code comments must stay accurate and helpful.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/bundler/attestation/doc.go` around lines 48 - 49, Package documentation
in doc.go inaccurately claims every .sigstore.json contains a certificate;
update the package comment in the attestation package to be mode-agnostic (e.g.,
say the Sigstore bundle may include a certificate, or a key identifier/proof
depending on signing mode such as KMS key-only signing vs. Fulcio-issued certs)
so it does not assert a certificate is always present; edit the descriptive
bullet mentioning ".sigstore.json" to use language like "may include" or
"contains a certificate or key identifier/proof depending on signing mode" to
cover both KMS key-based and Fulcio certificate-based signing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/bundler/attestation/signing_test.go`:
- Around line 282-287: Update the stale test comment above
TestSignStatementWithRejectsNilStrategies to describe that the test validates
rejection of nil signing strategies (i.e., ensures the signer/composer returns
an error when given nil strategies), replacing the current key-only/no-tlog
description; locate the block of comment text immediately preceding the
TestSignStatementWithRejectsNilStrategies function and rewrite it to succinctly
state the test's purpose (nil strategy validation) and expected behavior.

In `@pkg/cli/bundle.go`:
- Around line 336-363: validateSigningKeyExclusivity currently only checks
cmd.IsSet(...) and misses flags supplied via config; update the exclusivity
checks to use the config-aware helpers instead of IsSet: for boolean flags call
boolFlagOrConfig(cmd, flagOIDCDeviceFlow) (and boolFlagOrConfig for
flagIdentityToken if applicable) and for string flags call
stringFlagOrConfig(cmd, flagFulcioURL) when deciding conflicts, keeping the same
error messages and the existing empty-signing-key rejection (use
stringFlagOrConfig(cmd, flagSigningKey) if signing-key can also come from
config), and return the same errors when any config-derived keyless option is
present so KMS signing is not silently bypassed.

---

Outside diff comments:
In `@pkg/bundler/attestation/doc.go`:
- Around line 48-49: Package documentation in doc.go inaccurately claims every
.sigstore.json contains a certificate; update the package comment in the
attestation package to be mode-agnostic (e.g., say the Sigstore bundle may
include a certificate, or a key identifier/proof depending on signing mode such
as KMS key-only signing vs. Fulcio-issued certs) so it does not assert a
certificate is always present; edit the descriptive bullet mentioning
".sigstore.json" to use language like "may include" or "contains a certificate
or key identifier/proof depending on signing mode" to cover both KMS key-based
and Fulcio certificate-based signing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 96166589-808d-4a37-9201-73c3cb210a8d

📥 Commits

Reviewing files that changed from the base of the PR and between 09f273f and 1d4857f.

📒 Files selected for processing (22)
  • .claude/skills/creating-slide-decks/skeleton.html
  • cmd/gate/chainsaw-config.yaml
  • docs/user/cli-reference.md
  • pkg/bundler/attestation/doc.go
  • pkg/bundler/attestation/identity.go
  • pkg/bundler/attestation/keylessidentity.go
  • pkg/bundler/attestation/keylessidentity_test.go
  • pkg/bundler/attestation/kms.go
  • pkg/bundler/attestation/kms_test.go
  • pkg/bundler/attestation/kmsidentity.go
  • pkg/bundler/attestation/kmsidentity_test.go
  • pkg/bundler/attestation/kmskeypair.go
  • pkg/bundler/attestation/kmskeypair_test.go
  • pkg/bundler/attestation/resolver.go
  • pkg/bundler/attestation/resolver_test.go
  • pkg/bundler/attestation/signing.go
  • pkg/bundler/attestation/signing_test.go
  • pkg/bundler/attestation/transparency.go
  • pkg/bundler/attestation/transparency_test.go
  • pkg/cli/bundle.go
  • pkg/cli/bundle_test.go
  • pkg/cli/consts.go

Comment thread pkg/bundler/attestation/signing_test.go Outdated
Comment thread pkg/cli/bundle.go
@lockwobr lockwobr force-pushed the feat/kms-backed-signing branch from 1d4857f to 832c11f Compare June 5, 2026 23:15

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/user/cli-reference.md`:
- Line 2071: Replace the sentence "HashiCorp Vault (`hashivault://`) is not
currently supported." with a clear, permanent-licensing-based statement that
Vault is intentionally excluded due to its MPL-2.0 client libraries (e.g.,
"HashiCorp Vault (`hashivault://`) is intentionally excluded for licensing
reasons — its client libraries are MPL-2.0 and therefore not supported"). Locate
the exact string "HashiCorp Vault (`hashivault://`) is not currently supported."
in the docs and update the wording to explicitly mention "intentionally
excluded" and "MPL-2.0" so readers understand this is a deliberate, permanent
choice rather than a temporary limitation.

In `@pkg/bundler/attestation/kms.go`:
- Around line 53-56: Replace the unconditional errors.Wrap call so that upstream
structured error codes from BuildStatement are preserved: use
errors.PropagateOrWrap(err, errors.ErrCodeInternal, "failed to build attestation
statement") when handling the error returned by BuildStatement(subject,
metadata) (the variable statementJSON and the BuildStatement call are the places
to modify) so existing coded errors propagate while still adding the contextual
message.

In `@pkg/bundler/attestation/kmskeypair.go`:
- Around line 101-108: The SignData method in kmsKeypair currently wraps errors
from k.signer.SignDigest with errors.Wrap causing double-wrapping; update
kmsKeypair.SignData to use errors.PropagateOrWrap (or the package's equivalent)
when handling err returned by k.signer.SignDigest so that if the signer already
set an error code (ErrCodeUnavailable) it is propagated, otherwise the error is
wrapped with the "KMS sign failed" message; keep the same return values (sig,
digest[:], error) and only change the error handling in the SignData function.

In `@pkg/bundler/attestation/resolver_test.go`:
- Around line 149-178: Update the two tests to assert precedence by including
keyless OIDC fields alongside SigningKey: in TestResolveAttesterKMS and
TestResolveAttesterLazyKMS call ResolveAttester / ResolveAttesterLazy with
ResolveOptions that sets SigningKey to "awskms://..." and also sets one or more
keyless fields (e.g., OIDCIssuer and/or OIDCClientID) and then assert the
returned attester is still a *KMSAttester; this pins the conflict case and
ensures SigningKey takes precedence over keyless OIDC options.

In `@pkg/bundler/attestation/transparency_test.go`:
- Around line 19-40: Update the TestRekorPolicyLogs test to explicitly assert
the empty-URL fallback: when calling NewRekorPolicy("") inspect the attached log
client returned by p.Logs() (e.g., first element) and assert that its configured
base URL equals defaults.SigstoreRekorURL (or its string value), rather than
only checking the count; this ensures NewRekorPolicy sets the default Rekor URL
when given an empty string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: e2e65a84-6acb-4817-ba18-00c78a7c9d3f

📥 Commits

Reviewing files that changed from the base of the PR and between 1d4857f and 832c11f.

📒 Files selected for processing (20)
  • docs/user/cli-reference.md
  • pkg/bundler/attestation/doc.go
  • pkg/bundler/attestation/identity.go
  • pkg/bundler/attestation/keylessidentity.go
  • pkg/bundler/attestation/keylessidentity_test.go
  • pkg/bundler/attestation/kms.go
  • pkg/bundler/attestation/kms_test.go
  • pkg/bundler/attestation/kmsidentity.go
  • pkg/bundler/attestation/kmsidentity_test.go
  • pkg/bundler/attestation/kmskeypair.go
  • pkg/bundler/attestation/kmskeypair_test.go
  • pkg/bundler/attestation/resolver.go
  • pkg/bundler/attestation/resolver_test.go
  • pkg/bundler/attestation/signing.go
  • pkg/bundler/attestation/signing_test.go
  • pkg/bundler/attestation/transparency.go
  • pkg/bundler/attestation/transparency_test.go
  • pkg/cli/bundle.go
  • pkg/cli/bundle_test.go
  • pkg/cli/consts.go

Comment thread docs/user/cli-reference.md Outdated
Comment thread pkg/bundler/attestation/kms.go
Comment thread pkg/bundler/attestation/kmskeypair.go
Comment thread pkg/bundler/attestation/resolver_test.go
Comment thread pkg/bundler/attestation/transparency_test.go
@lockwobr lockwobr force-pushed the feat/kms-backed-signing branch 2 times, most recently from c8e2f5a to 9af2cb1 Compare June 8, 2026 18:11
lockwobr added 2 commits June 8, 2026 11:28
Add `aicr bundle --attest --signing-key <kms-uri>` to sign bundles with a
cloud-KMS-backed key instead of keyless OIDC, for CI/CD environments
without an OIDC token (Jenkins, internal pipelines).

Signing is decomposed into two composable axes consumed by a new
SignStatementWith primitive:
  - SigningIdentity: ephemeral key + Fulcio (keyless) or a KMS key with
    no certificate (kmsIdentity).
  - TransparencyPolicy: Rekor log, or none (reserved for #409).
SignStatement (keyless) now delegates to SignStatementWith with no
behavioral change; KMSAttester pairs a KMS identity with Rekor.

KMS-signed bundles carry public-key verification material (no Fulcio
cert) and upload to Rekor by default. Supported schemes: awskms://,
gcpkms://, azurekms://. HashiCorp Vault (hashivault://) is excluded
because its client libraries are MPL-2.0, which the license policy
disallows.

--signing-key is mutually exclusive with --identity-token,
--oidc-device-flow, and --fulcio-url; --rekor-url may be combined with it
to log to a private Rekor.

Verification today is via cosign verify with --key <kms-uri>; native
aicr verify --key is tracked in #1152.

Note: drops a debug-level "signing in-toto statement" log line whose
Fulcio/Rekor URLs are now encapsulated in the identity/policy objects.
@lockwobr lockwobr force-pushed the feat/kms-backed-signing branch from 9af2cb1 to 6f124ad Compare June 8, 2026 18:28

@mchmarny mchmarny left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full review (CodeRabbit was down). Walked through every changed pkg/bundler/attestation/*.go, pkg/cli/bundle.go, docs/user/cli-reference.md, and re-verified each open review thread against the head SHA.

All 7 outstanding comments are addressed in the code, even though the threads weren't marked resolved on GitHub:

Thread Verdict
Vault exclusion wording (CodeRabbit) cli-reference.md:2147 now reads "deliberate, ongoing exclusion… MPL-2.0"
PropagateOrWrap for BuildStatement (CodeRabbit) kms.go:56
PropagateOrWrap on SignData (CodeRabbit) kmskeypair.go:101
Precedence test pins SigningKey over keyless (CodeRabbit) resolver_test.go — both tests now include IdentityToken:"should-be-ignored" + DeviceFlow:true
Empty-URL fallback assertion (CodeRabbit) transparency_test.go — white-box assert on rekorPolicy.url == defaults.SigstoreRekorURL
HasRekorEntry driven by tlog policy (my own #409 nit) kms.go:76_, noTLog := k.tlog.(noTLogPolicy); return !noTLog
cosign verify --key hint in --signing-key Usage (my own nit) bundle.go:702

Resolving the 6 stale threads since the concerns are addressed.

One thing worth calling out beyond the comments: the new extractIssuerExtension in signing.go properly ASN.1-decodes the current Fulcio OID 1.3.6.1.4.1.57264.1.8 as a UTF8String (with trailing-byte rejection) and falls back to the legacy OID as raw bytes. The previous code treated both as raw bytes, which would have silently embedded the ASN.1 tag/length prefix in the issuer string for any Fulcio cert using the current OID. Nice quiet fix.

validateSigningKeyExclusivity correctly fixes the config-bypass concern from the earlier CodeRabbit comment — checks both cmd.IsSet (for empty-value fail-fast) and the resolved opts (catching config-sourced keyless flags). The --rekor-url deliberate omission is well-justified in the comment (enterprise "KMS key + private Rekor").

CI: all required checks green except tests / E2E still in_progress; CodeQL conclusion is neutral (informational, not blocking).

Approving. Architecture (composable SigningIdentity × TransparencyPolicy) sets up #409 and #1150 cleanly; failure-mode classification (ProviderNotFoundErrorErrCodeInvalidRequest vs. init failures → ErrCodeUnavailable) is exactly what the future server path needs.

@lockwobr lockwobr merged commit 3b8b1f3 into main Jun 8, 2026
32 checks passed
@lockwobr lockwobr deleted the feat/kms-backed-signing branch June 8, 2026 18:55
lockwobr added a commit that referenced this pull request Jun 10, 2026
Adds an end-to-end test that exercises the real awskms:// provider path for
`aicr bundle --attest --signing-key` and `aicr verify` against an emulated AWS
KMS, closing the automated-test gap for PR #1205's KMS signing feature.

Key points:
- MiniStack (https://ministack.org), an MIT-licensed token-free AWS emulator,
  replaces LocalStack, whose latest/stable images now refuse to boot without a
  paid license token. The image is pinned in .settings.yaml (never :latest).
- sigstore's awskms client hardcodes https://, so MiniStack runs with USE_SSL=1
  behind a mkcert localhost cert. Trust is handled across three planes: Go/aicr
  via the system store (mkcert CA), the aws CLI via AWS_CA_BUNDLE, and binary
  attestation against the untouched public Sigstore root.
- The bundle and verify steps pass --certificate-identity-regexp so a binary
  attested by an e2e/build-attested workflow (not on-tag) is accepted.
- mkcert is added as a pinned tool (.settings.yaml, load-versions, setup-tools,
  check-tools).
- run.sh reproduces the CI flow locally; the chainsaw suite is gated by
  --selector 'requires=ministack'.

Closes #1214
lockwobr added a commit that referenced this pull request Jun 10, 2026
Adds an end-to-end test that exercises the real awskms:// provider path for
`aicr bundle --attest --signing-key` and `aicr verify` against an emulated AWS
KMS, closing the automated-test gap for PR #1205's KMS signing feature.

Key points:
- MiniStack (https://ministack.org), an MIT-licensed token-free AWS emulator,
  replaces LocalStack, whose latest/stable images now refuse to boot without a
  paid license token. The image is pinned in .settings.yaml (never :latest).
- sigstore's awskms client hardcodes https://, so MiniStack runs with USE_SSL=1
  behind a mkcert localhost cert. Trust is handled across three planes: Go/aicr
  via the system store (mkcert CA), the aws CLI via AWS_CA_BUNDLE, and binary
  attestation against the untouched public Sigstore root.
- The bundle and verify steps pass --certificate-identity-regexp so a binary
  attested by an e2e/build-attested workflow (not on-tag) is accepted.
- mkcert is added as a pinned tool (.settings.yaml, load-versions, setup-tools,
  check-tools).
- run.sh reproduces the CI flow locally; the chainsaw suite is gated by
  --selector 'requires=ministack'.

Closes #1214
lockwobr added a commit that referenced this pull request Jun 10, 2026
Adds an end-to-end test that exercises the real awskms:// provider path for
`aicr bundle --attest --signing-key` and `aicr verify` against an emulated AWS
KMS, closing the automated-test gap for PR #1205's KMS signing feature.

Key points:
- MiniStack (https://ministack.org), an MIT-licensed token-free AWS emulator,
  replaces LocalStack, whose latest/stable images now refuse to boot without a
  paid license token. The image is pinned in .settings.yaml (never :latest).
- sigstore's awskms client hardcodes https://, so MiniStack runs with USE_SSL=1
  behind a mkcert localhost cert. Trust is handled across three planes: Go/aicr
  via the system store (mkcert CA), the aws CLI via AWS_CA_BUNDLE, and binary
  attestation against the untouched public Sigstore root.
- The bundle and verify steps pass --certificate-identity-regexp so a binary
  attested by an e2e/build-attested workflow (not on-tag) is accepted.
- mkcert is added as a pinned tool (.settings.yaml, load-versions, setup-tools,
  check-tools).
- run.sh reproduces the CI flow locally; the chainsaw suite is gated by
  --selector 'requires=ministack'.

Closes #1214
lockwobr added a commit that referenced this pull request Jun 10, 2026
Adds an end-to-end test that exercises the real awskms:// provider path for
`aicr bundle --attest --signing-key` and `aicr verify` against an emulated AWS
KMS, closing the automated-test gap for PR #1205's KMS signing feature.

Key points:
- MiniStack (https://ministack.org), an MIT-licensed token-free AWS emulator,
  replaces LocalStack, whose latest/stable images now refuse to boot without a
  paid license token. The image is pinned in .settings.yaml (never :latest).
- sigstore's awskms client hardcodes https://, so MiniStack runs with USE_SSL=1
  behind a mkcert localhost cert. Trust is handled across three planes: Go/aicr
  via the system store (mkcert CA), the aws CLI via AWS_CA_BUNDLE, and binary
  attestation against the untouched public Sigstore root.
- The bundle and verify steps pass --certificate-identity-regexp so a binary
  attested by an e2e/build-attested workflow (not on-tag) is accepted.
- mkcert is added as a pinned tool (.settings.yaml, load-versions, setup-tools,
  check-tools).
- run.sh reproduces the CI flow locally; the chainsaw suite is gated by
  --selector 'requires=ministack'.

Closes #1214
lockwobr added a commit that referenced this pull request Jun 11, 2026
Adds an end-to-end test that exercises the real awskms:// provider path for
`aicr bundle --attest --signing-key` and `aicr verify` against an emulated AWS
KMS, closing the automated-test gap for PR #1205's KMS signing feature.

Key points:
- MiniStack (https://ministack.org), an MIT-licensed token-free AWS emulator,
  replaces LocalStack, whose latest/stable images now refuse to boot without a
  paid license token. The image is pinned in .settings.yaml (never :latest).
- sigstore's awskms client hardcodes https://, so MiniStack runs with USE_SSL=1
  behind a mkcert localhost cert. Trust is handled across three planes: Go/aicr
  via the system store (mkcert CA), the aws CLI via AWS_CA_BUNDLE, and binary
  attestation against the untouched public Sigstore root.
- The bundle and verify steps pass --certificate-identity-regexp so a binary
  attested by an e2e/build-attested workflow (not on-tag) is accepted.
- mkcert is added as a pinned tool (.settings.yaml, load-versions, setup-tools,
  check-tools).
- run.sh reproduces the CI flow locally; the chainsaw suite is gated by
  --selector 'requires=ministack'.

Closes #1214
lockwobr added a commit that referenced this pull request Jun 11, 2026
Adds an end-to-end test that exercises the real awskms:// provider path for
`aicr bundle --attest --signing-key` and `aicr verify` against an emulated AWS
KMS, closing the automated-test gap for PR #1205's KMS signing feature.

Key points:
- MiniStack (https://ministack.org), an MIT-licensed token-free AWS emulator,
  replaces LocalStack, whose latest/stable images now refuse to boot without a
  paid license token. The image is pinned in .settings.yaml (never :latest).
- sigstore's awskms client hardcodes https://, so MiniStack runs with USE_SSL=1
  behind a mkcert localhost cert. Trust is handled across three planes: Go/aicr
  via the system store (mkcert CA), the aws CLI via AWS_CA_BUNDLE, and binary
  attestation against the untouched public Sigstore root.
- The bundle and verify steps pass --certificate-identity-regexp so a binary
  attested by an e2e/build-attested workflow (not on-tag) is accepted.
- mkcert is added as a pinned tool (.settings.yaml, load-versions, setup-tools,
  check-tools).
- run.sh reproduces the CI flow locally; the chainsaw suite is gated by
  --selector 'requires=ministack'.

Closes #1214
lockwobr added a commit that referenced this pull request Jun 11, 2026
Adds an end-to-end test that exercises the real awskms:// provider path for
`aicr bundle --attest --signing-key` and `aicr verify` against an emulated AWS
KMS, closing the automated-test gap for PR #1205's KMS signing feature.

Key points:
- MiniStack (https://ministack.org), an MIT-licensed token-free AWS emulator,
  replaces LocalStack, whose latest/stable images now refuse to boot without a
  paid license token. The image is pinned in .settings.yaml (never :latest).
- sigstore's awskms client hardcodes https://, so MiniStack runs with USE_SSL=1
  behind a mkcert localhost cert. Trust is handled across three planes: Go/aicr
  via the system store (mkcert CA), the aws CLI via AWS_CA_BUNDLE, and binary
  attestation against the untouched public Sigstore root.
- The bundle and verify steps pass --certificate-identity-regexp so a binary
  attested by an e2e/build-attested workflow (not on-tag) is accepted.
- mkcert is added as a pinned tool (.settings.yaml, load-versions, setup-tools,
  check-tools).
- run.sh reproduces the CI flow locally; the chainsaw suite is gated by
  --selector 'requires=ministack'.

Closes #1214
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(bundle): KMS-backed signing for CI/CD environments without OIDC

2 participants