Prepare and test your skills
Prepare and test your skills
Implementing least-privilege access and identity management means every workload uses its own service account identity with only the permissions its task requires. In Google Cloud, Identity and Access Management (IAM) binds roles directly to that service account, and the account is attached to the resource running the code, such as a Cloud Build (opens in a new tab) job, App Engine version, or Google Kubernetes Engine (GKE) pod. User-managed accounts use the form SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com and are created for one purpose, while default accounts are auto-created, shared, and historically over-permissioned.
Default service accounts are shared identities that increase blast radius because many workloads inherit the same broad permissions. The Compute Engine default service account (PROJECT_NUMBER-compute@developer.gserviceaccount.com) and the App Engine default service account (PROJECT_ID@appspot.gserviceaccount.com) may automatically receive the Editor role (roles/editor) on the project, which allows reading and modifying almost all resources. Cloud Build carries the same risk when no account is specified, because it may select an account with access to Cloud Source Repositories and any Cloud Storage bucket in the project. Traffic flows from the workload to Google Cloud APIs under the attached service account identity, so compromise of one workload can affect data owned by all workloads sharing that default account.
Fine-grained IAM grants the minimal predefined role to a specific service account identity instead of granting broad Owner, Editor, or Viewer roles. The binding adds the service account as a member for one role, for example granting roles/cloudtranslate.user to serviceAccount:SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com, so only that identity can use the permission. Scope is reduced further by granting the role on a single bucket, Artifact Registry repository, or dataset, by adding IAM Conditions, and by choosing task-specific roles over primitive roles. A function-build account shows this pattern with only the permissions the build needs:
roles/logging.logWriter) allows the build to send build logs to Cloud Logging.roles/artifactregistry.writer) allows the build to store images in repositories such as gcf-artifacts and cloud-run-source-deploy.roles/storage.objectViewer) allows the build to retrieve function source, scoped by condition to buckets starting with run-sources-*, gcf-v2-sources-*, and gcf-v2-uploads-*.Event-driven workloads use the same model, where a testing account receives only Eventarc Event Receiver (roles/eventarc.eventReceiver), Workflows Invoker (roles/workflows.invoker), and Logs Writer. For production, that testing identity is replaced by a new user-managed account that holds only the minimum required permissions.
Least-privilege identities for App Engine, Cloud Build, and GKE replace a shared default identity with a per-workload identity that limits which APIs the workload can call. In App Engine, a per-version service account is the identity for one deployed version, while an app-level custom default is the fallback identity for all services without a per-version account. If neither custom identity is set, App Engine falls back to the auto-created App Engine default account. Choose a per-version account when one version needs different permissions, because requests from that version then flow under its own identity instead of the shared app identity.
| App Engine identity | Scope of identity | Choose when |
|---|---|---|
| Per-version service account | One service version only | The version needs permissions that differ from the app default |
| App-level custom default service account | All services without a per-version account | One least-privilege identity can cover the whole app |
| Auto-created App Engine default service account | All services in the app | Only for legacy use; replace to remove Editor-level sharing |
Removing the default creates dependencies that must be replaced explicitly. App Engine flexible environment instances depend on Logs Writer, Monitoring Metric Writer, and Storage Object Viewer, so those three roles must be granted to the replacement account when Editor is removed. Cloud Build follows the same separation by configuring a user-specified account for building and pushing images to Artifact Registry. For GKE, development clusters that use the Compute Engine default account with full API access overprovision permissions because every workload on the node shares the node identity, and node account and scope settings cannot be changed after cluster creation. Production GKE associates a Kubernetes account with a Google account through Workload Identity in order:
.spec.serviceAccountName in the Kubernetes Deployment so pods run under that Kubernetes identity.Organization policy guardrails prevent new broad grants and disable risky defaults so least privilege persists across projects and folders. Enforcing iam.automaticIamGrantsForDefaultServiceAccounts blocks the automatic Editor grant to default service accounts, and organizations created after May 3, 2024 enforce this constraint by default. Related Cloud Build constraints cloudbuild.useBuildServiceAccount and cloudbuild.useComputeServiceAccount set to Not Enforced prevent use of the legacy build account and the default Compute Engine account for builds. Security Command Center flags violations as OVER_PRIVILEGED_ACCOUNT when a GKE node pool uses the default account and as PRIMITIVE_ROLES_USED when an account ending in iam.gserviceaccount.com holds roles/owner, roles/editor, or roles/viewer.
Downgrading an existing over-privileged account requires validation before revoking access. Policy Simulator first shows the impact of replacing Editor with less permissive roles, then the appropriate granular roles are granted and the primitive role is revoked. This order — first simulate, then grant minimal roles, then revoke the broad role — preserves logging, monitoring, and storage access while shrinking the trust boundary to the single workload that depends on the account.
Exam tip: The automatic Editor grant to default service accounts is blocked by iam.automaticIamGrantsForDefaultServiceAccounts, enforced by default only for organizations created after May 3, 2024; older organizations must enforce it explicitly and then manually replace Editor.
Monitoring, auditing, and enforcing security policies for service accounts means making service account use visible, detecting risky or inactive accounts, and blocking insecure defaults. In Google Cloud, Cloud Audit Logs records who acted as which service account, Security Command Center (SCC) (opens in a new tab) surfaces misconfigurations and dormant-account activity, and organization policy constraints prevent default accounts from inheriting broad permissions. Together they support least privilege and a disable-before-delete lifecycle.
Cloud Audit Logs is the authoritative record of service account activity, capturing when an action happened and which service account performed it. Admin Activity logs track configuration changes, while Data Access audit logs must be enabled for IAM APIs to capture reads and token operations such as impersonation, key creation, and short-lived credential issuance. Because impersonation lets a user act with a service account's permissions, the log may show only the service account and obscure the human actor behind it.
Traceability depends on using dedicated, single-purpose accounts for each workload. Cloud Audit Logs records the service account email but not the application that used it, so sharing one account across applications makes it impossible to trace activity to the correct workload. To close that gap, avoid long-lived keys when possible, correlate CI/CD deployment history with log timestamps, and have applications write custom entries that identify the end user. For retention, export entries through a log sink to long-term storage and protect the destination bucket with Bucket Lock retention policies. Log-based alerts extend auditing into enforcement by creating metric filters and alerting policies for project ownership assignments, audit configuration changes, custom role changes, firewall and network changes, and Cloud Storage IAM changes, so privilege escalation triggers notification.
Detection of inactive service accounts combines usage telemetry with posture findings to decide whether to disable an account. Three complementary signals cover different time windows and levels of detail:
| Detection source | What it reports | Inactivity threshold |
|---|---|---|
| Service account insights | Accounts in a project that have not authenticated | Past 90 days |
| Activity Analyzer | Most recent authentication or last use of an account or key | Last-used timestamp per account or key |
| Event Threat Detection in Security Command Center Premium | Dormant account triggering an action after long inactivity | Inactive for more than 180 days |
Service account insights and Activity Analyzer support routine cleanup, while Event Threat Detection treats post-dormancy use as a potential compromise signal. After a dormant account is used, it is no longer considered dormant. General usage metrics supplement these tools by tracking account and key trends over time.
Security Command Center continuously checks posture against controls that matter for service accounts. Key findings to monitor include accounts with admin privileges, user-managed keys where only Google-managed keys should exist, user-managed keys not rotated within 90 days, users granted Service Account User or Service Account Token Creator at project level, missing separation of duties, disabled Cloud Audit Logging, and missing log sinks. Configuring alerts at the organization level routes these findings to the team that can disable keys, remove bindings, or revoke over-broad grants.
Exam tip: Service account insights flags inactivity after 90 days, while Event Threat Detection flags a dormant account only after more than 180 days of inactivity when it triggers an action.
Enforcing guardrails for default service accounts prevents those accounts from starting with excessive privilege. The App Engine default and Compute Engine default accounts are auto-created to let services deploy jobs that access other resources. Depending on policy configuration, they may automatically receive Editor (roles/editor) on the project, which allows reading and modifying all resources in the project.
The organization policy constraint constraints/iam.automaticIamGrantsForDefaultServiceAccounts blocks those automatic Editor grants. Enforce the constraint on the organization or folder node to apply it to multiple projects at once, and for organizations created after May 3, 2024 it is enforced by default. Google Cloud services use service agents, not default service accounts, to access resources on your behalf, so blocking the grant does not break platform operation but requires explicit grants for needed roles.
If a default account already has Editor, replace it in a safe order. First use Policy Simulator to preview removal of Editor, then grant and revoke roles to reach least privilege, and use role recommendations when the binding is older than 90 days to find unused permissions. For lifecycle enforcement, disable an unused account first and delete it only after a waiting period confirms nothing breaks. Disabled accounts retain IAM bindings and can be re-enabled, while deleted default accounts cannot be recreated and a recreated account with the same email receives a new internal unique ID that does not inherit old bindings.
Securing and rotating service account credentials means controlling long-lived keys and replacing them with short-lived, federated credentials wherever possible. Service account keys (opens in a new tab) are long-lived private JSON files where possession of the file equals identity as the account. An application signs a JSON Web Token (JWT) with the private key, exchanges the JWT for an OAuth 2.0 access token, and calls Google Cloud APIs with all permissions granted to the account. Short-lived credentials work differently because Google manages the signing key and issues tokens automatically for attached accounts or impersonation sessions.
Service account keys are risky because any holder of the private key file can authenticate as the service account. The key can live in a gcloud CLI configuration directory after gcloud auth activate-service-account, on a local file system, or in a code repository, and any process that can read the file can mint access tokens. Malware commonly targets paths such as ~/.config/gcloud/ to harvest Application Default Credentials and key material, and a stolen key bypasses perimeter controls. Keys have no 2-Step Verification, no session limits, and no automatic expiry, so a stolen key gives persistent access until disabled or deleted. If a key came from an external source it must be validated before use, and if creation is blocked in the console or CLI, creation may be disabled by organization policy.
A safer authentication method removes the long-lived private key and lets Google issue short-lived tokens after verifying a trusted identity. Workloads in Google Cloud should use an attached service account on the Compute Engine instance or other resource, while containers in GKE should use Workload Identity Federation for GKE to attach accounts to pods. Local development should use user credentials or impersonate a service account with user credentials, and on-premises or other-cloud workloads should use Workload Identity Federation (WIF) when the external provider is supported. Create a user-managed key only when no federated or attached-identity option can reach the workload.
| Workload location | Preferred credential | Long-lived key required |
|---|---|---|
| Google Cloud resource such as Compute Engine | Attached service account with IAM roles | No, tokens come from the metadata server |
| GKE pods | Workload Identity Federation for GKE mapping Kubernetes ServiceAccount to IAM service account | No, pod receives a short-lived projected token |
| On-premises or other cloud with supported external provider | Workload Identity Federation to a Google Cloud service account | No, external token is exchanged for short-lived Google token |
| Single-user workstation or Cloud Shell needing consistency | Service account impersonation with user credentials | No, user credential brokers the short-lived token |
When impersonation or federation is used, the trust boundary sits between the calling identity and the target service account, and access depends on iam.serviceAccounts.actAs or a WIF pool binding on that specific account.
Key rotation is the process of replacing an active service account key with a new key and then invalidating the old key. Rotation limits how long a leaked key stays useful because attackers may take days or weeks to discover a leak, so a routinely rotated key is more likely to be invalid. Google recommends rotating every user-managed key at least every 90 days, and rotating immediately when compromise is suspected.
To rotate keys safely, follow the documented order so applications do not break:
Disabling preserves the ability to re-enable quickly, while deleting is permanent except through undelete of the whole account within its retention window. Never delete and recreate an account with the same name as a shortcut, because the new account receives a different internal unique ID and old bindings that show as deleted: will not apply to it.
Exam tip: Rotate user-managed service account keys at least every 90 days and immediately on suspected compromise; disable the old key first to validate, then delete it.
Auditing key age, usage, and dormancy means tracking both creation time and last authentication so unused or over-aged keys can be disabled before abuse. Cloud Asset Inventory can search all iam.googleapis.com/ServiceAccountKey assets by createTime across an organization to find keys created more than 90 days ago, and those results can drive notifications through Essential Contacts. Age alone is not enough, so usage signals must confirm whether a key or account is still needed:
For single-purpose accounts tied to one VM or application, the account lifecycle follows its workload and the account should be disabled as soon as the associated resource is disabled or deleted.
Workload Identity Federation (WIF) eliminates service account keys by letting an external workload prove its existing identity and receive short-lived Google credentials. Data flows from the external workload to its external identity provider for authentication, then from the workload to the configured workload identity pool with that provider token, then from the pool through an IAM allow-policy mapping to impersonation of a designated service account. The Security Token Service exchanges the trusted external token for a short-lived Google access token scoped to that account, so no private key file is stored, distributed, or rotated.
This dependency reverses the usual secret-management problem because the application no longer needs a stored Google secret to fetch a Google secret. Storing a key in Secret Manager, HashiCorp Vault, Azure Key Vault, or AWS Secrets Manager still leaves a long-lived key to protect, and Google does not recommend Secret Manager for this case because an application with a Google-recognized identity to read the secret could use that identity directly. Centralized rotation in HashiCorp Vault can automate replacement when keys cannot yet be removed, but federation removes the rotation burden for CI/CD systems, on-premises jobs, and multi-cloud workloads. Choose federation when the workload has a supportable external provider, and reserve manually rotated keys only for isolated systems with no trusted identity path to Google Cloud.
roles/editor), allowing read and write access to almost all project resources.iam.automaticIamGrantsForDefaultServiceAccounts blocks automatic Editor grants to default service accounts and is enforced by default for organizations created after May 3, 2024.The Compute Engine default service account and App Engine default service account are risky because they are shared identities that may automatically receive the Editor role on the project, which allows reading and modifying almost all resources. Because traffic from workloads to Google Cloud APIs flows under the attached service account identity, compromise of one workload sharing the default account can affect data owned by all workloads using it.
The constraint blocks the automatic Editor grant to default service accounts so new projects do not start with excessive privilege. It is enforced by default for organizations created after May 3, 2024, while older organizations must enforce it explicitly and then manually replace Editor with least-privilege roles.
You should use Workload Identity Federation (WIF) when the on-premises or other-cloud workload has a supportable external provider because it lets the workload prove its existing identity and receive a short-lived Google access token without storing a long-lived private key file. You should create a user-managed key only when no federated or attached-identity option can reach the workload.
User-managed service account keys must be rotated at least every 90 days and immediately when compromise is suspected. Safe rotation follows create a new key while the old key is still active, replace keys in applications, disable the old key and monitor logs and error rates, then delete the old key only after monitoring shows no continued use.
A multinational enterprise is hardening its Google Cloud environment against identity compromise and unauthorized privilege escalation. The security operations team identified that attackers might attempt to chain service account impersonations or exploit dormant and default service accounts to perform unauthorized administrative actions. The team needs to establish a comprehensive strategy to meet the following requirements:
Which combination of controls and tools should the security engineer implement?
Last updated