SPIFFE/SPIRE on OpenShift: Building the Workload Identity Plane Your Zero-Trust Model Is Missing
After locking down human and device access, pod-to-pod communication was still trust-the-network. SPIFFE/SPIRE closes that gap. Once it's in place, access is governed by cryptographic proof at every service boundary.
Part of the Infrastructure as Evidence series, a live demonstration of the cryptographic controls FEDLIN engineers for regulated clients, built and run on FEDLIN’s own infrastructure. The FIPS 140-3 rebuild (July 1) established the cert-manager Root CA that SPIRE chains under as an intermediate.
The short version
- 1.Monitoring without enforcement creates drift. NetworkPolicies enforce by network position: namespace, label selector, port. They cannot verify what is actually running behind the source IP. SPIFFE/SPIRE adds cryptographic workload identity: the registration entry defines which SPIFFE URI a workload receives, the receiving service validates the peer certificate, and a workload that is not registered cannot obtain an SVID to present.
- 2.SPIRE and cert-manager are complementary. SPIRE chains under your existing Root CA as an intermediate, so anything already trusting your CA trusts SPIFFE identities for free, with no second trust anchor to manage.
- 3.Don't try to flip the switch cluster-wide. Control plane first, reference workloads to prove mTLS, then namespace-by-namespace. Attempting the whole cluster at once breaks running services.
- 4.The principles aren't OpenShift-specific. SPIFFE/SPIRE runs on any Kubernetes distribution. The implementation details here reflect OpenShift's security posture; the architecture decisions apply regardless of which distribution you're running.
Building the workload identity plane into the cluster made visible a structural gap that was already there: I was monitoring but not enforcing. The compliance tooling was collecting evidence that NetworkPolicies existed, but the vast majority of live policies were applied manually, outside GitOps, unreconciled, and gradually drifting from documented intent. The tooling could tell me what the network policy said. It could not stop what shouldn’t happen. If that reads as something I should have caught earlier, fair. This cluster has evolved through several infrastructure generations, the DevSecOps layer built deliberately alongside the business. Building the identity plane is what made it visible.
That is the difference between evidence and enforcement. You can document a control, collect
proof it exists, and still have no guarantee that actual service communication matches what the
policy says. As my cluster evolves (namespaces deleted, services added, policies applied ad hoc),
network-based access control drifts. The identity and access remediation had already closed
the human and device gaps: named accounts, scoped network access control rules, no standing
*:* rules. But at the workload
layer, the same problem persisted: access was still governed by network position, not identity.
SPIFFE/SPIRE is the mechanism that makes the access policy a live,
enforced control rather than a documented one.
The gap: human identity without workload identity
There are two separate identity planes in a cluster. The human and device plane (who is accessing the cluster) was addressed in the prior remediation: the network access control layer governs which devices reach the cluster, OIDC controls which humans can authenticate. Every human access carries a named identity. No anonymous or shared entry points remain.
The workload plane answers a different question: which specific service is authorized to call which other service, and what happens when it does. Before SPIFFE/SPIRE, the enforcement mechanism for that question was the network. A pod that could reach another pod’s ClusterIP could call it. Server-side TLS proved “this is the server,” but it did not prove “this specific workload is authorized to call this endpoint.” NetworkPolicies constrain which IPs can reach which ports, but they are enforced by network position, not identity. A service cannot prove what it is; the server cannot verify the caller. NIST SP 800-207 calls this implicit trust by network location, and it is the assumption zero-trust is built to eliminate.
The compliance consequence: AC-3 (access enforcement) and SC-8 (transmission confidentiality) at the service layer are evidenced by the existence of NetworkPolicies, not enforced by verified identity. When those policies drift (and manually-applied policies do drift), the evidence and the reality diverge. SPIRE closes this structurally: a registration entry defines which SPIFFE URI a workload receives, and a workload that is not registered cannot obtain an SVID to present. The access control is in Git. Changing it requires a deliberate, auditable commit. It cannot silently drift the way a manually-applied policy can.
Issuing a workload identity and enforcing it are two separate things. SPIRE issues the credential. Something on the receiving end has to check it before allowing the call through. Both halves have to be in place before access is actually enforced rather than just documented.
What fills it
SPIFFE is the open standard for workload identity; SPIRE is the production implementation that runs on the cluster. Every registered service receives an SVID: a short-lived certificate that encodes its identity as a unique URI the rest of the cluster can verify:
spiffe://example.org/ns/payments/sa/processor
The certificate expires in one hour and rotates automatically. There are no long-lived credentials to manage or revoke.
The identity is not self-asserted. Before a service receives its certificate, SPIRE verifies that it is actually what it claims to be, running where it is supposed to be running. A service that is not registered cannot obtain one.
How it fits the existing security stack
The non-obvious insight: SPIRE sits beneath cert-manager as an intermediate CA. Rather than running its own independent trust chain, it chains under the same Root CA that already anchors the cluster's routes, certificates, and ingress TLS. Every workload identity inherits that trust anchor automatically, with no second trust chain to distribute or maintain.
How services prove who they are
On OpenShift, attestation uses projected service account tokens validated against the Kubernetes control plane at the moment of the request. SPIRE confirms the workload's identity is currently live, not just that a token was valid at some point in the past. For a regulated cluster, the difference matters: stale identities cannot accumulate.
For each service, a registration entry defines which identity it receives. When a workload requests its certificate, SPIRE checks it against those entries. A workload that does not match what is registered cannot obtain one. The definitions live in Git alongside everything else.
Getting the identity to where it's needed
Delivering the workload identity to each pod requires care on OpenShift. The default security posture restricts how pods can access system resources, and the straightforward approach to delivering the identity socket conflicts with those restrictions.
The SPIFFE CSI driver is the correct mechanism: it delivers the identity to pods as a standard volume mount, with no elevated privileges required in the pod itself. The pod requests the volume; the driver holds the necessary access. The workload stays within the default security constraints. On OpenShift, this is the only approach that works within the default security posture.
Rolling it out without breaking anything
A cluster-wide workload identity plane cannot be switched on atomically without breaking running services. The end-state is every pod holding an SVID; the path there is phased.
Control plane. SPIRE server (chained to Root CA), agent DaemonSet, SPIFFE CSI driver. Verify the upstream intermediate is issued by cert-manager and both nodes attest.
Reference workloads. Register a client/server pair, prove SVID-based mTLS end-to-end. This is the proof-of-concept that de-risks the broader rollout.
Namespace-by-namespace. Add registration entries and CSI socket mounts incrementally; promote services to require mTLS as each is verified. Don't try to do the whole cluster in one pass.
What the phased rollout produces is a cluster where AC-3 and SC-8 at the workload layer are enforced, not just evidenced. Every service-to-service call carries a verified identity. The authorization policies that govern those calls live in Git, version-controlled and reconciled automatically. They cannot silently drift.
The audit trail names the workload. The gap between what the control framework says and what the cluster actually enforces closes. That is the compliance outcome, and it is why workload identity belongs on the same infrastructure track as the PKI chain and the FIPS rebuild.
The architecture decisions here were worked through with Claude Code as an active copilot: cross-referencing the NIST 800-53 mapping, reasoning through implementation tradeoffs, running the drift audit. Identity architecture isn't new territory: a decade in enterprise IAM is what made the concepts legible. SPIRE was the implementation layer. No sensitive operational data passed through it; that work runs through local self-hosted models, in-boundary. The calls are mine.
Ready to close the workload identity gap?
FEDLIN implements the full zero-trust control stack inside your boundary: SPIFFE/SPIRE, attestation, mTLS enforcement, and NIST 800-53 control evidence wired for your actual architecture.
Subscribe to Security Insights
Get enterprise security tips, compliance guides, and best practices delivered to your inbox.