Domain 5: Configuring Access and Security (~17.5%)
Domain 5 accounts for approximately 17.5% of the Associate Cloud Engineer exam, translating to roughly 9-10 questions. This domain is entirely hands-on: you must know how to configure IAM policies, manage service accounts, and apply the principle of least privilege using gcloud commands. The exam tests two sub-domains -- IAM management and service account management -- with heavy emphasis on practical implementation and security best practices.
5.1 Managing Identity and Access Management (IAM)
The IAM Model: Who / What / Which
IAM controls access to Google Cloud resources through three components:
| Component | Question | IAM Term | Examples |
|---|---|---|---|
| Who | Who is making the request? | Principal (formerly "member") | Google Account, service account, Google Group, Google Workspace domain, Cloud Identity domain, allUsers, allAuthenticatedUsers |
| What | What can they do? | Role (collection of permissions) | roles/storage.objectViewer, roles/compute.admin |
| Which | On which resource? | Resource | Project, Cloud Storage bucket, Compute Engine instance, BigQuery dataset |
Permissions follow the format service.resource.verb (e.g., compute.instances.delete, storage.objects.get). You never grant permissions directly -- you grant roles that bundle permissions together.
IAM Policy Structure
An IAM allow policy is a JSON/YAML object that binds principals to roles on a resource. Every resource has exactly one allow policy.
{
"bindings": [
{
"role": "roles/storage.objectViewer",
"members": [
"user:alice@example.com",
"group:data-team@example.com"
]
},
{
"role": "roles/storage.objectAdmin",
"members": [
"serviceAccount:my-app@my-project.iam.gserviceaccount.com"
],
"condition": {
"title": "Business hours only",
"expression": "request.time.getHours('America/New_York') >= 9 && request.time.getHours('America/New_York') <= 17"
}
}
],
"etag": "BwWKmjvelug=",
"version": 3
}
Key elements:
- bindings: Array of role-to-members mappings
- role: The IAM role being granted
- members: List of principals receiving the role. Prefix indicates type:
user:,serviceAccount:,group:,domain:, or the special valuesallUsers(anyone on the internet) andallAuthenticatedUsers(any authenticated Google account) - condition: Optional CEL expression restricting when the binding applies
- etag: Concurrency control -- prevents overwriting concurrent policy updates
- version: Must be
3if any binding uses conditions; otherwise1
Exam trap:
allUsersmeans literally anyone, including unauthenticated users.allAuthenticatedUsersmeans any Google account -- including personal Gmail accounts outside your organization. Both are dangerous in production. If the exam describes a publicly accessible resource,allUsersis the member value.
Viewing and Managing IAM Policies
Essential gcloud commands for the exam:
# View project IAM policy
gcloud projects get-iam-policy PROJECT_ID
# View organization IAM policy
gcloud organizations get-iam-policy ORG_ID
# View folder IAM policy
gcloud resource-manager folders get-iam-policy FOLDER_ID
# Add a role binding
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="user:alice@example.com" \
--role="roles/storage.objectViewer"
# Remove a role binding
gcloud projects remove-iam-policy-binding PROJECT_ID \
--member="user:alice@example.com" \
--role="roles/storage.objectViewer"
# Set the entire policy from a JSON file (use with caution)
gcloud projects set-iam-policy PROJECT_ID policy.json
# View IAM policy for a specific resource (e.g., a bucket)
gcloud storage buckets get-iam-policy gs://BUCKET_NAME
Exam trap:
add-iam-policy-bindingis additive -- it adds to the existing policy.set-iam-policyreplaces the entire policy. Usingset-iam-policywithout the currentetagcan overwrite other people's changes. The exam favorsadd-iam-policy-bindingandremove-iam-policy-bindingfor safe modifications.
Role Types
Three categories of roles exist, and the exam heavily tests when to use each.
| Role Type | Format | Managed By | Scope | Production Use |
|---|---|---|---|---|
| Basic | roles/owner, roles/editor, roles/viewer |
Thousands of permissions across all services | No. Too broad. | |
| Predefined | roles/service.roleName |
Scoped to a specific service | Yes. Default choice. | |
| Custom | projects/PROJECT_ID/roles/roleName or organizations/ORG_ID/roles/roleName |
You | Only the permissions you specify | Yes. When predefined is too broad. |
Basic Roles (Avoid in Production)
| Role | Permissions | Key Risk |
|---|---|---|
Viewer (roles/viewer) |
Read-only access to all resources in the project | Exposes all data |
Editor (roles/editor) |
All Viewer permissions + create/update/delete for most resources | Can modify/delete almost anything; cannot change IAM policies or billing |
Owner (roles/owner) |
All Editor permissions + manage IAM policies + set up billing | Full control including granting access to others |
Basic roles are discouraged in production because they grant permissions across every service in the project. The Editor role alone includes thousands of permissions. The documentation explicitly states: "In production environments, do not grant basic roles unless there is no alternative."
Important restrictions on basic roles:
- Legacy basic roles (
roles/viewer,roles/editor,roles/owner) cannot use IAM Conditions. If you need conditional access, use predefined or custom roles. - Owner role can only be granted to Google Accounts, service accounts within your organization, or Google Groups in your organization.
Exam trap: Editor cannot modify IAM policies or manage billing. If a question asks "a user with Editor role needs to grant access to another user," the answer is they cannot -- they need Owner or a role with
resourcemanager.projects.setIamPolicy.
Predefined Roles -- Common Examples
| Service | Role | Permissions Summary |
|---|---|---|
| Compute Engine | roles/compute.viewer |
Read-only access to Compute Engine resources |
roles/compute.instanceAdmin.v1 |
Full control of instances, instance groups, disks, snapshots | |
roles/compute.networkAdmin |
Create/modify/delete networking resources (except firewall rules and SSL certs) | |
roles/compute.securityAdmin |
Create/modify/delete firewall rules and SSL certificates | |
| Cloud Storage | roles/storage.objectViewer |
Read objects and list bucket contents |
roles/storage.objectCreator |
Create objects (cannot view or delete) | |
roles/storage.objectAdmin |
Full control of objects | |
roles/storage.admin |
Full control of buckets and objects | |
| BigQuery | roles/bigquery.dataViewer |
Read data and metadata from datasets and tables |
roles/bigquery.dataEditor |
Read and modify data in datasets and tables | |
roles/bigquery.jobUser |
Run BigQuery jobs (queries) | |
roles/bigquery.user |
Run jobs + list datasets (but not read data unless dataViewer is also granted) | |
| GKE | roles/container.viewer |
Read-only access to GKE clusters and Kubernetes API objects |
roles/container.developer |
Access to Kubernetes API objects within clusters | |
roles/container.admin |
Full management of clusters and Kubernetes API objects | |
| Cloud Run | roles/run.invoker |
Invoke (call) Cloud Run services |
roles/run.developer |
Deploy and manage Cloud Run services (no IAM changes) | |
| Cloud Functions | roles/cloudfunctions.invoker |
Invoke Cloud Functions |
roles/cloudfunctions.developer |
Create and update functions (no IAM or deletion) |
Exam trap:
roles/bigquery.userdoes not include permission to read data in datasets. You needroles/bigquery.dataViewerin addition toroles/bigquery.userfor a user to run queries and read data. The exam frequently tests this distinction.
Custom IAM Roles
Create custom roles when predefined roles grant more permissions than needed. Custom roles can be created at the organization or project level -- never at the folder level.
# Create a custom role at the project level
gcloud iam roles create myCustomRole \
--project=PROJECT_ID \
--title="My Custom Role" \
--description="Limited compute access" \
--permissions="compute.instances.get,compute.instances.list" \
--stage=GA
# Create a custom role at the organization level
gcloud iam roles create myCustomRole \
--organization=ORG_ID \
--title="My Custom Role" \
--permissions="compute.instances.get,compute.instances.list"
# List custom roles
gcloud iam roles list --project=PROJECT_ID
# Update a custom role (add permissions)
gcloud iam roles update myCustomRole \
--project=PROJECT_ID \
--add-permissions="compute.instances.start"
Custom role constraints:
| Constraint | Detail |
|---|---|
| Launch stages | EAP, ALPHA, BETA, GA, DEPRECATED, DISABLED. A DISABLED role still appears in policies but grants no permissions. |
| Permissions coverage | Not all permissions can be used in custom roles. Permissions have support levels: SUPPORTED, TESTING, NOT_SUPPORTED. |
| Scope | Project-level custom roles are usable only in that project. Organization-level custom roles are usable in any project in the org. Project-level roles cannot include folder-specific or organization-specific permissions. |
| Limit | Maximum 300 custom roles per organization, 300 per project. |
| Role ID | Up to 64 bytes, alphanumeric plus underscores/periods. Once deleted, a role ID cannot be reused. |
Exam trap: Custom roles cannot be created at the folder level. Only project or organization level. Also: if a principal can edit custom roles in a project, they can add any permission to any custom role in that project -- this is a significant security consideration.
Policy Inheritance Through the Resource Hierarchy
IAM policies are additive and inherited down the resource hierarchy:
Organization -> Folder -> Project -> Resource
The effective policy on a resource is the union of all policies set on it and all its ancestors. A permission granted at the organization level cannot be revoked at the project level using allow policies alone.
| Rule | Implication |
|---|---|
| Policies are additive | If a parent grants access, a child cannot remove it via allow policies |
| More permissive wins | If org grants Viewer and project grants Editor, the effective role is Editor |
| Deny overrides allow | Deny policies can block permissions even when allow policies grant them |
| Resources inherit from all ancestors | A bucket inherits policies from its project, folder, and organization |
Exam trap: A user granted
roles/editorat the organization level has Editor on every project. You cannot fix this by removing them at the project level. You must either remove the org-level binding or create a deny policy.
IAM Deny Policies
Deny policies let you explicitly block specific permissions, overriding any allow policies. IAM always checks deny policies before checking allow policies.
Policy evaluation order:
- Organization policy constraints -- resource creation restrictions
- Deny policies -- checked first; if a deny rule matches, access is denied regardless of allow policies
- Allow policies -- checked only if no deny rule blocked the request
Deny policy structure:
{
"rules": [
{
"denyRule": {
"deniedPrincipals": ["principalSet://goog/public:all"],
"exceptionPrincipals": ["principalSet://goog/group/admins@example.com"],
"deniedPermissions": [
"cloudresourcemanager.googleapis.com/projects.delete"
],
"denialCondition": {
"title": "Only prod tagged resources",
"expression": "resource.matchTag('env', 'prod')"
}
}
}
]
}
Key deny policy facts:
| Fact | Detail |
|---|---|
| Attachment points | Organizations, folders, and projects. Deny cascades downward and cannot be overridden by lower-level allow policies. |
| deniedPrincipals | Who is denied. |
| exceptionPrincipals | Exemptions from the deny rule. |
| deniedPermissions | Full v2 format: SERVICE_FQDN/RESOURCE.ACTION (e.g., cloudresourcemanager.googleapis.com/projects.delete). |
| Permission groups | Wildcards like SERVICE_FQDN/RESOURCE.* deny all permissions for a resource type. SERVICE_FQDN/*.* denies all service permissions. These automatically include future matching permissions. |
| Conditions | CEL expressions, but restricted to resource tag functions only. |
| Limits | Maximum 500 deny policies per resource; up to 500 total deny rules across all policies per resource. |
Common use cases for deny policies:
- Centralizing admin privileges: Deny custom role management to everyone except a designated admin group
- Creating exceptions: Grant broad permissions at org level, then selectively deny on specific resources (e.g., block access to production projects)
- Tag-based guardrails: Deny project deletion unless the resource is tagged for decommissioning
Exam trap: Deny policies are the only way to block inherited permissions from a parent resource. If an allow policy at the org level grants overly broad access, a deny policy at the project or folder level is how you restrict it.
IAM Conditions
IAM Conditions add attribute-based access control to role bindings. A condition is a CEL (Common Expression Language) expression that must evaluate to true for the binding to take effect.
A condition contains three fields:
title(required): Human-readable identifierdescription(optional): Explanation of the conditionexpression(required): CEL logic statement
Common condition attributes:
| Attribute Category | Attribute | Example Expression |
|---|---|---|
| Time | request.time |
request.time < timestamp("2026-03-01T00:00:00Z") |
| Resource name | resource.name |
resource.name.startsWith("projects/my-project/zones/us-central1-a/instances/") |
| Resource type | resource.type |
resource.type == "compute.googleapis.com/Instance" |
| Resource service | resource.service |
resource.service == "storage.googleapis.com" |
| Resource tags | resource.matchTag() |
resource.matchTag("env", "production") |
| Destination IP/port | destination.ip, destination.port |
destination.ip == "10.0.0.1" |
| URL host/path | request.url.host |
request.url.host == "example.com" |
Important condition limitations:
- Cannot be used with legacy basic roles (
roles/owner,roles/editor,roles/viewer) - Cannot apply conditions when granting access to
allUsersorallAuthenticatedUsers - Cloud Storage requires uniform bucket-level access enabled to use conditions on buckets
- An unconditional role binding overrides a conditional one for the same role -- if a principal already has the role unconditionally, adding a conditional binding has no effect
Exam trap: When a policy uses conditions, the policy version must be set to
3. Version1policies silently drop conditions, which can lead to granting broader access than intended. The exam tests this.
IAM Recommender
IAM Recommender analyzes permission usage patterns and recommends removing or replacing overly broad roles. It identifies:
- Roles with permissions never used in the last 90 days
- Opportunities to replace basic roles with more granular predefined roles
- Service accounts with excess permissions
Use IAM Recommender to enforce the principle of least privilege continuously, not just at initial setup.
5.2 Managing Service Accounts
What Service Accounts Are
Service accounts are special accounts used by applications and workloads -- not humans -- to authenticate to Google Cloud APIs. Each service account has a unique email address as its identifier.
| Characteristic | User Account | Service Account |
|---|---|---|
| Used by | Humans | Applications, VMs, services |
| Authentication | Password + 2SV | Keys, tokens, attached identity |
| Email format | user@domain.com |
NAME@PROJECT_ID.iam.gserviceaccount.com |
| Google Workspace | Belongs to a domain | Does not belong to a domain; cannot own Workspace assets |
| Quota | N/A | 100 per project (default; can request increase) |
Types of Service Accounts
| Type | Created By | Example | Key Facts |
|---|---|---|---|
| User-managed | You | my-app@my-project.iam.gserviceaccount.com |
You control permissions and lifecycle. Preferred. |
| Default | Google (when enabling APIs) | PROJECT_NUMBER-compute@developer.gserviceaccount.com (Compute Engine default) |
Automatically granted roles/editor on the project. Dangerously overprivileged. |
| Service agents | Google (internal) | Various @*.gserviceaccount.com |
Google-managed; used internally by GCP services. Do not modify. |
Exam trap: The Compute Engine and App Engine default service accounts are granted
roles/editorwhen created. This means any VM using the default service account has Editor-level access to the entire project. The exam expects you to know this is a security risk and that you should create dedicated user-managed service accounts with minimum permissions instead.
Creating and Managing Service Accounts
# Create a service account
gcloud iam service-accounts create my-app-sa \
--display-name="My App Service Account" \
--description="Service account for my application"
# List service accounts in a project
gcloud iam service-accounts list --project=PROJECT_ID
# Grant a role to the service account (on a project)
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:my-app-sa@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/storage.objectViewer"
# Disable a service account (recommended before deletion)
gcloud iam service-accounts disable my-app-sa@PROJECT_ID.iam.gserviceaccount.com
# Delete a service account
gcloud iam service-accounts delete my-app-sa@PROJECT_ID.iam.gserviceaccount.com
Best practice: Disable unused service accounts before deleting them. This lets you verify nothing breaks before permanent deletion. Google also provides service account insights (90-day inactivity detection) and Activity Analyzer to identify unused accounts.
Exam trap: Recreating a deleted service account with the same email address does NOT restore old role bindings or resource attachments. Each service account receives a unique internal ID at creation time. Old bindings reference the old ID and will not apply to the new account.
Attaching Service Accounts to Resources
The most common and secure way for applications to authenticate is by attaching a service account to the resource running the application. The application automatically receives credentials without needing keys.
# Create a VM with a specific service account
gcloud compute instances create my-instance \
--service-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com \
--scopes=cloud-platform
# Deploy a Cloud Run service with a specific service account
gcloud run deploy my-service \
--image=gcr.io/PROJECT_ID/my-image \
--service-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com
# Deploy a Cloud Function with a specific service account
gcloud functions deploy my-function \
--runtime=python311 \
--service-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com
The --scopes flag on Compute Engine is a legacy access control mechanism. When set to cloud-platform, IAM roles alone determine what the service account can do. The exam may present scopes as a distractor -- IAM roles are the primary access control.
Managing IAM of a Service Account
A service account is both an identity and a resource. As an identity, it acts on resources. As a resource, other principals need IAM permissions to use or manage it.
| Role on the Service Account | Role ID | What It Grants |
|---|---|---|
| Service Account User | roles/iam.serviceAccountUser |
Permission to attach the SA to resources (e.g., deploy a VM as that SA) |
| Service Account Token Creator | roles/iam.serviceAccountTokenCreator |
Permission to create tokens and impersonate the SA |
| Service Account Admin | roles/iam.serviceAccountAdmin |
Full management: view, edit, disable, delete the SA |
| Service Account Key Admin | roles/iam.serviceAccountKeyAdmin |
Create and manage service account keys |
# Grant a user permission to use (attach) a service account
gcloud iam service-accounts add-iam-policy-binding \
my-app-sa@PROJECT_ID.iam.gserviceaccount.com \
--member="user:alice@example.com" \
--role="roles/iam.serviceAccountUser"
Exam trap: To attach a service account to a Compute Engine instance, the user needs both
roles/iam.serviceAccountUseron the service account AND permission to create instances (roles/compute.instanceAdmin.v1or similar) on the project. Having only one of the two is insufficient.
Service Account Impersonation
Service account impersonation allows an authenticated principal to act as a service account temporarily without using service account keys. The principal's actions are performed using the service account's identity and permissions.
Required role: roles/iam.serviceAccountTokenCreator on the target service account.
# Run a gcloud command as a service account
gcloud storage ls gs://my-bucket \
--impersonate-service-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com
# Set impersonation as default for all gcloud commands
gcloud config set auth/impersonate_service_account \
my-app-sa@PROJECT_ID.iam.gserviceaccount.com
Use cases:
- Temporary elevated access -- handle an incident using a privileged SA without permanent role grants
- Testing -- verify that a service account's permissions are sufficient before deployment
- Local development -- authenticate as a service account without downloading keys
- Audit trail -- both the caller's identity and the impersonated SA are recorded in audit logs
Exam trap: Service account impersonation is not available in the Google Cloud Console -- only via
gcloud, client libraries, and REST APIs. Console actions always use the signed-in user's own identity.
Short-Lived Service Account Credentials
Short-lived credentials are the preferred alternative to service account keys. They expire automatically (typically within 1 hour) and do not require manual key management.
| Method | API | Result | Use Case |
|---|---|---|---|
generateAccessToken |
IAM Credentials API | OAuth 2.0 access token (default: 1 hour) | Authenticate API requests |
generateIdToken |
IAM Credentials API | OIDC identity token | Invoke Cloud Run, Cloud Functions, IAP-protected resources |
signBlob |
IAM Credentials API | Signed binary data | Create signed URLs for Cloud Storage |
signJwt |
IAM Credentials API | Signed JWT | Custom authentication flows |
The --impersonate-service-account flag in gcloud uses generateAccessToken behind the scenes.
Service Account Keys: Why to Avoid Them
Service account keys are long-lived credentials (RSA key pairs) that can be used to authenticate as a service account. Google strongly recommends avoiding them.
| Risk | Detail |
|---|---|
| Key leakage | Keys checked into source control, left in logs, or stored insecurely can be exploited |
| No expiration | Keys are valid until explicitly revoked -- compromised keys remain dangerous indefinitely |
| Management burden | You must rotate, track, and audit keys manually |
| Audit gaps | Harder to trace actions to the person who used the key |
When keys may be necessary: On-premises applications or third-party systems that cannot use Workload Identity Federation or any other keyless method.
# Create a key (avoid if possible)
gcloud iam service-accounts keys create key.json \
--iam-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com
# List keys for a service account
gcloud iam service-accounts keys list \
--iam-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com
# Delete a key
gcloud iam service-accounts keys delete KEY_ID \
--iam-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com
Exam trap: The exam strongly favors answers that avoid service account keys. If a question offers both "create a service account key" and "use Workload Identity Federation" or "attach a service account to the resource," the keyless option is almost always correct.
Workload Identity Federation
Workload Identity Federation allows external workloads (AWS, Azure, on-premises, GitHub Actions, GitLab CI) to access Google Cloud resources without service account keys. It exchanges external credentials for short-lived GCP tokens using the OAuth 2.0 token exchange specification (RFC 8693).
How it works:
- External workload obtains a credential from its identity provider (AWS STS, Azure AD, OIDC, SAML)
- Workload presents credential to Google's Security Token Service (STS)
- STS validates the credential and returns a federated token
- Federated token is exchanged for a short-lived GCP access token (via service account impersonation or direct resource access)
- Workload uses the access token to call GCP APIs
Key components:
| Component | Purpose |
|---|---|
| Workload identity pool | Container that manages external identities. Create one per environment (dev, staging, prod). |
| Workload identity pool provider | Configuration describing the relationship with a specific IdP (AWS, Azure AD, OIDC provider) |
| Attribute mapping | CEL expressions that map external IdP claims to Google token attributes (google.subject, google.groups, attribute.NAME). google.subject is required and has a max of 127 characters. |
| Attribute conditions | CEL expressions that filter which external identities can authenticate. Prevents the confused deputy problem by restricting which identities from a public IdP can use your pool. |
Two access models:
| Model | How It Works | Required Role |
|---|---|---|
| Direct resource access | Grant external identities IAM roles directly on Google Cloud resources | Standard IAM roles on the target resource |
| Service account impersonation | External identities assume a service account | roles/iam.workloadIdentityUser on the service account |
Supported identity providers: AWS, Azure AD, any OIDC provider, any SAML 2.0 provider, GitHub Actions, GitLab CI, Kubernetes clusters, Okta, AD FS, X.509 certificates.
Workload Identity for GKE
Workload Identity for GKE maps Kubernetes service accounts to Google Cloud service accounts, enabling pods to authenticate to GCP APIs without service account keys.
# Enable Workload Identity on a GKE cluster
gcloud container clusters update my-cluster \
--workload-pool=PROJECT_ID.svc.id.goog
# Create a Kubernetes service account
kubectl create serviceaccount my-ksa --namespace=default
# Create a GCP service account
gcloud iam service-accounts create my-gsa
# Bind the K8s SA to the GCP SA
gcloud iam service-accounts add-iam-policy-binding \
my-gsa@PROJECT_ID.iam.gserviceaccount.com \
--member="serviceAccount:PROJECT_ID.svc.id.goog[default/my-ksa]" \
--role="roles/iam.workloadIdentityUser"
# Annotate the K8s SA with the GCP SA email
kubectl annotate serviceaccount my-ksa \
--namespace=default \
iam.gke.io/gcp-service-account=my-gsa@PROJECT_ID.iam.gserviceaccount.com
Pods using the annotated Kubernetes service account automatically authenticate as the linked GCP service account. No keys are involved.
Exam trap: Workload Identity for GKE requires the cluster to have Workload Identity enabled (
--workload-pool). The mapping is bidirectional: the GCP SA must grantroles/iam.workloadIdentityUserto the K8s SA, and the K8s SA must be annotated with the GCP SA email. Missing either side breaks the link.
5.3 Additional Security Topics (Cross-Cutting)
These topics are not listed as explicit sub-domains but regularly appear in ACE exam questions.
Cloud KMS and Encryption
Cloud KMS is Google Cloud's cryptographic key management service. It manages encryption keys for Google Cloud services and custom applications.
Key hierarchy:
| Level | Description |
|---|---|
| Key Ring | Logical container that organizes keys by location. Cannot be deleted once created. |
| Crypto Key | An individual encryption key within a key ring. Can have multiple versions. |
| Key Version | A specific instance of a key containing the actual cryptographic material. Has its own state (enabled, disabled, destroyed). |
Encryption options comparison:
| Option | Key Controller | Where Keys Reside | Use Case | Supported Services |
|---|---|---|---|---|
| Google-managed (GMEK) | Google's internal Keystore | Standard workloads; zero management overhead | All services (default) | |
| Customer-Managed (CMEK) | Customer via Cloud KMS | Cloud KMS (software, HSM, or external) | Regulatory compliance; customer controls lifecycle | 40+ services |
| Customer-Supplied (CSEK) | Customer provides key material | Customer infrastructure; never stored permanently by Google | Maximum control | Cloud Storage and Compute Engine only |
| Cloud EKM (External) | Customer via external KMS | External key management provider; never sent to Google | Sovereignty and trust requirements | 30+ services |
Key facts for the exam:
- All data in Google Cloud is encrypted at rest by default using Google-managed keys. CMEK does not add encryption -- it changes who controls the keys.
- CMEK uses envelope encryption: Cloud KMS manages the Key Encryption Key (KEK) that wraps Data Encryption Keys (DEKs) managed by the service. This separation enables crypto-shredding (destroying the KEK makes all data encrypted with it permanently inaccessible).
- Automatic rotation is available for symmetric keys only. Asymmetric and external keys require manual rotation.
- Cloud KMS Autokey automates key provisioning by creating key rings and keys as resources are created -- eliminates pre-provisioning.
- Protection levels: Software (FIPS 140-2 Level 1), Cloud HSM (FIPS 140-2 Level 3), Cloud EKM (external).
Exam trap: CSEK is only supported by Cloud Storage and Compute Engine. If a question asks about CSEK with BigQuery, Cloud SQL, or other services, the answer is that CSEK is not supported -- use CMEK instead.
Secret Manager
Secret Manager stores API keys, passwords, certificates, and other sensitive data. It provides versioning, rotation, and IAM-based access control.
# Create a secret
gcloud secrets create my-secret --replication-policy="automatic"
# Add a secret version
echo -n "my-password" | gcloud secrets versions add my-secret --data-file=-
# Access a secret version
gcloud secrets versions access latest --secret=my-secret
# Access a specific version
gcloud secrets versions access 2 --secret=my-secret
Key features:
| Feature | Detail |
|---|---|
| Versioning | Each secret can have multiple versions. Pin workloads to specific versions or use latest. Roll back if a secret is compromised. |
| Replication | Automatic (Google chooses regions) or user-managed (you specify regions). |
| Encryption | AES-256-bit at rest, TLS in transit by default. Optional CMEK for customer-controlled encryption. |
| Regional secrets | Store secrets within specific geographic locations for data sovereignty compliance. |
| Rotation | Supports automatic rotation to protect against unauthorized access. |
| IAM | Fine-grained roles: roles/secretmanager.secretAccessor (read secret data), roles/secretmanager.admin (full management). |
Secret Manager vs. Cloud KMS: Secret Manager stores and retrieves actual secret values. Cloud KMS manages cryptographic keys used for encryption/decryption -- key material in Cloud KMS is not directly viewable or exportable. Use Secret Manager for passwords and API keys; use Cloud KMS for encryption operations.
VPC Service Controls
VPC Service Controls create security perimeters around Google Cloud resources to prevent data exfiltration via API calls.
| Concept | What It Does |
|---|---|
| Service perimeter | Boundary around projects that restricts API access to/from services inside the perimeter. Free communication inside; all cross-boundary communication blocked by default. |
| Access level | Conditions (IP range, device, identity, geolocation) that allow access through the perimeter |
| Ingress rules | Allow specific external clients to access protected resources inside the perimeter |
| Egress rules | Allow resources inside the perimeter to access specific Google Cloud resources outside it |
| Bridge perimeters | Allow two perimeters to communicate bidirectionally. Google recommends using ingress/egress rules instead for more granular control. |
| Dry run mode | Monitor requests without enforcing -- understand traffic patterns before enabling enforcement |
VPC Service Controls operate at the API level, not the network level. They complement VPC firewall rules, which control network-level traffic. Use both for defense-in-depth.
Exam trap: VPC Service Controls protect Google-managed services only (BigQuery, Cloud Storage, Pub/Sub, etc.). They do not protect third-party APIs or internet-facing services. For HTTP-level protection, use Cloud Armor instead.
Cloud Armor
Cloud Armor provides DDoS protection and WAF (Web Application Firewall) capabilities for applications behind Google Cloud load balancers.
- Security policies: Rules with match conditions (IP, geography, headers) and actions (allow, deny, rate-limit)
- Preconfigured WAF rules: Based on OWASP ModSecurity Core Rule Set for SQL injection, XSS, etc.
- Adaptive Protection: ML-based anomaly detection (Enterprise tier)
Cloud Armor protects only resources behind external HTTP(S) load balancers. For VM-level firewall rules, use VPC firewall rules instead.
Organization Policy Service
Organization policies enforce constraints across an organization, overriding individual project settings. Common constraints for the exam:
| Constraint | Effect |
|---|---|
constraints/iam.disableServiceAccountCreation |
Prevents creating new service accounts |
constraints/iam.disableServiceAccountKeyCreation |
Prevents creating service account keys |
constraints/compute.requireShieldedVm |
Requires Shielded VM features on all instances |
constraints/gcp.resourceLocations |
Restricts which regions resources can be created in |
constraints/compute.vmExternalIpAccess |
Controls which VMs can have external IPs |
Organization policies are evaluated before IAM. Even if IAM allows an action, an organization policy constraint can block it.
Quick-Reference: Decision Tree
| Scenario | Correct Approach |
|---|---|
| Application on a VM needs GCS access | Attach a user-managed SA with roles/storage.objectViewer to the VM |
| External CI/CD pipeline (GitHub Actions) needs GCP access | Workload Identity Federation (no keys) |
| Pods in GKE need BigQuery access | Workload Identity for GKE: map K8s SA to GCP SA |
| User needs temporary admin access | Service account impersonation or Privileged Access Manager |
| Need to block project deletion for everyone except admins | IAM deny policy with exceptionPrincipals |
| User has too many permissions | IAM Recommender to identify and remove excess roles |
| Need to grant access only during business hours | IAM Conditions with time-based CEL expression |
| On-premises app needs GCP access, no OIDC provider available | Service account key (last resort) |
| Default Compute Engine SA has too many permissions | Create a user-managed SA with minimum permissions; attach it to the VM instead |
| Need to encrypt BigQuery data with your own keys | CMEK via Cloud KMS (CSEK not supported for BigQuery) |
| Need to store a database password securely | Secret Manager |
| Need to prevent data exfiltration from Cloud Storage via API | VPC Service Controls service perimeter |
| Need to restrict all projects to specific regions | Organization policy: constraints/gcp.resourceLocations |
Common Exam Traps Summary
- Default service accounts have Editor role -- the Compute Engine and App Engine default SAs get
roles/editor. Always create dedicated SAs with least privilege. - Editor cannot manage IAM --
roles/editordoes not includesetIamPolicy. Onlyroles/owneror specific IAM admin roles can modify IAM policies. - Basic roles in production -- if the answer uses
roles/owner,roles/editor, orroles/viewerin a production scenario, it is almost certainly wrong. - Service account keys vs. keyless -- the exam strongly prefers Workload Identity Federation, attached SAs, or impersonation over downloading key files.
- Policy version 3 for conditions -- if a policy uses conditions but version is
1, conditions are silently dropped, granting broader access than intended. allUsersvs.allAuthenticatedUsers--allUsersis public (no auth).allAuthenticatedUsersrequires a Google account but includes anyone with one (including personal Gmail).- Custom roles cannot exist at the folder level -- only project or organization level.
- Deny policies override allow policies -- the only way to block inherited permissions from a parent resource.
- Workload Identity for GKE is bidirectional -- both the IAM binding and the K8s annotation are required.
add-iam-policy-bindingvs.set-iam-policy-- useadd/removefor safe incremental changes;setreplaces the entire policy.- CSEK only works with Cloud Storage and Compute Engine -- not with BigQuery, Cloud SQL, or other services.
- Recreating a deleted service account does not restore old bindings -- the new account gets a new internal ID.
- Legacy basic roles cannot use IAM Conditions -- use predefined or custom roles for conditional bindings.
- Organization policies override IAM -- even if IAM allows an action, an org policy constraint can block resource creation.