Daniel's been thinking about the software that runs without anyone sitting at a keyboard. Cron jobs, CI pipelines, Kubernetes pods, Lambda functions — these things aren't people, but they still need to prove who they are to get their work done. So he's asking three things. One: what actually distinguishes a service account or workload identity from a normal user account? Two: why not just create a bot user, stash its password somewhere, and call it a day? And three: how are the big cloud platforms moving away from that whole pattern — away from long-lived secrets and toward short-lived tokens, federation, and identities that get issued automatically without anyone ever touching a key file? He wants us to trace the architectural shift across Google Cloud, AWS, Azure, and Kubernetes.
This is one of those shifts where the entire industry is quietly converging on the same answer, and the answer is kind of radical when you step back. The short version is: we're eliminating the secret. Not rotating it more often, not encrypting it better — removing the thing entirely from the system. The credential becomes something the platform generates on the fly and throws away minutes later.
The secret zero problem.
No, I mean, that's the name for it. The secret that gets you all the other secrets. And the whole architectural move of the last five or six years has been toward making sure that secret never exists as a file on disk, never sits in a config variable, never gets committed to a repo. It's born, used, and discarded inside a single request.
So let's start with the thing Daniel's actually asking about. What makes a service account different from the account I use to log into the console?
The fundamental thing is that a service account isn't a person. It has no password, no MFA device, no login UI. You can't type a username and password into a web form and authenticate as a service account — there's nothing to type. Instead, it has a cryptographic identity. Historically that meant a key pair — a JSON file in GCP, an access key and secret key in AWS, a certificate or client secret in Azure. But increasingly it means no key at all. The identity is bound to the runtime context of whatever's running — the VM, the pod, the function — and the platform vouches for it.
So the distinction isn't just "it's a user but without the human." It's a completely different category of thing.
Right. A user account has a lifecycle that's tied to a person — onboarding, offboarding, password resets, suspicious login detection, all of that. A service account has none of that machinery because none of it applies. You can't phish a cron job. You can't send a push notification to a Lambda function and ask it to approve a sign-in. And the offboarding — when you delete the workload, you delete the identity with it. There's no "former employee who still has access" problem because the identity was never a person in the first place.
Which is why Daniel's second question — the "why not just make a bot user" question — is where the danger actually lives.
That pattern is the most dangerous thing in a lot of cloud deployments. You create a regular user account — let's call it "ci-pipeline-bot" — you give it a password or an access key, and you store that credential in a config file, an environment variable, a secrets manager, wherever. And now you've just created the single most valuable target in your entire infrastructure.
Because that credential is long-lived, it's shared across whoever or whatever needs it, and there's no human on the other end who's going to notice if it's being used from an unexpected location at three in the morning.
And it never expires unless you remember to rotate it, which nobody does. So it sits there for eighteen months, and eventually someone accidentally pushes it to a public repo, or a contractor copies it to their personal machine, or an attacker finds it in a log file. And the blast radius is enormous because that bot user probably has broad permissions — it needs to deploy, it needs to read from the artifact registry, it needs to write to the database. You've handed out a master key and called it a day.
The thing that gets me is that the bot user pattern feels responsible. You've created a dedicated account, you've scoped its permissions, you've stored the credential somewhere you think is safe. It feels like you did the work. And you did — you just did the wrong work.
The wrong work, and it's work that actively makes things worse. Because the credential exists. That's the problem. As long as there's a secret that can be extracted, copied, and reused somewhere else, you're vulnerable. The entire industry has realized this, and the response isn't "protect the secret harder" — it's "stop having the secret."
Alright, so walk me through how the platforms actually do that. How do you authenticate something without ever storing a credential?
The key insight is that the platform already knows what's running where. If I launch a virtual machine in Google Cloud, Google knows exactly which VM it is, which project it belongs to, which service account is attached to it. So instead of me handing the VM a key file and saying "use this to prove who you are," the VM just asks Google directly. There's a metadata server — a little HTTP endpoint that's only accessible from inside the instance — and the VM hits that endpoint and says "I need a token to call the Cloud Storage API." The metadata server checks which service account is bound to this instance, generates a short-lived access token, and hands it back. No key file ever touched disk.
And the metadata server knows which instance is asking because the request comes from inside that instance.
The network path is the authentication. If you're not running on that VM, you can't reach that metadata server. This is the "zero storage" pattern — the credential is generated at request time and cached in memory, never written to a file.
So let's go through the three clouds and then Kubernetes. Start with Google.
Google Cloud has had this pattern the longest in some ways. Every Compute Engine instance gets a default service account automatically — you don't have to create anything. That service account has the "compute default service account" role, which is fairly limited, but you can attach any service account you want when you create the instance. The instance metadata server is at a well-known IP — 169.254.169.254, same as AWS actually — and any Google Cloud SDK or client library will automatically hit that endpoint to get credentials. You never write a line of credential-handling code. It just works.
And this isn't limited to VMs.
Right — Cloud Run does the same thing. A Cloud Run service gets a service account identity, and the container can fetch tokens from the metadata server. GKE nodes use the same mechanism. The pattern is uniform: attach a service account to the compute resource, and the resource can prove its identity by calling the metadata server.
AWS takes a different approach or the same approach with different names?
Same architecture, different terminology. In AWS, the identity is an IAM role, not a service account. You create a role, you attach a policy to it, and you assign that role to an EC2 instance via an instance profile. The instance metadata service — IMDS, at that same 169.254.169.254 address — delivers temporary credentials. The SDK requests them, gets back an access key, a secret key, and a session token, all valid for up to six hours by default. The SDK handles refresh automatically — when the credentials are close to expiring, it requests new ones.
And AWS had a bit of a wake-up call on this front.
They did. In 2019, the Capital One breach happened. The attacker exploited a server-side request forgery vulnerability — an SSRF — in a web application running on EC2. The app was tricked into making a request to the internal metadata service at 169.254.169.254, and the metadata service happily returned the IAM role credentials for that instance. Those credentials were then used to list and exfiltrate data from S3 buckets. The fundamental problem was that IMDS version one had no protection against SSRF — any process on the instance could call it, and any request that reached it would be served.
So the response was IMDSv2.
IMDSv2, which adds a session-oriented request flow. You have to first send a PUT request to get a session token, and that token has to be included in subsequent GET requests. The session token is returned with a TTL — typically six hours. The key protection is that the PUT request can't be made via a simple SSRF — most SSRF attacks can only trigger GET requests, not PUTs with custom headers. It's not a perfect defense, but it raises the bar significantly. And AWS has been pushing hard to make IMDSv2 the default everywhere.
What about Azure?
Azure calls them managed identities, and they were introduced in 2018. The architecture is the same — each Azure resource, like a VM or an App Service or an AKS cluster, gets an identity in Azure AD automatically. There are two flavors: system-assigned, where the identity is tied to the lifecycle of the resource and deleted when the resource is deleted, and user-assigned, where you create the identity separately and can attach it to multiple resources. In both cases, the resource calls the Azure Instance Metadata Service — again at 169.254.169.254 — and Azure AD issues a token on the fly. No client secret, no certificate, no key file.
Three clouds, three naming schemes, one pattern.
One pattern. And the pattern is: the platform is the identity provider. The workload doesn't bring its own credentials — it brings its context, and the platform vouches for it.
Kubernetes adds a wrinkle here because it's a platform running on top of a platform.
And this is where things get interesting. Kubernetes has its own concept of service accounts, and they're completely separate from cloud service accounts. A Kubernetes service account is a resource inside the cluster — you create it with a YAML manifest, and when a pod runs with that service account, Kubernetes mounts a token into the pod at a well-known path. The pod can use that token to authenticate to the Kubernetes API server.
But the old way of doing this had the same problem as the bot user pattern.
In the old model — and this is still the default in many clusters — the token is a long-lived secret. It's stored in a Kubernetes Secret object, and it doesn't expire. If someone gets access to that token, they can authenticate to the API server as that service account forever. It's the same "credential sitting on disk" problem.
And the fix?
The TokenRequest API, which has been stable since Kubernetes 1.21. Instead of mounting a long-lived token from a Secret, the kubelet requests a short-lived token from the API server on behalf of the pod. This token is projected into the pod's filesystem as a volume mount, and it's automatically rotated — the kubelet fetches a new one before the old one expires. The token is also audience-bound, meaning it's scoped to a specific intended recipient. A token issued for the Kubernetes API server can't be used to authenticate to an external service, even if someone extracts it.
So it's the same zero-storage pattern, but implemented inside the cluster.
And it gets better. The token is also bound to the pod's identity — the token contains claims about which pod, which namespace, which service account it was issued for. If the pod is deleted, the token becomes useless because the kubelet stops refreshing it. The identity is tied to the workload's runtime existence, not to a static file.
Alright, so we've got four platforms, each with its own mechanism for issuing short-lived credentials to its own workloads. But Daniel's third question pushes further — what happens when you need to authenticate across platforms? A GitHub Actions workflow that needs to deploy to Google Cloud. A Lambda function that needs to read from an Azure blob. That's where the old pattern would have been "create a service account key and store it in the CI system's secrets manager," which is exactly the thing we're trying to eliminate.
This is where workload identity federation comes in, and it's the real architectural convergence. All four platforms are moving toward the same design: instead of managing keys in one cloud and trying to use them from another, you federate. The external identity provider — GitHub, AWS, Kubernetes, whatever — issues a token, and the target cloud validates that token and exchanges it for a short-lived access token. No static secret ever crosses the boundary.
Walk me through Google Cloud's version first.
Google Cloud Workload Identity Federation launched in 2021 and has been expanded pretty aggressively through 2025 and into this year. The idea is that you set up a workload identity pool — a container for external identities — and configure a provider, which is basically "I trust tokens issued by this OIDC provider" or "I trust SAML assertions from this identity provider." The external workload gets a token from its own platform — say a GitHub Actions OIDC token — and presents it to Google's Security Token Service. Google validates the token, checks that the claims match the attribute mappings you've configured, and returns a short-lived Google Cloud access token.
So the GitHub Actions workflow never sees a GCP service account key. It sees its own GitHub token, which GitHub issued and which is only valid for that specific workflow run.
Right. And the attribute mapping is where the fine-grained control lives. You can say "only tokens from repository X, on branch main, with this specific audience claim, can impersonate this service account." If someone forks your repo and tries to run a workflow, the token claims won't match and Google will reject it. The identity is bound to the CI context, not to a secret that anyone with read access can copy.
AWS's version of this?
IAM Roles Anywhere, launched in 2022. It uses X.509 certificates instead of OIDC — your external workload has a certificate issued by a CA you trust, and AWS exchanges that certificate for temporary IAM role credentials. It's designed for on-premises servers, hybrid cloud setups, IoT devices — anything that's not running inside AWS but needs AWS API access. The certificate is the identity, and AWS trusts it because you've configured a trust anchor — the CA that issued it. No long-lived AWS access keys anywhere in the system.
And Azure?
Azure Workload Identity Federation went GA in 2022 and has been deeply integrated with Azure AD. It uses OIDC, same as Google's approach. You configure a federated credential on an Azure AD application or user-assigned managed identity — you specify the issuer URL, the subject claim, the audience. When the external workload presents a token that matches, Azure AD issues an access token. This is how GitHub Actions authenticates to Azure without a client secret, how Kubernetes pods in other clouds authenticate to Azure Key Vault, how pretty much any OIDC-capable platform can get short-lived Azure credentials.
So the pattern across all three clouds is: the external platform says "I vouch for this workload," the cloud validates that assertion, and the cloud issues a token. The credential is generated at the moment of the request and is valid for an hour or less.
And the knock-on effect is that credential management as a practice just disappears. No rotation schedules. No secret scanning tools frantically searching your repos for leaked keys. No "we need to rotate the production service account key but nobody remembers which twelve services depend on it." The identity is bound to the workload's context — the pod, the VM, the CI job run — and it can't be extracted and reused somewhere else.
There's a tradeoff here, though. You're now dependent on the platform's metadata service and token issuance infrastructure. If that gets compromised, the attacker can still get tokens.
That's the real vulnerability in this model, and it's not hypothetical. The Capital One breach in 2019 was exactly this — an SSRF that tricked the EC2 instance into requesting credentials from the metadata service. The attacker didn't steal a key file because there was no key file. They stole the tokens directly from the metadata endpoint. But the blast radius is smaller in the modern model. Those tokens were valid for six hours max, and they were scoped to the IAM role of that specific instance. If the same attack happened today with IMDSv2 enforced, the SSRF would need to be sophisticated enough to make a PUT request first, which is much harder.
And the tokens are getting even more tightly bound. Audience-scoped tokens that only work for a specific service. IP-bound tokens that only work from a specific address. Pod-bound tokens in Kubernetes that die with the pod.
The direction of travel is clear. The token becomes less and less portable, more and more context-bound, until stealing it is almost pointless — you can't use it from anywhere else for anything else.
That's the theory. But Hilbert has a story about what happens when the theory fails.
Hilbert: Forty-seven.
Forty-seven what?
Hilbert: JSON key files. Service account credentials. All in one private GitHub repo. Fintech startup, 2019. I was the SRE.
Forty-seven service account keys in a single repository.
Hilbert: We called it the Keys of the Realm. The CTO had it bookmarked. Chrome bookmark bar, right between the AWS console and the PagerDuty dashboard. One click and you had every credential in the company.
And someone pushed it public.
Hilbert: Accidentally. Developer was cleaning up old branches, force-pushed to the wrong remote. The repo was public for eleven minutes. Our secret scanner caught it — we had a scanner, that's the funny part — but eleven minutes is an eternity. We spent the entire weekend rotating all forty-seven keys. Every service broke. Staging, production, the CI pipeline itself — because the CI pipeline needed a key to deploy, and we'd just revoked it. It was a recursive nightmare.
You were rotating the key that the rotation script needed to authenticate.
Hilbert: We had to bootstrap the rotation with a temporary key that we created manually, stored in a text file on someone's laptop, and deleted immediately after. That temporary key was valid for about forty minutes and it was the most terrifying forty minutes of my professional life.
This is the pattern Daniel's asking about — the bot user pattern, the "just stash the credential somewhere" approach. It works until it doesn't.
Hilbert: The repo's still there. Archived. All forty-seven keys revoked, obviously. But we kept the files. We show them to new hires during onboarding. It's a museum of bad practices. The README says "Keys of the Realm" in bold, and underneath someone added "please don't" in a commit from about three months after the incident.
A museum.
Hilbert: You need artifacts. People don't believe you when you tell them how bad it was. You have to show them the forty-seven JSON files, each one with a project ID and a private key, all sitting in a folder called "credentials" with an underscore at the front so it would sort to the top. The underscore was someone's idea of organization.
Today, if you were building that same system, none of those files would exist.
Hilbert: Zero. The CI pipeline would use workload identity federation. The services would get tokens from the metadata server. The only thing in the credentials folder would be a README that says "nothing to see here." That's the shift you're describing, and it's not elegant architecture — it's the difference between a weekend of panic and a normal Friday.
The museum detail is going to stick with me. Not just that the keys existed, but that the company turned them into a cautionary exhibit.
It's actually a perfect illustration of the architectural point. Those forty-seven keys were long-lived, shared, and stored in a single place — the Keys of the Realm bookmark. Every property we said makes the bot user pattern dangerous, concentrated in one Chrome tab.
Hilbert: The CTO's bookmark bar. I still see it when I close my eyes.
The pattern is clear — eliminate the static secret, bind identity to runtime context. But what's the next vulnerability in that chain? If we've gotten rid of the key file, what's the new thing attackers go after?
The metadata service itself. SSRF attacks that steal short-lived tokens are the obvious next target, and they're already happening. The industry response is to make those tokens even less portable — audience binding, IP binding, pod binding. But the deeper question is whether the metadata service model itself is the final answer, or whether we'll eventually move to something where the workload doesn't even need to request a token — the platform just injects it at the network layer, transparently, with no HTTP endpoint to attack.
Like a sidecar proxy that handles all authentication, and the application code never touches a credential or a token or a metadata endpoint at all.
Service mesh patterns — Istio, Linkerd, the sidecar model in general — are already moving in that direction. The application makes a plain HTTP request to another service, and the sidecar injects the authentication token automatically. The application doesn't know about tokens, doesn't request them, doesn't have a metadata endpoint to be exploited. The identity is handled entirely out of band.
Which brings us to the open question. If workload identity federation eliminates static credentials, and service meshes eliminate the metadata endpoint as an attack surface, what's the next secret zero? What's the new thing we're going to be cleaning up after the next Capital One breach?
I think it's the identity provider itself. All of this federation — OIDC, SAML, certificate-based trust — depends on the external identity provider being trustworthy. If someone compromises the GitHub OIDC endpoint, or the Kubernetes API server's token issuance, or the CA that issues certificates for IAM Roles Anywhere, they can mint tokens that every cloud will accept. The attack surface shrinks, but what remains becomes incredibly high-value.
We've traded forty-seven key files for a handful of identity providers that, if compromised, give you everything.
We've traded a distributed mess for a concentrated trust boundary. That's progress — the concentrated boundary is easier to monitor, harder to accidentally expose, and has a much smaller blast radius when you do need to rotate something. But it's not magic. The secret doesn't vanish — it just moves up the stack to a place where it's harder to reach and easier to control.
The misconception I keep running into is that a service account is just a bot user — create a regular account, give it a password, use it in code. The reality is that service accounts are a completely different category. No password, no MFA, no login UI. They're designed from the ground up to operate without any stored secret, and the whole industry is converging on making that the default.
The corollary misconception — that workload identity federation is only for cross-cloud scenarios. It's equally valuable inside a single cloud. It eliminates the need to manage keys even for workloads running entirely within GCP or entirely within AWS. The pattern is the same whether the trust boundary is between clouds or between services in the same project.
The future here feels like it's heading toward a world where human identity is the special case. Right now we treat human users as the default and workload identities as the exception. But as AI agents and automated systems proliferate, that's going to flip. Most authentication events will be non-human — services talking to services, agents acting on behalf of users, automated pipelines deploying code. The human clicking "sign in" will be the weird edge case.
The infrastructure is already being built for that world. Short-lived tokens, automatic rotation, identity bound to context rather than credentials — all of it assumes that the entity authenticating is software, not a person. The human model of "here's my password, I'll keep it for two years and forget it six times" is the legacy pattern that everything else is moving away from.
Thanks to our producer Hilbert Flumingtop for keeping the show running, and for the museum of bad practices that I'm now going to be thinking about every time I see a credentials folder.
This has been My Weird Prompts. If you want to send us your own questions — about cloud architecture or anything else Daniel's been reading at two in the morning — email the show at show at my weird prompts dot com.
We'll be back soon.