Credentials That Expire by Design

AWS shipped IAM Roles Anywhere last month, which means all three large clouds now let a workload trade a proof of identity for a credential with an expiry stamped on it. This is about where each of them puts the thing it will not doubt: the mechanism is nearly identical and the trust anchor underneath it is not, and whoever wires up the first workload chooses that anchor for everybody.

The Key That Never Fails

Somewhere in your organization there is a cloud access key that was created for a deployment job on an afternoon when something needed to ship, pasted into a secret store, and never touched again. It works. It has worked for years. The reason nobody has replaced it is not laziness, and it is not ignorance of the risk. It is that a credential which never expires never fails, so the system never produces a reason to go and look at it.

That property is the entire problem, and it is worth stating without the security-awareness framing. A static credential has no clock on it, so its lifetime is not a decision anybody made. It is however long it takes someone to notice. In the meantime it lives in the secret store, in the environment of every runner that consumes it, in the shell history of whoever debugged the pipeline in March, in an image layer, and in the backup of the secret store. Copying it leaves no trace, and a request made with the copy is indistinguishable from a request made with the original.

The standard answer is rotation on a schedule, and I have watched that answer fail more often than I have watched it work. Rotating a shared key is a coordinated change across every consumer of it, and the list of consumers is exactly the thing nobody has. So the rotation either breaks something at an inconvenient hour or it quietly does not happen, and the ninety-day interval on the compliance spreadsheet describes a control that is not running.

By the middle of this year all three large clouds had shipped a way out, and the interesting part is that they agree almost completely on the mechanism. A workload proves it is what it claims to be, exchanges that proof for credentials with an expiry stamped on them, and holds no long-term secret at all. Where they part company is one layer down, in what each of them is willing to treat as the thing it cannot doubt.

The Shape They All Converged On

The proof starts with something the workload could not mint. A certificate signed by a certificate authority the workload does not operate, a token issued by the platform the workload is running on, an assertion signed by an identity provider. The shared property is unforgeability from the inside: a process that has been fully compromised still cannot manufacture the thing, because the signing material was never on the machine.

The credential has an expiry printed on it. IAM Roles Anywhere sessions run from 900 seconds to 43200 seconds, fifteen minutes to twelve hours, set on the profile and capped by the role. That range is the whole security argument: a stolen credential is stolen for the rest of its window rather than forever, which turns a leak from a permanent condition into an incident with an end date you can calculate.

Authorization does not move at all. The role, the policy, the permission boundary and the service control policy stay exactly where they were. Only the authentication step changed. This is not a small detail. It is the reason any of this is adoptable, because a team can put a short-lived credential under an existing workload without reopening the argument about what that workload is allowed to do.

The secret store does not go away. You still have database passwords, vendor API keys, signing keys and everything else that no cloud is issuing on your behalf. What leaves is one class of secret, the class that grants access to your cloud account and therefore to everything else. That is a large reduction and it is not elimination, and I would rather say so now than let the sentence "we removed our secrets" out of the room.

Where the Trust Anchor Lives

AWS elected your public key infrastructure. IAM Roles Anywhere, announced on 6 July, asks you to register a certificate authority as a trust anchor. A workload then signs a CreateSession call with the private key bound to its certificate, attaches the certificate itself in a header, and gets back an ordinary temporary session. The root of trust is a CA, and whether it is AWS Private CA or one of your own, somebody in your organization owns its issuance policy.

Azure elected the platform. A managed identity is not a thing you install; the virtual machine asks a link-local address on its own network stack for a token scoped to a resource, and the platform that created the machine vouches for it. There is no key material on disk to copy, because there is no key material. You cannot inspect this trust anchor or operate it yourself, and you get it for nothing precisely because you are already trusting the same control plane with the machine's existence.

Google elected an identity provider. Workload identity federation puts a pool and a provider between an external token and a Google identity, maps the token's claims onto attributes, and evaluates a condition expression over those attributes before anything is issued. GitHub Actions has spoken the same protocol since 27 October last year, when it began minting a per-job token whose subject names the repository and the ref that is running.

So the question underneath the three products is not on-premises against cloud, and it is not certificates against tokens. It is which institution becomes the root of machine identity across the estate. Choose certificates and it is your PKI, with everything that implies about issuance and renewal and revocation. Choose federation and it is your identity provider, which already held human identity and now holds both. Neither is wrong. Both are close to irreversible by the time a hundred workloads depend on it, and neither gets discussed at the point it is chosen.

What Each Anchor Costs

The certificate route makes you a certificate authority operator, which is a real job. Something has to issue certificates to workloads, renew them before they expire, and revoke the ones that should not work anymore. Revocation is the part that gets skipped, because a revocation list only does anything if it is published, distributed and actually consulted at validation time, and none of that is automatic. The failure mode is a certificate that was withdrawn on a wiki page and continues to work.

And a certificate on disk is a file. If the private key sits in the filesystem next to the application, you have replaced a credential that never expires with one that expires in a year or two, which is better but is not the same as short-lived. The design only delivers what it promises when the key is in hardware the process can use and cannot read, and that requirement is the difference between the architecture diagram and the deployment.

The federation route sends a smaller bill and a stranger one. There is nothing to run, and in exchange the identity provider's availability becomes your deployment pipeline's availability, and the trust policy becomes the entire security boundary. The exchange is at least the one place the trust decision happens, and therefore the one place you can audit it, but that policy is a string comparison against a claim. Every serious misconfiguration in this space is the same mistake in a different syntax: a condition that checks who issued the token and not which workload it was issued to.

I want to be plain that none of this is mandatory. If you have a handful of workloads and one cloud account, a small number of access keys with owners and a real rotation runbook is a defensible answer, and it beats a federation setup that nobody understands well enough to review. What changes the arithmetic is scale and distance: many workloads, several accounts, machines outside the cloud that still need to reach into it. Past that point the manual answer is a spreadsheet describing a control nobody is running.

How This Gets Built Wrong

The check is on the issuer and not the subject. A trust policy that verifies a token came from a given provider, and stops there, will accept a token from anyone else who uses that provider, which for a public build service means anybody at all. The condition has to pin the specific repository, the specific ref or environment, the specific workload. This is one line of policy and it is the line the whole design rests on.

Wildcards get written for convenience during setup. A pattern match ending in a wildcard gets added to make the first pipeline work, because getting the exact subject string right takes three attempts and the deadline is real. It then stays. Anything matching the pattern inherits the role, and the set of things matching the pattern grows every time someone creates a repository. The temporary version of this is the permanent version.

Certificate lifetime gets treated as an implementation detail. The session is short. The certificate that obtains sessions may be valid for a year, and it is the certificate that an attacker wants. Whatever you set there is the real credential lifetime for anyone who gets the private key, and it deserves the same argument as any other expiry rather than whatever default the issuing tool proposed.

The old key gets left in place as a fallback. Federation gets wired up, the workload switches over, and the original access key stays active in case of trouble. Nothing has improved. The attack surface is the union of both paths, and the one nobody is watching is the one that still works. The migration is not finished when the new path works, it is finished when the old credential is deleted and something breaks loudly if it is needed.

Nobody knows what shows up in the audit trail. Short-lived sessions are only useful for investigation if the session carries something that identifies the workload. When it does not, the log shows a role being assumed thousands of times by nobody in particular, and the question after an incident is unanswerable. Work out what the session name will be before you need it, not from the trail of an event you are already trying to explain.

What I Would Actually Do

Start by finding out how many long-lived cloud credentials exist and what each one is for. That inventory is uncomfortable and it is the only part of this work that is guaranteed to pay, because a credential nobody can attribute to a workload is a credential you can delete, and deletion is the cheapest security control there is. Most estates have a surprising number of these and no list of them, which is the actual finding.

Then take the build system first. It has the worst concentration of powerful keys, the change is a policy document and a workflow edit rather than an architecture project, and the improvement is visible in a week. Doing the hardest workload first is how this kind of program dies at the pilot, and doing the build system first gives you a working example that everybody in the organization can read.

Decide the trust anchor question deliberately and once, in a room, rather than letting the first integration settle it. If your organization already runs a certificate authority competently, certificates are a natural fit and the operational muscle exists. If it does not, standing one up to avoid federation is trading a problem you understand for one you do not. Write the decision down with the reasoning, because the next person will need it and will otherwise reopen it at random.

And keep the expiry short enough to hurt slightly. An expiry long enough to be invisible is an expiry that has stopped doing anything, and the twelve-hour ceiling exists for workloads that genuinely need it rather than as a default. Short sessions force the renewal path to work continuously, which means you find out it is broken on an ordinary Tuesday instead of during the incident where it matters.

I should narrow the claim, because the enthusiasm around this deserves a limit. None of this removes trust; it moves it into one place and puts a clock on what comes out. If the certificate authority issues to the wrong workload, or the trust policy matches more than it should, an attacker gets short-lived credentials continuously, which is operationally identical to a long-lived one and considerably harder to see. What improves is not the possibility of compromise. It is that the blast radius has an end, and that the place where trust is decided is a document somebody can read.

Still, the difference between the two designs is the difference between a promise and a mechanism. A rotation policy is a promise, kept by people, on a schedule that competes with everything else those people are doing, and its failures are silent by construction. An expiry is a mechanism, enforced by the thing issuing the credential, and its failures are loud within the hour. That access key in your secret store has not failed once since it was created, which is the reason it is still there, and the reason nobody knows who else has it.