Workload Identity Without Shared Secrets
Workloads · July 18, 2026 · 9 min read
Most access decisions in a modern estate involve no human at all. One service calls another; a job reads a bucket; a controller updates a record. If policy is written against identity, then these callers need identities — and this is the part of zero trust that is least discussed and most often still running on whatever was there before.
What was there before is usually a shared secret. An API key in a configuration file, a database password in an environment variable, a service account token mounted into a container, a certificate generated years ago with a long validity because renewing it was painful. These work. They are also the most durable weakness in the estate, and their weakness is structural rather than accidental.
Why the bearer secret is the problem
A shared secret authenticates by demonstrating knowledge. Anything holding the value is the principal, for as long as the value is accepted, from anywhere.
That yields a specific set of properties, none of them good. The secret must be distributed to reach the workload, and every step in the distribution path — the build system, the image, the configuration store, the deployment pipeline, the backup of any of those — is a place it now exists. It cannot be scoped to a caller, because the check is possession and nothing else. It cannot easily be attributed, because two workloads holding the same value produce identical evidence in the log. And it does not expire on any timescale that matters, which means the interval between theft and detection is bounded only by luck.
Rotation is supposed to bound the damage, and in practice rotation is where the model collapses. Changing a shared secret requires every holder to change at once, which requires knowing every holder, which nobody does. So rotation is deferred, and the deferral becomes permanent, and the credential ages into something the organisation is afraid to touch. Secrets that are frightening to rotate are the ones that have been in place longest and are held in the most places — precisely the inverse of what risk would dictate.
Identity you do not have to hand over
The alternative is to stop distributing secrets and start issuing credentials based on something the workload already is.
The pattern is consistent across implementations. The platform running the workload — an orchestrator, a hypervisor, a cloud control plane, an instance metadata service — knows things about it that the workload could not have told it: which image, which namespace, which node, which service account, which machine. That knowledge is the root of the identity. The workload presents evidence of its platform context to an issuing authority, the authority verifies it against the platform, and issues a short-lived credential naming the workload.
Nothing secret was placed in the workload. The identity derives from where and what it is, and it is attested by a system with independent knowledge rather than asserted by the workload itself. A copy of the image running somewhere else does not inherit it, because the platform context differs and the attestation fails.
The document format matters less than these two properties: the credential is short-lived, and it was never transported. Whether it appears as a signed token with a structured identifier or as an X.509 certificate carrying that identifier in a subject alternative name is largely an interoperability question. A namespaced, hierarchical identifier — organisation, then environment, then service — is worth insisting on regardless, because it lets policy be written against prefixes rather than enumerations, and enumerated policy is policy that stops being accurate.
Mutual TLS does two jobs, and people usually mean one
mTLS is the common transport for this, and it is worth separating what it provides, because “we use mTLS” is used to mean several different things.
It provides confidentiality and integrity on the wire, which ordinary TLS already does. Its distinctive contribution is that the client also presents a certificate, so the server learns a verified identity for the caller rather than an address. That is the part that matters here: the callee can make an authorisation decision about a named peer.
What mTLS does not provide is authorisation. A verified identity is an input; the decision about whether that identity may perform this operation on this resource is separate, and if it is not made, mTLS has produced a mesh in which every workload can prove who it is to every other workload that will still talk to anyone. Deployments frequently stop at the first half, and describe the result as zero trust, when what has been achieved is authenticated permissiveness.
The second thing mTLS does not automatically provide is short lifetimes. A client certificate with a multi-year validity, baked into an image, distributed through the build system, is a shared secret in a more respectable format. The security property comes from the issuance being automatic and frequent enough that manual rotation never has to happen — certificates measured in hours, renewed by machinery, with a private key that is generated on the workload and never leaves it.
Identity does not travel through calls
One failure mode deserves separate mention because it survives an otherwise correct implementation.
Service A receives a request from a user, authenticates it properly, and calls service B to fulfil it. Service B sees a request from service A, verifies the workload identity, and applies the policy for service A — which, because A serves many users, is broad.
The user’s authority has now vanished. B is enforcing what A is allowed to do, not what this request was allowed to do, and any flaw in A that lets an attacker influence its outbound calls converts directly into A’s full privilege at B. This is the confused deputy problem, and it does not appear in architecture diagrams, because the diagram shows two authenticated services talking.
Fixing it means carrying the original authority forward — a delegated or exchanged token that names both the calling workload and the principal on whose behalf it acts, so that B can require both. It is more work, and it is the difference between a mesh where services are authenticated and one where requests are authorised.
What good looks like
The test is unglamorous and quick. Take a running workload and ask what credential it holds, where that credential came from, how long it is valid, and what would happen if it were copied to a machine elsewhere.
If the answer is that it holds a value someone placed there, valid until further notice, which would work identically anywhere it was pasted — the estate is running on shared secrets regardless of what surrounds them.
If the answer is that it holds something it generated locally, signed by an authority that verified its platform context, expiring within hours, and useless elsewhere because the attestation would not reproduce — then the workloads have identities, and policy written against identity finally means something for the majority of traffic that no person ever sees.