Feat: Implementing Sigstore-A2A verification for A2A Agent Cards#355
Feat: Implementing Sigstore-A2A verification for A2A Agent Cards#355DeanKelly751 wants to merge 7 commits into
Conversation
Implement Sigstore (sigstore-a2a) bundle verification for agent cards
using the sigstore-go library with production TUF root, certificate
identity validation, and Rekor transparency log verification.
**Core Verification**
- Verify SignedAgentCard bundles using sigstore-go verify.NewVerifier
- Validate Fulcio certificate identity against expected GitHub workflow
- Confirm Rekor transparency log inclusion
- Extract SLSA provenance (repository, commit SHA) from bundles
- Support both current (attestations) and legacy (verificationMaterial) formats
- Use JCS (RFC 8785) canonicalization for artifact bytes
**Configuration**
- CLI flags: --enable-sigstore-verification, --sigstore-audit-mode,
--sigstore-certificate-identity, --sigstore-certificate-oidc-issuer
- Per-AgentCard identity override via spec.sigstoreVerification
- Support custom TUF trust roots via ConfigMap
- Staging TUF support for testing (--sigstore-staging)
**Status & Observability**
- Status fields: sigstoreBundleVerified, sigstoreIdentity, rekorLogIndex,
slsaRepository, slsaCommitSHA
- SigstoreVerified condition with reasons: SigstoreVerified,
SigstoreVerificationFailed, SigstoreVerificationFailedAudit,
SigstoreBundleNotFound
- Kubernetes Events: SigstoreVerified (Normal), SigstoreVerificationFailed
(Warning), SigstoreBundleNotFound (Warning)
- Prometheus metrics: kagenti_sigstore_verification_total{result},
kagenti_sigstore_verification_duration_seconds,
kagenti_sigstore_trusted_root_age_seconds
**Enforcement**
- Audit mode: log failures without blocking reconciliation
- Enforcement mode: reject cards with invalid/missing bundles
- NetworkPolicy integration: verified label requires both JWS and Sigstore
- Graceful adoption: absent bundles (plain agent cards) marked as Absent
**CI Integration**
- GitHub Actions workflow: .github/workflows/sign-agent-card.yml
- Uses sigstore-a2a Python library to sign example agent card
- OIDC token from GitHub Actions for keyless signing
- Publishes signed card as workflow artifact
**Helm Chart**
- New values: sigstore.enabled, sigstore.auditMode,
sigstore.certificateIdentity, sigstore.certificateOIDCIssuer,
sigstore.staging, sigstore.trustedRoot
- Manager deployment updated to pass Sigstore flags
**Testing**
- 6 integration test cases: valid bundle, absent bundle, audit mode,
enforcement mode, SLSA extraction, per-card identity override
- Unit tests for parseProvenance, parseSignedAgentCardStructure
- Example signed agent card in examples/ci-agent-card.json
**Documentation**
- Manual E2E test guide for Sigstore verification
- Inline code comments for Sigstore initialization and verification flow
- Webhook configuration comment for local testing without certificates
**Code Review Fixes**
- Add kustomize patch for webhook namespace/object selectors (W-1 HIGH)
- Include Sigstore in NetworkPolicy label propagation (P-2 MEDIUM)
- Emit Kubernetes Events for all Sigstore paths (P-3 MEDIUM)
- Handle infrastructure errors in enforcement mode (M-3 MEDIUM)
- Clear Sigstore status when verification disabled (P-6 LOW)
- Remove unused RekorURL CRD field (CRD-1 LOW)
- Allow validation webhooks to be disabled via ENABLE_WEBHOOKS=false
Signed-off-by: dekelly <dekelly@redhat.com>
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
- Split long error messages in cmd/main.go to stay under 120 char limit - Add nolint:gocyclo directive for updateAgentCardStatus (TODO: refactor) Signed-off-by: dekelly <dekelly@redhat.com>
Signed-off-by: dekelly <dekelly@redhat.com>
…ification Signed-off-by: dekelly <dekelly@redhat.com>
a6b1300 to
ec5f236
Compare
kevincogan
left a comment
There was a problem hiding this comment.
Great work on the Sigstore integration. The architecture is solid with clean use of sigstore-go, proper JCS canonicalization, good separation between the fetcher and verifier, and the audit/enforcement mode split is well thought out. Integration tests cover the key paths nicely.
Two items to address, both are quick fixes. See inline comments.
| - name: Install sigstore-a2a with pinned a2a-sdk | ||
| run: | | ||
| uv pip install --system --prerelease=allow "a2a-sdk==0.2.16" | ||
| uv pip install --system --prerelease=allow "git+https://github.com/sigstore/sigstore-a2a.git@main" |
There was a problem hiding this comment.
This installs sigstore-a2a from an unpinned @main branch. For a PR that adds supply-chain verification, the signing toolchain itself should be pinned to a specific commit SHA or tagged release. A compromised or broken main push would silently affect every CI run.
There was a problem hiding this comment.
Changed from:
uv pip install --system --prerelease=allow "git+https://github.com/sigstore/sigstore-a2a.git@main"
To:
uv pip install --system --prerelease=allow
"git+https://github.com/sigstore/sigstore-a2a.git@293f9bd"
Also I added a comment in the workflow to update periodically by checking the commit history.
| rekorURL: | ||
| description: RekorURL is reserved for custom transparency log | ||
| base URL; the operator primarily uses the trusted root material. | ||
| type: string |
There was a problem hiding this comment.
This rekorURL field exists in the Helm chart CRD but not in the Go type (SigstoreVerification in agentcard_types.go) or the generated CRD at config/crd/bases/. That means a user can set spec.sigstoreVerification.rekorURL on their AgentCard and the API server will accept it, but the operator will silently ignore it.
Either remove rekorURL from this file to match the generated CRD, or add the corresponding field to the Go type and regenerate. Since the description says "reserved," removing it until it's wired up is the safer option.
There was a problem hiding this comment.
Followed your recommendation to remove it as the safer option since it was only "reserved" and not actually wired up.
2e51891 to
63b495f
Compare
- Pin sigstore-a2a to commit SHA 293f9bd instead of @main for reproducibility - Remove non-functional rekorURL field from Helm chart CRD to match Go types Signed-off-by: dekelly <dekelly@redhat.com>
63b495f to
bca169f
Compare
What This PR Delivers
Phase 2b: Sigstore-based Agent Card Verification
Keyless Signing in CI/CD
sigstore-a2aCLI for signingCryptographic Verification
Supply Chain Provenance
Audit Trail
Graceful Adoption Mode
sigstoreBundleVerified: false)status.sigstoreBundleVerifiedfieldImplementation Details
Core Changes:
AgentCardcontroller: Added Sigstore bundle verification logicAgentCardstatus: New fields for verification state (sigstoreBundleVerified,sigstoreIdentity,rekorLogIndex, SLSA provenance)--enable-sigstore-verification,--sigstore-certificate-identity,--sigstore-certificate-oidc-issuer,--sigstore-audit-mode.github/workflows/sign-agent-card.yml- OIDC-based signing workflowVerification Flow:
signed-agent-card.json)attestations.signatureBundle, verification is attemptedConfiguration Example: