Prepare and test your skills
Prepare and test your skills
Service Account Impersonation and Credential Security Governance is the practice of letting one identity act as a service account by minting short-lived credentials instead of distributing long-lived static keys. A source principal with permission to impersonate calls the Service Account Credentials API (opens in a new tab) to create a temporary access token, ID token, JWT, or blob for a target service account. The target service account's existing IAM permissions then control what the temporary credential can access. This pattern keeps delegation short-lived and least privilege by default while organization policy and Workload Identity Federation remove the need for downloadable keys.
Short-lived service account credentials are temporary credentials minted by the Service Account Credentials API using an internal Google-owned key, and by default OAuth 2.0 access tokens expire after 1 hour. The API can create OAuth 2.0 access tokens, OpenID Connect (OIDC) ID tokens, self-signed JSON Web Tokens (JWTs), and self-signed binary blobs, and each type carries the target service account's identity for a limited time. Credentials are often obtained automatically when a workload uses Application Default Credentials (ADC), when the gcloud CLI runs with the --impersonate-service-account flag, when a workload runs on an attached service account on Compute Engine or App Engine, or when an external identity is federated through Workload Identity Federation.
The service account impersonation (opens in a new tab) flow moves trust from the source to the target without copying a secret. First the source authenticates with its own user credentials, attached service account, or federated identity, then the source calls the Service Account Credentials API on the target service account, then the API returns a short-lived token signed by the target's Google-owned key. The caller presents that token to Google APIs, and audit logs record both the impersonated service account and the identity that created the credential. Most Google Cloud services log both identities, while App Engine and Google Kubernetes Engine do not log the creator identity, which limits traceability on those platforms.
Prohibited self-impersonation is the blocked pattern where a service account's own short-lived credential is used to generate a new credential for that same service account. The Service Account Credentials API prohibits using a short-lived credential for a service account to generate a new access token for the same account, and it prohibits using a short-lived credential to sign a blob or JWT that will be used to call the Identity and Access Management API, the Service Account Credentials API, or the OAuth 2.0 API. Google Cloud blocks these patterns because they would let an attacker who steals one short-lived token refresh it indefinitely.
A prohibited attempt fails with FAILED_PRECONDITION: You can't create a token for the same service account that you used to authenticate the request. To recover, the request must authenticate with different credentials, such as end-user credentials or a different service account's credentials, and then request the token for the target account. The one exception is self-signed JWTs, where a self-signed JWT for a service account can be used to generate a new access token for that same account.
Exam tip: Self-impersonation with a short-lived token to mint another access token or to sign for IAM, Credentials, or OAuth 2.0 APIs is blocked, but using a self-signed JWT to mint its own access token is allowed.
Service account keys (opens in a new tab) are RSA public/private key pairs associated with a service account, and they fall into two categories with different ownership and risk. Google-owned keys are held in escrow by Google and never exposed, while user-managed keys expose the private key to the customer as a downloadable key that must be stored securely. Each service account can have up to 10 user-managed keys, and Google stores only the public portion.
| Key type | Private key access | Rotation and use |
|---|---|---|
| Google-owned and managed key pair | Private key held in escrow by Google and never directly accessible; public key is public for signature verification | Actively used signing keys are rotated regularly with probabilistic ramp-up and ramp-down; used by Service Account Credentials API, App Engine, and Compute Engine to mint short-lived credentials |
| User-managed key pair | Private key is the downloadable service account key; holder can sign a JWT and exchange it for an access token via Cloud Client Libraries or manual OAuth 2.0 flow | Customer-managed lifetime and rotation; creates long-lived credential risk including leakage, privilege escalation, and concealment of the true actor |
The public key for a Google-owned pair can be retrieved without authentication in three formats: X.509 certificate at https://www.googleapis.com/service_accounts/v1/metadata/x509/SERVICE_ACCOUNT_EMAIL, JSON Web Key (JWK) at https://www.googleapis.com/service_accounts/v1/jwk/SERVICE_ACCOUNT_EMAIL, and raw format at https://www.googleapis.com/service_accounts/v1/metadata/raw/SERVICE_ACCOUNT_EMAIL. If the public key is cached, the cache should last at most 24 hours, and any retrieved key remains valid for at least 24 hours after retrieval. For user-managed keys, the X.509 endpoint is also public, so an uploaded certificate that contains optional attributes such as address or location in the common name will disclose that metadata publicly and should instead use a generic Subject.
Keyless delegation is the pattern of authenticating first with an attached service account or federated identity and then using impersonation or signing APIs instead of downloading a static key. For workloads on Google Cloud, the preferred method is to attach a service account to the compute resource where code runs, such as a Compute Engine virtual machine, and let client libraries obtain short-lived credentials automatically. For workloads outside Google Cloud or on-premises, the preferred method is to set up Workload Identity Federation to provide an authenticated external identity and then configure the application with a credential configuration file to impersonate a service account.
Domain-wide delegation without service account keys follows an ordered signing flow that avoids managing a private key file:
sub claim to the email address of the user for whom delegated access is requested.signJwt API on the Service Account Credentials API to sign the JWT with the service account's Google-owned key.This sequence keeps the private signing key inside Google while still producing a token that carries delegated user context. The same principle applies to external applications: federate first, then impersonate, rather than distributing a service account key that can be copied, leaked from source repositories, buckets, email, file shares, or binaries, and reused without additional sign-in verification.
Governance controls for keys and impersonation combine authorization, organization policy, and auditability to keep delegation short-lived and traceable. Impersonation depends on IAM permission on the target service account, granted through the Service Account Token Creator role, so only approved users, groups, or federated subjects can mint credentials for that account. Organization policy constraints limit which projects can create or upload user-managed keys, secure-by-default organizations can block key creation entirely, and teams are expected to choose impersonation or Workload Identity Federation whenever possible and to validate any externally sourced credential before use.
When keys must exist, risk is reduced by minimizing circulation and improving attribution. Best practices include providing keyless alternatives, never leaving keys in temporary directories or passing them between users, never committing keys to source repositories or embedding them in binaries, using metrics to find unused keys, rotating keys, and setting expiry times so keys expire automatically. For non-repudiation, each application should use a dedicated service account so the principalEmail field in audit logs identifies the application, and each machine running a copy should use a dedicated key so the serviceAccountKeyName field identifies the source machine.
Granular Authorization and Identity-Resource Dual Role Configuration is the control of two different directions of access for a service account (opens in a new tab) with least privilege at the lowest level of the resource hierarchy that still allows the work. A service account acts as an identity when it is granted Identity and Access Management (IAM) roles on APIs and resources, and it acts as a manageable resource when users and other service accounts are granted IAM roles on the service account itself. Confusing those two directions causes over-privilege, because access granted to the service account determines what jobs running as that account can do, while access granted on the service account determines who can become or use that account.
A service account as an identity is a principal that authenticates to Google Cloud APIs and is authorized by IAM allow policies attached to organizations, folders, projects, and resources such as Compute Engine virtual machines (VMs), Pub/Sub topics, and Cloud Storage buckets. The policy flows from the resource to the service account identity, and the service account can only perform operations allowed by roles bound to it at that resource or inherited from a parent. Least privilege for this direction means granting only job-function predefined roles or tightly scoped custom roles at the project or resource level, avoiding basic roles such as Editor and Owner, and never relying on the automatic Editor grant given to default service accounts.
A service account as a resource has its own IAM allow policy that controls who can manage, attach, impersonate, or mint credentials for that account. The policy flows from the service account resource to the user or calling service account, and granting a role on the service account does not grant access to the data the service account can access until the holder actually acts as the account. Because impersonation transfers all of the service account's access to the holder, highly privileged Compute Engine and App Engine default service accounts require extra caution when granting any use rights on them.
The three common use rights granted on a service account resource divide by what the holder is allowed to do with the account:
| Role on service account | Key permission | Allows holder to |
|---|---|---|
| Service Account User | iam.serviceAccounts.actAs | Attach the service account to a resource so jobs on that resource run as the account |
| Service Account Token Creator | iam.serviceAccounts.getAccessToken, iam.serviceAccounts.signBlob, iam.serviceAccounts.signJwt, iam.serviceAccounts.implicitDelegation | Authenticate as the account, sign blobs and JWTs with its Google-managed key, or chain delegation across accounts |
| Service Account OpenID Connect Identity Token Creator | iam.serviceAccounts.getOpenIdToken | Generate an OIDC-compatible JWT signed by the Google OIDC Provider that represents the service account identity |
Exam tip: A role granted to a service account controls what that account can access; a role granted on a service account, such as Service Account User with iam.serviceAccounts.actAs, controls who can use that account.
Least privilege across the resource hierarchy starts from the Organization resource at the apex, with folders grouping projects and projects containing service resources. An IAM allow policy attached at the organization or folder is inherited by all child folders, projects, and resources, so a grant at a higher level has wider blast radius than the same grant at the project or single-resource level. Secure design therefore attaches each binding at the lowest node that satisfies the workload, uses folders to isolate environments and teams, and relies on inheritance only for intentionally broad governance controls.
Default permissions undermine that design unless they are explicitly removed. The boolean Organization Policy Service constraint constraints/iam.automaticIamGrantsForDefaultServiceAccounts set to False disables automatic Editor (roles/editor) grants when default service accounts are created, forcing deliberate role assignment. Complementary controls include removing domain-wide Project Creator and Billing Account Creator bindings, downscoping existing default accounts with role recommendations, enforcing constraints/iam.disableServiceAccountCreation where service accounts must be centralized, and blocking long-lived keys with constraints/iam.disableServiceAccountKeyCreation and constraints/iam.disableServiceAccountKeyUpload.
Fine-grained enforcement narrows broad grants without creating role sprawl. Tags annotate resources so IAM policies and organization policies can conditionally allow or deny access based on tag presence across the hierarchy. Roles for service account authentication (opens in a new tab) work together with IAM Conditions that restrict when a binding applies, IAM deny policies that constrain which permissions can be granted or which principals can receive them, and principal access boundary (PAB) policies that limit what a compromised principal can reach to reduce phishing and exfiltration impact. Together these controls let an administrator grant a small role broadly but still deny sensitive actions, rather than granting a large role narrowly and hoping it is sufficient.
Authorizing attachment, impersonation, and token use connects permission to attach a service account with permission to act as that account. For most services the user must hold iam.serviceAccounts.actAs on the specific service account being attached, typically through the Service Account User role granted on the project or directly on the service account. The attached service account then depends on its own identity grants to authorize API calls, so both the actAs grant on the account and the workload roles granted to the account must be least privilege.
Creating the attachment follows an ordered dependency where requiring permission to attach service accounts to resources (opens in a new tab) enforces the check:
iam.serviceAccounts.actAs on the chosen service account.Impersonation and signing let a principal use a service account without attaching it to infrastructure. With iam.serviceAccounts.getAccessToken the caller calls generateAccessToken() or uses the gcloud --impersonate-service-account flag to authenticate as the account and access all resources the account can access. With iam.serviceAccounts.signBlob and iam.serviceAccounts.signJwt the caller asks the Google-managed private key held in escrow to sign arbitrary payloads or well-formed JWTs, and with iam.serviceAccounts.getOpenIdToken the caller mints an OIDC token for federation. Advanced chaining uses iam.serviceAccounts.implicitDelegation, where service account A with that permission on B can obtain an access token for C when B holds getAccessToken on C, so trust flows from A to B to C without A ever holding C's credential.
Legacy behavior in App Engine, Managed Service for Apache Airflow, Dataflow, Managed Service for Apache Spark, Cloud Data Fusion, and Dataform once allowed attachment without actAs checks, creating non-obvious privilege escalation. Remediation grants actAs to legitimate deployers, replaces the Compute Engine default service account with purpose-built accounts that follow least privilege, and then enforces checks with boolean constraints such as constraints/appengine.enforceServiceAccountActAsCheck, constraints/dataflow.enforceComputeDefaultServiceAccountCheck, and constraints/dataproc.enforceComputeDefaultServiceAccountCheck. These constraints are visible only where legacy behavior remains; their absence means enforcement is already active and attachment requests without actAs on the target account will fail.
Service Account Provisioning and Lifecycle Management is the practice of creating custom non-human identities in Google Cloud, controlling what those identities can access, controlling who can use those identities, and adjusting or revoking that access over time. A service account (opens in a new tab) acts in two directions at once: it is a principal that can be granted access to resources, and it is a resource that other principals can be granted access to use. Identity and Access Management (IAM) controls both directions through allow policies that bind principals to roles.
Service account types differ by who creates the identity and who manages its lifecycle. The documentation illustrates two patterns: user-managed service accounts that an administrator provisions for a workload, and service agents that Google Cloud creates automatically when an API is enabled.
| Account type | How creation is triggered | Identity example |
|---|---|---|
| User-managed service account | Administrator runs gcloud iam service-accounts create in a project | SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com |
| Service agent | Google Cloud creates the account when the administrator enables an API, such as the Conversational Analytics API | service-PROJECT_NUMBER@gcp-sa-geminidataanalytics.iam.gserviceaccount.com |
A user-managed service account remains under administrator control for role grants, attachment to resources, and later policy changes. A service agent exists so the enabled service can access resources on the administrator's behalf, and its lifecycle depends on use of that Google Cloud service.
Provisioning a custom service account creates a dedicated identity for code running on Google Cloud, then authorizes that identity before any workload uses it. The administrator must hold Project IAM Admin and Project IAM Admin-adjacent creation rights, and management of the account later requires the Service Account Admin (roles/iam.serviceAccountAdmin) role on the service account or its project.
Provisioning follows an ordered workflow where each step depends on the previous identity existing:
gcloud iam service-accounts create SERVICE_ACCOUNT_NAME to create the identity in the project.gcloud projects add-iam-policy-binding PROJECT_ID with --member="serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com" and --role=ROLE so the service account gains permission on project resources.gcloud iam service-accounts add-iam-policy-binding on the service account email to grant roles/iam.serviceAccountUser to the user who will attach the account to resources.gcloud compute instances create INSTANCE_NAME --zone=ZONE --service-account=SERVICE_ACCOUNT_EMAIL, so traffic and API calls from that resource authenticate as the attached service account.Only after the service account exists can roles be bound to it, and only after a principal receives roles/iam.serviceAccountUser can that principal attach the account to a new instance. In production, do not grant Owner, Editor, or Viewer to the service account; instead grant a predefined role or custom role that meets the workload need, and revoke or add roles later as requirements change.
Authorizing access to and from service accounts separates what the account can access from who can use the account. A role granted to the service account defines which project, folder, or resource APIs the service account identity can call. A role granted on the service account defines which users, groups, or other service accounts can impersonate the account, create tokens as it, or attach it to resources.
Exam tip: Granting a role to a service account controls what the service account can access, while granting roles/iam.serviceAccountUser on a service account controls who can attach and use that service account.
Manage access to service accounts (opens in a new tab) as a resource requires allow-policy permissions on that account. The required permissions are:
iam.serviceAccounts.getiam.serviceAccounts.listiam.serviceAccounts.getIamPolicyiam.serviceAccounts.setIamPolicyCurrent access can be reviewed in the Google Cloud console on the Service Accounts page by selecting the project, clicking the service account email, and opening the Principals with access tab. Because an allow policy attached to a resource also applies to that resource's descendants in the resource hierarchy, project-level grants affect all service accounts in the project, while account-level grants affect only that single service account.
Attaching a service account connects the identity to a compute resource so code on that resource inherits the account's permissions. When a Compute Engine instance is created with the --service-account flag set to the service account email, code running on the instance authenticates as that service account and can access any resource the account's allow-policy bindings permit. This means a user with shell access or code-execution rights on the instance can indirectly exercise the attached account's permissions without directly impersonating it.
For workloads running on-premises or on another cloud provider, the preferred authentication path does not use a downloaded key attached to a provisioned account. The workload instead uses workload identity federation to obtain short-lived Google Cloud credentials, which avoids storing long-lived service account keys in local files, CLI configuration, or code repositories.
iam.serviceAccounts.actAs granted on a service account controls who can attach and use that account.iam.serviceAccounts.implicitDelegation on B and B holds iam.serviceAccounts.getAccessToken on C.Granting a role to a service account controls what that service account identity can access through IAM allow policies on organizations, folders, projects, and resources. Granting a role on a service account controls who can use that account, such as Service Account User with iam.serviceAccounts.actAs allowing the holder to attach the account to a resource. Because impersonation transfers all of the service account's access to the holder, highly privileged default service accounts require extra caution when granting use rights on them.
Service account impersonation lets a source principal with permission on a target service account call the Service Account Credentials API to mint a temporary access token, ID token, JSON Web Token (JWT), or blob that carries the target account's identity. By default OAuth 2.0 access tokens expire after 1 hour and the target account's existing IAM permissions control what the temporary credential can access. The source first authenticates with its own credentials, attached service account, or federated identity, then presents the short-lived token to Google APIs while audit logs record both the impersonated account and the creator identity.
Prohibited self-impersonation is using a service account's own short-lived credential to generate a new access token for the same account or to sign a blob or JWT for calling the Identity and Access Management API, the Service Account Credentials API, or the OAuth 2.0 API. Google Cloud blocks these patterns because they would let an attacker who steals one short-lived token refresh it indefinitely, and a prohibited attempt fails with FAILED_PRECONDITION. To recover, authenticate with different credentials such as end-user credentials or a different service account and then request the token, while the one exception is that a self-signed JWT can be used to generate a new access token for the same account.
An enterprise security engineer is hardening identity governance for a production Google Cloud environment. A security audit reveals that several Compute Engine virtual machines (VMs) are utilizing the Compute Engine default service account (PROJECT_NUMBER-compute@developer.gserviceaccount.com) with the Editor role (roles/editor). Additionally, multiple legacy workloads are being decommissioned, and the operations team plans to immediately delete their associated service accounts.
Which strategy should the security engineer implement to remediate the VM identities and manage the decommissioning lifecycle according to Google Cloud best practices?
Last updated