Skip to content

[ASI07] Inbound SPIFFE auth provider — JWT-SVID + X.509-SVID mTLS, validate against SPIRE trust bundle, authorize by SPIFFE ID (K8s) #240

Description

@initializ-mk

Problem

Forge agents authenticate inbound callers via the auth provider chain (auth.providers, first-match-wins: oidc, aws_sigv4, gcp_iap, azure_ad, http_verifier, static_token). Today, agent-to-agent and platform-to-agent auth means registering an OIDC resource app per agent in Okta — which doesn't scale to agent fleets and has no agent-native construct.

Once agents get SPIFFE identity from a managed SPIRE plane (initializ/console-next#6, forge#239), the same SVID should serve inbound: the agent presents it as its server identity, and callers that are workloads present their own SVIDs. This issue adds a spiffe inbound auth provider so caller identity is a SPIFFE ID validated against the SPIRE trust bundle — no per-agent Okta resource app.

Proposed control

A spiffe provider in the existing auth chain (analogous to the oidc provider), with two modes:

  • JWT-SVID bearer (minimal path). Caller presents a JWT-SVID (sub = caller SPIFFE ID, aud = this agent's SPIFFE ID). The agent validates it against the SPIRE trust bundle (the JWT signing keys' JWKS, rooted in the customer KMS per Modular skills architecture with trust model and security analyzer #6) — structurally the same as the current OIDC bearer flow, issuer = SPIRE. Slots into the existing bearer chain with minimal transport change.
  • X.509-SVID mTLS (fuller mode). Mutual TLS: the agent presents its SVID and requires + verifies the caller's client SVID against the trust bundle. Either terminated in-process (agent TLS server config) or by a SPIFFE-aware mesh/gateway (Istio/Envoy) that forwards the verified identity.

Common to both:

  • Trust root = SPIRE trust bundle (KMS-rooted, same root as Modular skills architecture with trust model and security analyzer #6), fetched once from the Workload API / bundle endpoint and auto-rotated; no static cert.
  • Authorize by SPIFFE ID — an allowlist/policy (e.g. only spiffe://<td>/agent/frontend may call), rather than Okta audience/scope.
  • Agent Card advertises the SPIFFE scheme in securitySchemes (via the existing PopulateSecuritySchemes derivation) so callers discover how to authenticate.
  • Hybrid via the chainspiffe for internal agent-to-agent / platform-to-agent; keep oidc for external/human callers. First-match-wins.

Scope: Kubernetes-first (SVIDs from the k8s_psat-attested SPIRE plane). JWT-SVID is the minimal deliverable; X.509 mTLS is the fuller mode.

Acceptance criteria

  • spiffe provider registered in the auth chain; selectable alongside oidc (both can be active — first-match-wins).
  • JWT-SVID validation against the SPIRE trust bundle (KMS-rooted), with bundle auto-rotation; invalid/expired/wrong-audience SVIDs are rejected with the standard auth failure (auth_fail audit event).
  • X.509-SVID mTLS mode: agent presents its SVID and verifies caller SVIDs against the bundle (in-process or mesh-terminated with forwarded identity).
  • Authorization by caller SPIFFE ID (allowlist/policy); unauthorized SPIFFE IDs are denied even with a valid SVID.
  • Agent Card advertises the SPIFFE security scheme.
  • Coexists with oidc in the chain (SPIFFE for internal callers, OIDC for external) without per-agent Okta resource apps.

Conformance test

  • TestSpiffeProvider_ValidJWTSVIDAccepted / _ExpiredOrWrongAudienceRejected
  • TestSpiffeProvider_AuthorizesBySpiffeID (valid SVID, unlisted SPIFFE ID -> denied)
  • TestAuthChain_SpiffeAndOidcCoexist

Out of scope

  • The managed SPIRE issuance plane / KMS UpstreamAuthority / attestation — initializ/console-next#6.
  • Outbound identity + audit signing (the SVID as epoch key) — forge#239.
  • Non-Kubernetes node attestation (VM/cloud IID/TPM) — future; the provider validates SVIDs regardless of how the workload was attested.
  • Rebuilding a human IdP — oidc stays in the chain for people.

References

  • Agent-side outbound + audit: forge#239 (uses the same SVID)
  • Managed SPIRE plane rooted in customer KMS: initializ/console-next#6
  • Relates to ASI07 (inter-agent communication) and ASI03 (identity).

Metadata

Metadata

Assignees

No one assigned

    Labels

    asi07OWASP ASI07forge-coreAffects the forge-core library (runtime, security, types, llm, mcp, auth)owasp-asiOWASP Top 10 for Agentic Applications 2026 conformanceplatformInitializ Platform (governance control plane) responsibilitysecuritySecurity vulnerability fixes

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions