Workload identity (SPIFFE/SPIRE)

Audience: DevOps / Platform engineers, Security architects
Time: ~25 min
Prerequisites: Custom (Kubernetes / Helm) or Kickstart Control Plane + at least one Bouncer.

Control Core v3.5 makes SPIFFE/SPIRE workload identity the default platform baseline. Every Bouncer and Control Plane component obtains a short-lived X.509 SVID, and internal traffic uses mutual TLS (mTLS) with hot certificate rotation. Static Bouncer API keys remain available only through an audited legacy flag (removed in a future major release).

TL;DR

  1. Helm chart ships SPIRE Server + Agent with global.spire.enabled: true.
  2. Bouncer env: REQUIRE_WORKLOAD_IDENTITY=true, SPIFFE_ENDPOINT_SOCKET=unix:///run/spire/sockets/agent.sock.
  3. SVIDs rotate at ≤4 hours (configurable); Bouncer SDS reloads certs in memory (0 ms downtime design).
  4. For upgrades without SPIRE on day 1: set ALLOW_LEGACY_STATIC_AUTH=true (emits SECURITY_WARNING_DEPRECATED_STATIC_AUTH_ACTIVE).

Architecture (operator view)

ComponentSPIFFE ID patternAttestor
Control Plane APIspiffe://controlcore.internal/ns/{env}/sa/control-planek8s_psat / aws_iid
Control Bridge (policy sync)spiffe://controlcore.internal/ns/{env}/sa/control-bridgek8s_psat
Bouncer PEPspiffe://controlcore.internal/ns/{env}/sa/bouncer-{id}k8s / docker / unix
PIP cachespiffe://controlcore.internal/ns/{env}/sa/pip-redis-cachek8s / systemd

Trust domain default: controlcore.internal. Override with global.spire.trustDomain / SPIFFE_TRUST_DOMAIN.

Helm values

global:
  spire:
    enabled: true
    trustDomain: "controlcore.internal"
    serverPort: 8081
    workloadSocketPath: "/run/spire/sockets/agent.sock"
    svidMaxTTLHours: 4
    requireWorkloadIdentity: true
    allowLegacyStaticAuth: false
    attestors:
      k8sPsat: true
      awsIid: true
      unix: true

Troubleshooting: If Bouncer pods crash with FATAL_SPIFFE_ATTESTATION_FAILED, confirm the SPIRE Agent DaemonSet is Ready and the socket is mounted at /run/spire/sockets/agent.sock. Check kubectl logs -l app.kubernetes.io/component=spire-agent. Common causes: Agent not scheduled on the node, wrong SPIFFE_ENDPOINT_SOCKET, or REQUIRE_WORKLOAD_IDENTITY=true before SPIRE is healthy.

Bouncer environment variables

VariableDefaultPurpose
REQUIRE_WORKLOAD_IDENTITYtrueAbort startup if Workload API unreachable
SPIFFE_ENDPOINT_SOCKETunix:///run/spire/sockets/agent.sockWorkload API UDS
SPIFFE_TRUST_DOMAINcontrolcore.internalTrust domain
SPIFFE_SVID_MAX_TTL_HOURS4Max SVID lifetime (defence may set 1)
ALLOW_LEGACY_STATIC_AUTHfalseAudited Bearer API_KEY fallback
SPIRE_ENABLEDtrue (Helm)Enable SDS mTLS + agent

Legacy Control Bridge WebSocket auth tokens are deprecated — prefer SPIFFE mTLS on the policy-sync stream.

Migration (v2.x → v3.5)

v3.5  REQUIRE_WORKLOAD_IDENTITY=true (default)
      ALLOW_LEGACY_STATIC_AUTH=false
v3.6  Legacy flag requires explicit CISO audit log
Later  Static auth engine removed
  1. Install SPIRE Server/Agent (chart default).
  2. Confirm Bouncer registers with a SPIFFE peer (Control Plane audit / PEP list).
  3. Set ALLOW_LEGACY_STATIC_AUTH=false after validation.
  4. Rotate away long-lived Bouncer API keys.

Troubleshooting: If registration fails with HTTP 401 SPIFFE workload identity required, either mount a valid SVID path or temporarily set ALLOW_LEGACY_STATIC_AUTH=true while you finish SPIRE bring-up. Legacy mode logs SECURITY_WARNING_DEPRECATED_STATIC_AUTH_ACTIVE to SIEM.

Certificate rotation monitoring

  • SPIRE Agent rotates SVIDs at 50% of TTL (e.g. every 2 hours for a 4-hour cert).
  • Bouncer pulls updates via SDS over the Workload API socket — no Bouncer restart.
  • Alert if Agent memory exceeds 64 MB or if FATAL_SPIFFE_ATTESTATION_FAILED appears in Bouncer logs.

Compliance mapping

Supports continuous identity verification for NIST SP 800-207, SOC 2 CC6.8, CCCP / CPCSC Level 3, OSFI B-13, and FIPS 140-3 crypto providers used by SPIRE.

Next steps