Workload SVID Issuance (X.509)

How a workload obtains a cryptographic identity (an X.509-SVID) with no pre-provisioned secret — via SPIRE node attestation and workload attestation — and uses it for mTLS.

Workload
SPIRE Agent
SPIRE Server
Peer Service
Back channel (server-to-server)
Step 1 / 9SPIRE AgentSPIRE Server

AttestAgent (node attestation)

On startup the SPIRE Agent proves the identity of the node it runs on. It calls the Server's Agent API (gRPC AttestAgent) presenting node attestation data — here a Kubernetes projected service-account token (a JWT bound to the node's pod and service account). No long-lived shared secret is configured on the node; the platform itself vouches for it.

Payload
eyJhbGciOiJSUzI1NiIsImtpZCI6Ims4cy1zYS0yMDI2LTAxIiwidHlwIjoiSldUIn0.eyJhdWQiOlsic3BpcmUtc2VydmVyIl0sImV4cCI6MTc4MjAwMDAwMCwiaWF0IjoxNzgxOTk2NDAwLCJuYmYiOjE3ODE5OTY0MDAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJwcm9kIiwicG9kIjp7Im5hbWUiOiJ3ZWItN2Q5ZjhjNmI1NC0yeHFxcCIsInVpZCI6ImExYjJjM2Q0LTExMTEtMjIyMi0zMzMzLTQ0NDQ1NTU1NjY2NiJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoid2ViIiwidWlkIjoiOTk4ODc3NjYtYWFhYS1iYmJiLWNjY2MtZGRkZGVlZWVmZmZmIn19LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6cHJvZDp3ZWIifQ.3aF9mK2pQ7rX1sV8tY0wZ4bN6cH5dJ8eL1gP3iR7uT
Header
  • alg: "RS256"
  • kid: "k8s-sa-2026-01"
  • typ: "JWT"
Payload (claims)
  • aud: ["spire-server"]
  • exp: 1782000000// 2026-06-21T00:00:00.000Z
  • iat: 1781996400// 2026-06-20T23:00:00.000Z
  • nbf: 1781996400// 2026-06-20T23:00:00.000Z
  • iss: "https://kubernetes.default.svc.cluster.local"
  • kubernetes.io: {"namespace":"prod","pod":{"name":"web-7d9f8c6b54-2xqqp","uid":"a1b2c3d4-1111-2222-3333-444455556666"},"serviceaccount":{"name":"web","uid":"99887766-aaaa-bbbb-cccc-ddddeeeeffff"}}
  • sub: "system:serviceaccount:prod:web"

signature — verified by the recipient using the issuer's key (not decoded here).

aud
The token is audience-bound to `spire-server`, so it cannot be replayed against the Kubernetes API or any other audience.
iss
The cluster's token issuer. The Server's k8s_psat node attestor validates this signature against the cluster's public keys.
kubernetes.io
Pod and service-account identity the Server uses to derive the agent's node selectors and its SPIFFE ID.
exp
Projected tokens are short-lived and auto-rotated by the kubelet — there is no static credential to steal.

The secret-zero problem

Every credential a workload holds to prove its identity — an API key, a database password, a client secret — had to be delivered to it somehow. That first secret, "secret zero," is the hardest to protect: bake it into an image and it leaks; mount it from a vault and the vault needs its own credential to talk to. The problem is turtles all the way down.

SPIFFE (Secure Production Identity Framework For Everyone) breaks the regress. A workload gets a cryptographic identity — a short-lived certificate — without ever being given a secret to bootstrap it. Instead, identity is derived from what the workload is: which node it runs on, which namespace and service account, which user it executes as. SPIRE is the reference implementation that performs that derivation and issues the certificates.

The two identity documents

  • A SPIFFE ID is a URI like spiffe://example.org/ns/prod/sa/web. The part before the first path segment is the trust domain (example.org); the rest names the workload.
  • An SVID (SPIFFE Verifiable Identity Document) is the signed proof of a SPIFFE ID. This flow issues an X.509-SVID: a normal X.509 certificate whose URI SAN carries the SPIFFE ID. (SPIFFE also defines a JWT-SVID — a JWT with the ID in sub — for contexts where mTLS isn't available.)

Walking the flow

Trust is bootstrapped in two layers of attestation — proving an identity by observed facts rather than a presented secret.

  1. Node attestation — at AttestAgent (node attestation), the SPIRE Agent proves the node's identity to the SPIRE Server. Here it presents a Kubernetes projected service-account token (a JWT, audience-bound to spire-server). The platform vouches for the node; the node holds no static SPIRE secret. The Server replies (Agent SVID + bundle + entries) with the agent's own SVID, the trust bundle, and the registration entries this agent may issue.

  2. Workload attestation — at FetchX509SVID (no secret), the workload calls the Workload API over a Unix domain socket and presents nothing — no token, no password. The agent reads the caller's PID from the socket's peer credentials and, at Workload attestation (selectors), inspects the process to derive selectors (unix:uid:1000, k8s:ns:prod, k8s:sa:web). It matches those against its registration entries to decide the workload's SPIFFE ID.

The agent then obtains a signed leaf (BatchNewX509SVID → Signed X.509-SVID), delivers the certificate, private key, and bundle to the workload, and the workload uses the SVID for mTLS against the peer, which authorizes on the peer's SPIFFE ID.

Why there is no secret to steal

  • The workload generates its own private key locally; it never travels the network, and the agent signs only the public half (the CSR).
  • The workload proves identity by what it is — its kernel- and orchestrator-observed selectors — which it cannot forge and cannot leak.
  • SVIDs are short-lived (≈1 hour) and the agent pushes rotations over the streaming Workload API, so continuous rotation replaces revocation in the common case.

Security notes

  • The SPIFFE ID lives in the URI SAN, not the CN. Per the X.509-SVID spec a leaf has exactly one URI SAN and the Common Name must not be used for identity. Validators must read the URI SAN.
  • Selectors are AND-matched. An entry applies only when every one of its selectors is present on the caller. Registering broad selectors (e.g. a uid shared by many pods) over-grants identity — scope entries tightly.
  • Attestation data must be audience/replay bound. The projected service-account token is bound to spire-server; a token minted for the Kubernetes API audience must not be accepted as node attestation.
  • SPIFFE gives identity, not authorization. The peer still enforces an explicit policy over SPIFFE IDs. Mutual TLS authenticates both ends — don't treat a valid certificate as automatically authorized.
  • Validate against the trust bundle, not the network. A workload trusts a peer because its SVID chains to the trust domain CA, never because of its IP or DNS name.

Further reading