Workload identity for AI
AI agents, pipelines, and MCP server callers are multiplying fast. Each one needs an identity. The question is whether that identity is a stored secret someone can steal — or something the platform itself guarantees.
The identity problem in AI
Every AI workload that calls an MCP server needs to answer one question: "Who are you?"
Traditional answers break down at scale:
| Approach | Works until... |
|---|---|
| Hardcoded API key | Someone commits it to git, or it leaks in a log |
| Shared service account secret | Two teams share a secret; audit can't tell who called what |
| Per-workload secret in env vars | You're managing hundreds of secrets across dozens of clusters |
| Private key on disk | A container image rebuild ships the key to every environment |
The pattern: every stored credential is a liability. It can be copied, shared, leaked, forgotten, or used by something other than the intended workload. And the more AI workloads you run, the worse it gets.
What workload identity changes
Workload identity flips the model: instead of giving a workload a credential it holds, you let the platform prove what the workload is.
| Traditional (stored credential) | Workload identity (SPIFFE) | |
|---|---|---|
| The workload says | "Here's my secret" | "I'm this pod, in this namespace, running this service account" |
| What happens | Anyone with the secret is the workload | The platform attests the pod's runtime attributes |
| Result | Long-lived credential that can be stolen | Short-lived token issued on demand — nothing to steal |
The difference is fundamental:
| Stored credential | Workload identity (SPIFFE) | |
|---|---|---|
| Identity source | Something you know (a secret) | Something you are (runtime attributes) |
| Can be stolen? | Yes — it's a string | No — there's nothing to copy |
| Shared across pods? | Often, yes | Never — each pod has its own SVID |
| Rotation | Manual deployment | Automatic every ~5 minutes |
| Audit trail | "A caller with secret X" | "Pod Y in namespace Z with service account W" |
| Survives container restart? | Only if re-injected | Yes — SPIRE re-attests automatically |
How SPIFFE works
SPIFFE (Secure Production Identity Framework For Everyone) is the open standard behind workload identity. SPIRE is the runtime that implements it.
The three actors
- Your pod asks the local SPIRE agent for a JWT-SVID (via unix socket)
- SPIRE agent checks the pod's runtime attributes (namespace, service account, labels, image) against registered selectors
- If the attributes match, SPIRE issues a JWT-SVID — a signed, short-lived token containing the workload's SPIFFE ID
The SVID
A JWT-SVID looks like any JWT, but its claims are platform-attested:
{
"sub": "spiffe://acme.prod/ns/ml/sa/inference-pipeline",
"aud": ["https://app.authsec.ai/oauth/token"],
"exp": 1719500000,
"iat": 1719499700
}
sub— the SPIFFE ID, uniquely identifying this workloadaud— what this SVID can be presented to (AuthSec's token endpoint)exp— expires in ~5 minutes; SPIRE auto-renews before expiry
No secret, no key, no password. The SVID's authority comes from SPIRE's attestation of the pod's runtime identity.
SPIFFE's role in the AI identity landscape
AI workloads come in three flavors. Each needs a different identity model:
1. Machine callers (pipelines, batch jobs, services)
These call MCP servers as themselves with standing permissions. SPIFFE is the strongest option:
No stored secret anywhere in the chain. The pipeline's identity is its Kubernetes identity.
2. AI agents acting for users (ID-JAG)
These act on behalf of a signed-in user. SPIFFE authenticates the agent itself; the user's identity comes from the OAuth login:
SPIFFE answers "which agent is this?" while ID-JAG answers "acting for whom?" — they're complementary, not alternatives.
3. Interactive MCP clients (Claude Desktop, Cursor)
These run on a user's machine, not in Kubernetes. SPIFFE doesn't apply — they use OAuth DCR and the user's own login. No workload identity needed.
Where each fits
| Workload type | Identity method | SPIFFE role |
|---|---|---|
| K8s pipeline / batch job | SPIFFE SVID → OAuth token | Primary identity |
| K8s service calling MCP | SPIFFE SVID → OAuth token | Primary identity |
| AI agent (K8s) for users | SPIFFE + ID-JAG | Agent identity (user identity via OAuth) |
| AI agent (non-K8s) for users | Client secret/JWT + ID-JAG | Not used |
| Interactive client (desktop) | OAuth DCR | Not used |
| CI/CD pipeline (GitHub Actions) | OIDC federation | Similar pattern (platform-attested) |
SPIFFE vs other identity approaches
vs API keys / client secrets
API keys are shared strings. Anyone who has the key is the caller. SPIFFE binds identity to the workload's runtime — nothing to share, nothing to steal.
vs private-key JWT (RFC 7523)
Private-key JWT is better than secrets (the key never crosses the wire), but the key file is still stored on disk. SPIFFE eliminates stored credentials entirely — the "key" is the pod's Kubernetes identity.
vs Kubernetes service account tokens
K8s service account tokens prove "I'm in this namespace with this service account" — similar to SPIFFE. But K8s tokens are bound to the cluster's API server; SPIFFE IDs are portable across clusters, clouds, and on-prem. SPIRE also adds richer attestation (pod labels, image hash).
vs cloud IAM (AWS IAM roles, GCP Workload Identity)
Cloud IAM is workload identity for one cloud. SPIFFE is workload identity across clouds. If you run in a single cloud, either works. If you run multi-cloud or hybrid, SPIFFE gives you one identity model everywhere.
Getting started with SPIFFE in AuthSec
Three steps, each done once:
- Deploy SPIRE in your cluster (quickstart)
- Register the trust domain in AuthSec (dashboard → Trusted Issuers → Add provider)
- Connect workloads per application (Access tab → Add access → Kubernetes workload)
Then your pods authenticate with zero stored credentials — forever.
→ Connect a Kubernetes workload (step-by-step)
Further reading
- Workload identity and SPIFFE (concepts) — the broader context: SPIFFE beyond AuthSec, federation, ecosystem
- SPIFFE SDK reference (Python) —
SpiffeWorkloadIdentityandSpiffeSvidAuthclasses - SPIFFE SDK reference (Go) — Go equivalent
- spiffe.io — the SPIFFE project and specification