SPIFFE and SPIRE for Enterprise Workload Identity
Prerequisites
- Kubernetes administration basics
- PKI and mutual TLS fundamentals
Steps
SPIFFE defines a standard identity format for workloads, while SPIRE implements automated issuance and rotation of workload identities at scale. Enterprises use them to replace static secrets, strengthen zero trust, and standardize service authentication across Kubernetes, VMs, and hybrid environments.
Overview
SPIFFE, the Secure Production Identity Framework For Everyone, is an open standard for issuing cryptographically verifiable identities to workloads. A SPIFFE identity is expressed as a SPIFFE ID such as spiffe://example.org/ns/payments/sa/api, and is typically delivered as an X.509 SVID or JWT-SVID.
SPIRE, the SPIFFE Runtime Environment, is the reference implementation used to attest workloads and nodes, issue identities, and rotate credentials automatically. Enterprises adopt SPIFFE and SPIRE to eliminate long-lived service credentials, unify identity across heterogeneous platforms, and enforce mutual TLS and policy-based authorization in zero trust architectures.
Architecture
Core components
- SPIRE Server: Trust domain authority, registration authority, and CA for SVID issuance.
- SPIRE Agent: Runs on each node, performs node attestation, exposes the Workload API, and brokers workload SVIDs.
- Node attestors: Verify node identity using methods such as
k8s_psat,aws_iid, orx509pop. - Workload attestors: Identify workloads using selectors such as Kubernetes namespace, service account, pod label, Unix UID, or process metadata.
- Workload API: Unix domain socket used by applications or sidecars to fetch and rotate SVIDs.
Deployment models
- Kubernetes-native: SPIRE Server in-cluster, Agent as DaemonSet,
k8s_psatfor node attestation. - Hybrid: Central SPIRE Server with Agents on VMs and Kubernetes nodes.
- Federated trust domains: Multiple SPIRE deployments exchange trust bundles for cross-environment authentication.
Data flow
- A node starts a SPIRE Agent and completes node attestation.
- An operator creates registration entries that bind selectors to SPIFFE IDs.
- A workload connects to the local Workload API.
- The Agent validates selectors and requests an SVID from the Server.
- The workload receives a short-lived certificate or JWT and uses it for mTLS or signed service-to-service calls.
Implementation Guide
1. Install SPIRE with Helm on Kubernetes
helm repo add spiffe https://spiffe.github.io/helm-charts-hardened/
helm repo update
kubectl create namespace spire
helm install spire spiffe/spire -n spire \
--set spire-server.controllerManagerIdentity.enabled=true \
--set spire-agent.enabled=true
kubectl get pods -n spire
2. Verify server and agent health
kubectl exec -n spire deploy/spire-server -- /opt/spire/bin/spire-server healthcheck
kubectl exec -n spire ds/spire-agent -c spire-agent -- /opt/spire/bin/spire-agent healthcheck
3. Create a workload registration entry
kubectl exec -n spire deploy/spire-server -- /opt/spire/bin/spire-server entry create \
-spiffeID spiffe://corp.example/ns/prod/sa/payments-api \
-parentID spiffe://corp.example/spire/agent/k8s_psat/cluster/prod-cluster/node/.* \
-selector k8s:ns:prod \
-selector k8s:sa:payments-api
4. Configure server trust domain
server {
bind_address = "0.0.0.0"
bind_port = "8081"
trust_domain = "corp.example"
data_dir = "/run/spire/data"
log_level = "INFO"
ca_ttl = "24h"
default_x509_svid_ttl = "1h"
}
plugins {
DataStore "sql" {
plugin_data {
database_type = "postgres"
connection_string = "dbname=spire user=spire password=strongpass host=postgres.spire.svc sslmode=verify-full"
}
}
NodeAttestor "k8s_psat" {
plugin_data {
clusters = {
"prod-cluster" = {
service_account_allow_list = ["spire:spire-agent"]
}
}
}
}
}
5. Expose identities to applications
Mount the SPIRE CSI driver or Workload API socket into application pods. Applications should fetch SVIDs dynamically instead of reading static key material from secrets.
Code Examples
Bash: fetch workload identity
/opt/spire/bin/spire-agent api fetch x509 -socketPath /run/spire/sockets/agent.sock
YAML: Kubernetes workload using SPIFFE CSI
apiVersion: apps/v1
kind: Deployment
metadata:
name: payments-api
namespace: prod
spec:
replicas: 2
selector:
matchLabels:
app: payments-api
template:
metadata:
labels:
app: payments-api
spec:
serviceAccountName: payments-api
containers:
- name: app
image: ghcr.io/example/payments-api:1.4.2
volumeMounts:
- name: spiffe-workload-api
mountPath: /run/spire/sockets
readOnly: true
volumes:
- name: spiffe-workload-api
csi:
driver: csi.spiffe.io
readOnly: true
Python: read an X.509 SVID from Workload API
from pyspiffe.workloadapi import X509Source
with X509Source(socket_path="unix:///run/spire/sockets/agent.sock") as source:
svid = source.get_x509_svid()
print(svid.spiffe_id)
print(svid.cert_chain_pem.decode())
Security Hardening
- Use short SVID TTLs such as
1hor less for high-risk services. - Protect the Workload API socket with strict filesystem permissions and pod isolation.
- Store SPIRE Server state in PostgreSQL with TLS enabled and encrypted backups.
- Enable upstream authority integration with AWS PCA, Vault PKI, or enterprise CA where required.
- Restrict registration entry creation to a small admin group and audit
spire-server entrychanges. - Separate trust domains for production and non-production.
- Use federation only where cross-domain trust is required, and pin bundle endpoints.
Comparison
| Product | Pricing | Deployment | Scalability | Security |
|---|---|---|---|---|
| SPIFFE + SPIRE | Open source; infrastructure and ops cost | Kubernetes, VMs, hybrid, multi-cloud | High with clustered server and external datastore | Strong workload attestation, automatic rotation, standards-based identity |
| HashiCorp Vault PKI | Commercial for enterprise features; open source core | Broad deployment options, often central PKI model | High, but workload identity usually requires additional integration | Strong PKI and secret management, less native workload identity standardization |
| Istio | Open source; enterprise support via vendors | Primarily Kubernetes service mesh | High in large clusters, operationally heavier | Strong mTLS in-mesh, but identity is mesh-centric rather than cross-platform standard |
Troubleshooting
Error 1: node attestation failed
Log sample:
time="2025-02-14T09:12:44Z" level=error msg="Node attestation failed" error="k8s_psat: token review failed: unauthorized"
Fix: Verify the SPIRE Server has RBAC to perform TokenReview and that the cluster name in k8s_psat matches the agent configuration.
Error 2: no identity issued for workload
Log sample:
time="2025-02-14T09:18:02Z" level=warning msg="No identity issued" subsystem_name=endpoints workload_id=12345 selectors="k8s:ns:prod,k8s:sa:default"
Fix: Create or correct the registration entry so selectors exactly match the namespace and service account used by the pod.
Error 3: workload API socket unavailable
Log sample:
rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /run/spire/sockets/agent.sock: connect: no such file or directory"
Fix: Confirm the CSI driver or hostPath mount is present, and ensure the application container mounts the same socket path exposed by the SPIRE Agent.
Best Practices
Do
- Use selector-based registration tied to immutable attributes such as service account and namespace.
- Integrate SPIFFE IDs with Envoy, Istio, or custom authorization for policy decisions.
- Monitor SVID issuance, attestation failures, and agent health with centralized logging.
- Test federation in lower environments before enabling production cross-domain trust.
Don't
- Do not expose the Workload API socket to unrelated containers in the same pod.
- Do not use overly broad selectors like only
k8s:ns:prodfor sensitive workloads. - Do not keep default trust domains such as
example.orgin production. - Do not rely on SPIFFE alone for authorization; pair identity with policy engines such as OPA or Envoy RBAC.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI