Business Challenge
#40 ended by pointing here. This is the mechanism that makes keys avoidable, and the one place in this block where the audit trail gets better rather than worse.
Not if developers can run code on privileged resources. Giving someone an SSH session to a VM instance can create privilege-escalation and non-repudiation risks in exactly the same way a key does — the workload authenticates as its attached service account, and the audit logs record only the identity of the service account.
Correct approachTreat interactive access to a machine with a privileged attached service account as equivalent to handing out that account's key. The credential is different; the attribution gap is identical.
You cannot. In the Google Cloud console you always authenticate with your user credentials — impersonation is a gcloud CLI, client library and API mechanism only.
Correct approach
Reproduce the check from the CLI with --impersonate-service-account. A console test proves what you can do, which is a different question.
It does not. Short-lived credentials have a limited lifetime, with durations of just a few hours or shorter, and are not automatically refreshed — the expiry is the security property, and handling it is the caller's job.
Correct approachLet the CLI or a client library manage the exchange. Code that fetches a token once and holds it will work in testing and fail in production an hour later.
It is the ability to become the service account. To impersonate a service account, you need the iam.serviceAccounts.getAccessToken permission — so whoever holds it inherits everything that account can do, which is the #31 point about a service account being a resource with its own policy.
Review who can impersonate with the same seriousness as who holds the roles directly, because functionally they are the same set.
Architecture
The definition carries the whole design: service account impersonation involves two identities — an authenticated principal, and the service account that the principal impersonates. To impersonate the service account, the authenticated principal gets a token for the service account, then uses that token to authenticate as the service account.
Three ways to act as a service account, and what each records
| Route | Identities involved | What the audit log shows |
|---|---|---|
| Impersonation | Two — the principal, and the service account. | Most audit logs include both their identity and the identity of the service account. |
| A service account key | One. The key holder disappears into it. | Only the service account. Not the identities of the people who used the key to authenticate. |
| An attached service account | One. The workload is the account. | Only the service account. Not the identities of the users who executed code on the workload. |
Note the hedge in the first row, because it is Google's and not mine: most audit logs. Impersonation is a large improvement in attributability rather than a guarantee of it, and a design that depends on the human name being present should verify it is present for the specific API in question.
Rows two and three of that table record the same thing, and only one of them is a key. So an organisation that enforces iam.disableServiceAccountKeyCreation from #40, migrates every workload, and eliminates the last key file has closed row two and left row three exactly as it was. A developer with an SSH session to a VM carrying a privileged attached service account can act as that account, and the log will show the account. Google names this directly — executing code on privileged resources can create privilege-escalation and non-repudiation risks — and lists it alongside keys rather than as a footnote to them. The control you need here is not a credential policy; it is who can get a shell on which machines.
What you actually get, in time
By default, the maximum token lifetime is 1 hour (3,600 seconds). To extend the maximum lifetime for these tokens to 12 hours (43,200 seconds), the service account has to be added to an organization policy that includes the constraints/iam.allowServiceAccountCredentialLifetimeExtension list constraint.
That constraint is worth noticing for its shape. It is a list constraint naming the service accounts allowed the longer lifetime, so the extension is per-account and deliberate rather than a global setting. Twelve hours is the ceiling, not a default anyone drifts into — which is the opposite of a key, whose lifetime is however long until someone remembers it exists.
Where a single exchange is not enough, you can use a delegation chain consisting of several service accounts. The mechanics of that, and of the different token types, are #42.
Why This Architecture Holds Up
Nine posts into this block, almost every mechanism has had a sting in it. Allow policies only add. Conditions do not narrow. A cloned role silently drops permissions. The troubleshooting tool will not take a group. Impersonation is the one where the design is straightforwardly better than the thing it replaces, and it is worth being explicit about why.
A key answers "can this caller authenticate as the service account" with a file. The file has no opinion about who is holding it, so the question of who is unanswerable by construction — the credential itself contains no trace of the human. Impersonation answers the same question with an exchange: an already-authenticated principal presents their own identity and asks for a token. The human is not an annotation on the request, they are a prerequisite for it, which is why the log can name them.
Short-lived credentials create less risk than long-lived credentials such as service account keys, and the mechanism is the reason rather than the duration. A token that expires in an hour and is not automatically refreshed forces the exchange to happen again, and every exchange re-presents the human identity. The expiry is not primarily about limiting the blast radius of a leak; it is what keeps the two-identity structure true over time.
Which also explains why the lifetime extension is a list constraint rather than a switch. Twelve hours is long enough that the exchange happens roughly once a working day, and naming the accounts that get it keeps the exception visible.
What to do with this
- Audit who holds
iam.serviceAccounts.getAccessTokenalongside who holds roles directly — they are the same access, one step removed. - Treat SSH to a privileged VM as credential issuance. It is row three of the table, and no key policy touches it.
- Use impersonation for temporary elevated access, which is the first use case Google lists, rather than granting and later removing a role.
- Do not build token caching yourself. Credentials are not automatically refreshed, and the libraries already handle the exchange.
- Keep the lifetime extension list short and reviewed. The constraint names accounts, so the list is the audit.
- Verify the human identity is in the log for the specific API you depend on, because the guarantee is "most audit logs", not all.
Key Architecture Decisions
| Decision | Choose this | Because |
|---|---|---|
| A human needs service account access | Impersonation | Two identities are involved, so both can be recorded. |
| Temporary elevated access | Impersonation, not a role grant | It is the first use case listed, and it expires by itself. |
| Testing what a service account can do | The CLI, not the console | In the console you always authenticate with your user credentials. |
| Granting Token Creator | Review as a full grant | It confers everything the target account can do. |
| Token handling in code | Let the library do it | Short-lived credentials are not automatically refreshed. |
| A job that runs longer than an hour | The lifetime extension constraint | Default maximum is 1 hour; 12 hours is available per named account. |
| Interactive access to privileged VMs | Restrict it like a credential | The attached service account is the only identity logged. |
| Depending on human attribution | Verify per API | Both identities appear in most audit logs, not all. |
Closing Thought
The useful way to hold impersonation is not as a safer credential but as a different question being asked. A key asks the service to verify a secret. Impersonation asks an already-identified principal to request a token, which means the request cannot be made anonymously even in principle. That structural difference is what the audit trail is reporting when it carries both names — not extra logging, but an extra identity that genuinely existed.
Which makes the attached service account case the one to sit with. It is the default for every workload on Google Cloud and it is entirely correct for a workload: the machine is the account, one identity, nothing missing. It only becomes a non-repudiation problem when a human gets inside the machine. So the boundary that matters is not between key and no key — it is between an identity acting on its own and an identity being worn. Keys let you wear one without saying who you are, and so does a shell on the right VM.
#42 goes under the exchange: short-lived credentials and token generation — access tokens against ID tokens, signed blobs and JWTs, delegation chains, and which of them the Service Account Credentials API will actually mint for you.
Comments