Service Accounts
A service account (SA) is an identity for a workload, not a person. Code running on a VM, a Cloud Function, or GKE authenticates AS an SA. It is both an identity (you grant it roles) AND a resource (you grant people roles ON it).
Two ways an SA gets used:
- Attached SA (preferred) - assign the SA to the resource (VM, function, Cloud Run). The metadata server hands out short-lived tokens automatically. No keys to manage.
- SA key (avoid) - a downloaded JSON private key. Long-lived, leakable, the top cause of GCP credential incidents.
There are three types of service account, distinguished by who creates them:
- Compute Engine default SA:
PROJECT_NUMBER-compute@developer.gserviceaccount.com- historically had the broad Editor role. Newer orgs disable that automatic grant via theiam.automaticIamGrantsForDefaultServiceAccountsorg policy. Lock it down. - App Engine / Cloud Functions default SA:
PROJECT_ID@appspot.gserviceaccount.com. - Google-managed service agents (e.g.
service-...@...gserviceaccount.com) are created by Google to let a service act on your resources - don't delete them. - Google APIs service account:
PROJECT_NUMBER@cloudservices.gserviceaccount.com- runs internal Google processes on your behalf; also automatically granted the Editor role. - An SA email is its identifier; it has a unique numeric ID too.
- 10 user-managed keys max per SA. You can disable an SA (
gcloud iam service-accounts disable) instead of deleting it.
Deploying a resource that runs as an SA requires serviceAccountUser on that SA, plus normal deploy permissions.
Grant the SA only the roles its workload needs, scoped to the specific resources. Do not reuse the default Editor SA for everything. One purpose-built SA per workload.
IAM lets you slice a project into microservices, each with its own SA and its own scoped access - even reaching into another project or a single bucket:
A person or group with roles/iam.serviceAccountUser on an SA can act as it, and therefore reach every resource that SA has access to. Be cautious granting it - the person inherits the SA's full blast radius.
Service account keys
Every SA has a key pair used to authenticate it. There are two kinds, and the difference is who holds the private half:
Inside Google Cloud (Compute Engine, App Engine, GKE, Cloud Run), keys are Google-managed automatically. Create user-managed keys only as a last resort - prefer short-lived credentials (tokens) or service account impersonation instead.
Google never stores the private half of a user-managed key. Lose it and it is gone - Google cannot help you recover it. You own its security and its rotation.
Impersonation & short-lived credentials
Impersonation lets one identity temporarily act as a service account WITHOUT ever holding that SA's key. You use your own credentials to mint a short-lived token for the SA, then call APIs as the SA. This is the modern replacement for downloading key files.
Mental model: "let me borrow that SA's permissions for a few minutes, then throw the token away."
- To impersonate an SA you need
roles/iam.serviceAccountTokenCreatorON that SA. - Generated access tokens are short-lived - default 1 hour, max 12 hours (org policy
constraints/iam.allowServiceAccountCredentialLifetimeExtensiongates the extension). - Contrast with
roles/iam.serviceAccountUser= attach/run as (deploy-time);serviceAccountTokenCreator= mint tokens for (runtime impersonation).
Easy to swap on the exam:
If a question is about impersonating or --impersonate-service-account, the answer is Token Creator.
Every impersonated call is logged (who borrowed which SA), and no long-lived key exists to leak. Prefer it over SA keys for admins and CI that must act as an SA occasionally.
Access scopes (legacy VM authorization)
Access scopes are an older, VM-level authorization layer applied to the attached SA. When you create a VM you choose scopes ("Allow full access to all Cloud APIs", "Allow default access", or Set access for each API - e.g. Storage: Read Write). They gate which APIs the VM's SA token may call, regardless of the SA's IAM roles.
Scopes were the only mechanism for granting permissions to service accounts before IAM roles existed. You can change a VM's scopes after creation, but only while the instance is stopped. For user-created SAs, use IAM roles instead.
A VM's SA can do something only if both allow it. If the SA has roles/storage.admin but the VM's scope is Storage Read Only, writes are still blocked. The modern best practice: attach a purpose-built SA, set scope to cloud-platform (--scopes=cloud-platform), and control everything with IAM roles - don't rely on scopes for least privilege.
SSH into an instance and any gcloud/API call runs as the VM's attached SA - your own personal roles don't apply. So if you personally hold Compute Instance Admin but the SA only has storage.objectViewer, then from the VM gcloud compute instances list fails ("insufficient authentication scopes") while downloading a bucket object works. Grant the SA (not just yourself) whatever the workload needs, and remember writes also need a role that permits them (e.g. storage.objectCreator) - viewer alone gives a 403 on upload.
Recap
serviceAccountUserserviceAccountTokenCreator