SPIFFE/SPIRE: Workload Identity
SPIFFE (Secure Production Identity Framework for Everyone) is the CNCF standard for workload identity. SPIRE is its production-ready implementation. Together, they provide the cryptographic identity foundation that PRECINCT uses to authenticate every agent, tool, and service in the system.
Every workload in PRECINCT (agents, gateways, sidecars, and secret stores) receives a cryptographically verifiable identity through SPIFFE and SPIRE. No static secrets. No shared tokens. Identity is attested, not asserted.
Why SPIFFE for Agentic AI
AI agents are ephemeral, autonomous, and potentially adversarial. Traditional credential management (static API keys, long-lived tokens, and manually provisioned certificates) cannot keep pace with workloads that spin up, execute, and terminate in seconds. SPIFFE was designed for exactly this world.
- Platform-agnostic workload identity. SPIFFE IDs work identically across Kubernetes, VMs, bare metal, and multi-cloud environments. No vendor lock-in.
- Runtime identity issuance via attestation. Workloads prove who they are through platform-level evidence (kernel metadata, container labels, Kubernetes service accounts), not through pre-shared secrets.
- Short-lived credentials. SVIDs (SPIFFE Verifiable Identity Documents) rotate continuously, typically every hour. Compromise of a single credential has a bounded blast radius.
- Zero trust foundation. No workload is trusted by default. Every connection requires mutual authentication via mTLS, with both sides presenting a valid SVID.
- Multi-environment support. The same trust domain spans Kubernetes clusters, Docker Compose stacks, VMs, and bare-metal hosts. Agents running on a laptop and agents running in production use the same identity framework.
How It Works in PRECINCT
SPIRE operates as a two-tier system: a centralized SPIRE Server that acts as the certificate authority and registration store, and per-node SPIRE Agents that attest workloads and deliver SVIDs.
Issues and rotates SVIDs"] REG["Registration Store
Maps workloads to SPIFFE IDs"] TB["Trust Bundle Manager
Distributes root certificates"] end subgraph Node["Per-Node SPIRE Agent"] NA["Node Attestor
Proves node identity to server"] WA["Workload Attestor
Identifies local workloads via
PID, container labels, K8s SA"] SC["SVID Cache
Caches and rotates
workload SVIDs"] end subgraph Workloads["Agent Workloads"] W1["MCP Client
(DSPy Researcher)"] W2["MCP Security Gateway"] W3["SPIKE Nexus"] end CA --> |"Issues SVIDs"| SC REG --> |"Registration entries"| NA TB --> |"Trust bundles"| SC NA --> |"Node attestation"| CA WA --> |"Workload attestation"| SC SC --> |"SVID via UDS"| W1 SC --> |"SVID via UDS"| W2 SC --> |"SVID via UDS"| W3
Workloads consume SVIDs through a Unix Domain Socket (UDS) exposed by the SPIRE Agent. No network call is required to obtain identity credentials; the agent delivers them locally via the Workload API.
SPIFFE ID Schema
PRECINCT follows a structured naming convention for SPIFFE IDs that encodes the workload type, framework, name, and environment into the URI path.
Naming Convention
spiffe://<trust-domain>/<workload-type>/<framework>/<name>/<environment>
Examples
| Workload | SPIFFE ID |
|---|---|
| DSPy Researcher Agent | spiffe://poc.local/agents/mcp-client/dspy-researcher/dev |
| MCP Security Gateway | spiffe://poc.local/gateways/mcp-security-gateway/dev |
| SPIKE Nexus | spiffe://poc.local/services/spike/nexus/dev |
| OPA Sidecar | spiffe://poc.local/services/opa/sidecar/dev |
The trust domain (poc.local in development, agentic-ref-arch.poc
in Kubernetes) defines the boundary of trust. Workloads in different trust domains
require explicit federation to communicate.
Docker Compose Setup
In the Docker Compose deployment, SPIRE runs as two containers: one for the server and one for the agent. A third one-shot container handles join token generation during initialization.
- SPIRE Server container: runs the registration API and certificate authority. Stores registration entries in SQLite.
-
SPIRE Agent container: attests workloads on the Docker
host using
docker:labelselectors for workload attestation. - Token Generator (one-shot init): creates a join token and passes it to the agent at startup. Exits after token delivery.
- Join token attestation: used for development environments where node attestation via platform-specific attestors is not available.
-
docker:labelselectors: the workload attestor matches running containers by their Docker labels to determine which SPIFFE ID to issue.
# Simplified excerpt from docker-compose.yaml
services:
spire-server:
image: ghcr.io/spiffe/spire-server:latest
volumes:
- ./config/spire/server.conf:/opt/spire/conf/server/server.conf
ports:
- "8081:8081"
spire-agent:
image: ghcr.io/spiffe/spire-agent:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- spire-agent-socket:/tmp/spire-agent/public
depends_on:
spire-server:
condition: service_healthy
token-generator:
image: ghcr.io/spiffe/spire-server:latest
entrypoint: ["/opt/spire/bin/spire-server", "token", "generate"]
depends_on:
spire-server:
condition: service_healthy
Kubernetes Setup
In Kubernetes, SPIRE deploys as production-grade infrastructure components within
the spire-system namespace.
-
SPIRE Server as StatefulSet: deployed in the
spire-systemnamespace with persistent storage for the datastore and generated keys. - SPIRE Agent as DaemonSet: runs on every node in the cluster, ensuring that any pod on any node can obtain an SVID.
-
k8s_psatattestation: for managed Kubernetes (EKS, GKE, AKS), the agent uses projected service account tokens for node and workload attestation. This is the recommended approach for production. -
join_tokenfallback: for Docker Desktop Kubernetes or local clusters wherek8s_psatis not available, join token attestation provides a functional alternative.
SPIFFE ID Format (Kubernetes)
spiffe://agentic-ref-arch.poc/ns/{namespace}/sa/{service-account}
This convention maps directly to Kubernetes namespaces and service accounts, making policy decisions straightforward: the SPIFFE ID encodes where the workload runs and what identity it claims.
# Deploy SPIRE into the cluster
kubectl apply -f k8s/spire/
# Verify the SPIRE Server is running
kubectl -n spire-system get statefulset spire-server
# Verify agents are running on all nodes
kubectl -n spire-system get daemonset spire-agent
Verification
After deploying SPIRE in either environment, verify that workload identities are being issued correctly.
Docker Compose
# Fetch an X.509 SVID from the agent's Workload API
docker compose exec spire-agent \
/opt/spire/bin/spire-agent api fetch x509 \
-socketPath /tmp/spire-agent/public/api.sock
# List all registered entries on the server
docker compose exec spire-server \
/opt/spire/bin/spire-server entry list
Kubernetes
# List all registration entries
kubectl -n spire-system exec -it statefulset/spire-server -- \
/opt/spire/bin/spire-server entry list
# Verify an agent's identity
kubectl -n spire-system exec -it daemonset/spire-agent -- \
/opt/spire/bin/spire-agent api fetch x509 \
-socketPath /tmp/spire-agent/public/api.sock
# Check SPIRE Server health
kubectl -n spire-system exec -it statefulset/spire-server -- \
/opt/spire/bin/spire-server healthcheck
A successful fetch x509 command returns the SVID certificate,
private key, and trust bundle. If you see SVID: followed by
a SPIFFE ID and PEM-encoded certificate, identity issuance is working.
Why Not OAuth/OIDC?
OAuth 2.0 and OpenID Connect are excellent protocols for human-facing authentication flows. However, they were designed for a fundamentally different trust model than what autonomous AI agents require. The table below summarizes the key differences.
| Dimension | OAuth/OIDC | SPIFFE |
|---|---|---|
| Provisioning model | Manual client registration; client IDs and secrets provisioned ahead of time | Automatic attestation; identity derived from platform evidence at runtime |
| Credential lifetime | Access tokens valid for minutes to hours; refresh tokens can be long-lived | SVIDs rotate continuously (typically hourly); no long-lived refresh mechanism |
| Trust model | Centralized authorization server; trust anchored in client secret possession | Decentralized attestation; trust anchored in platform-level evidence (kernel, hypervisor, K8s API) |
| Multi-hop delegation | Requires token exchange (RFC 8693) or on-behalf-of flows; complex, brittle | Native via downstream SVIDs; each hop presents its own identity |
| Ephemeral workload support | Poor; pre-registration required before workload can authenticate | Native; workloads attest and receive identity within seconds of startup |
| Human interaction required | Often requires consent screens, redirect flows, browser interaction | Fully automated; no human in the loop |
| Secret exposure risk | Client secrets and tokens are transmitted over the network and stored by clients | Private keys never leave the workload; only certificates are transmitted |
SPIFFE does not replace OAuth/OIDC for user-facing authentication. In PRECINCT, human users may authenticate via OIDC at the ingress boundary, while agent-to-agent and agent-to-tool communication uses SPIFFE/mTLS exclusively. The two protocols complement each other.