Chapter 1
Google Cloud from a SecDevOps Perspective
Scope. This chapter establishes the platform model the rest of the book builds on: what Google Cloud is structurally, where the trust boundaries fall, and the operating principles — automation, auditability, least privilege, zero trust — that every later chapter applies to a specific service. It deliberately defers all hierarchy mechanics (creating organizations, folders, and projects; organization policy; project factories) to Chapter 2, and all IAM detail to Chapter 3. Prerequisites. Working knowledge of Linux, TCP/IP, containers, and at least one other public cloud. No prior GCP experience is assumed. Verified against. Google Cloud console and API surface as of 2026-09, Cloud SDK 583.0.0, and
hashicorp/googleprovider 8.x; see sources at end.
Most engineers arrive at Google Cloud carrying an AWS or Azure mental model, and most of the resulting incidents trace back to three specific mismatches. The first is the project: in GCP the project is not a loose grouping, it is the unit that owns billing, quota, API enablement, and the default IAM boundary, and a design that treats it as a folder-with-a-label will produce blast radii nobody intended. The second is inheritance: IAM in GCP flows downward from organization to folder to project to resource, additively, and there is no way to subtract a granted role at a lower node except with an explicitly configured deny policy. The third is the network: a VPC in GCP is a global object with regional subnets, so the isolation instinct trained by AWS's per-region VPCs produces either far too many networks or far too few.
This book is written for the engineer who has to operationalize the platform rather than pass a certification on it. That means the recurring question is not "what does this service do" but "what is on by default, what is the blast radius when it is wrong, how do I express it as code, and how do I prove afterward that it was correct." Those four questions are the shape of every section in this book.
SecDevOps, as this book uses the term, is the practice of making the secure configuration the only reachable configuration — not the recommended one. On Google Cloud that is achievable to an unusual degree, because organization policy, IAM deny policies, VPC Service Controls, and policy-as-code in the deployment pipeline can each independently refuse a bad change. The rest of this chapter defines the platform primitives those controls act on, and fixes the design principles the remaining seventy-seven chapters apply.
1.1 What Google Cloud Platform Is §
Google Cloud Platform is the set of infrastructure, platform, and managed services that Google exposes on the same physical infrastructure, network, and control systems that run its consumer products. Structurally it is three things at once: a global fiber network with points of presence that terminate user traffic close to the user; a fleet of regional data centers offering compute, storage, and managed data services; and a uniform API surface — every service is a REST API under *.googleapis.com, and the console, gcloud, the client libraries, and Terraform are all clients of that same API.
That last point matters more than it sounds. Because there is one API surface, there is one authorization system (IAM), one audit trail (Cloud Audit Logs), and one policy system (Organization Policy) that apply to every service uniformly. A control you learn once is a control you apply everywhere. It also means the console is never privileged: anything a human can do in the browser has an equivalent API call that a pipeline can make, and an equivalent log entry recording that it happened.
Google Cloud is distinct from Google Workspace, which is a separate SaaS product, though the two share an identity plane. Cloud Identity is the free identity tier that provides that plane without Workspace's productivity applications (§2.2).
1.2 The GCP Shared Responsibility Model §
Google's published model divides obligations by service class. For IaaS (Compute Engine, Persistent Disk, Cloud VPN) the bulk of the security work is yours: guest OS patching, application code, network policy, identity, and data. For PaaS (GKE, App Engine, BigQuery) Google absorbs more — the control plane, the runtime, the node image where you use one of the managed modes — leaving you application-level controls, IAM, and data. For SaaS and serverless (Cloud Run, Google Security Operations) Google owns nearly all of it and you own access control and the data you put in.
Two responsibilities never shift regardless of service class: your access policies and your data. Google does not decide who in your organization can read a bucket, and Google does not decide what you put in it. Every breach this book is designed to prevent lands in that non-shifting half.
Google supplements the model with what it calls shared fate: rather than only drawing the line, Google publishes secure-by-default deployable assets and controls that make the customer's half easier to get right. In practice this means the enterprise foundations blueprint, the Well-Architected Framework, Assured Workloads, Security Command Center, Organization Policy, Confidential Computing, and Policy Intelligence. The Risk Protection Program, which pairs Google's posture signals with cyber insurance underwriting from Munich Re and Allianz, is Preview and must not be a production dependency.
What goes wrong. Teams read "Google handles security of the cloud" and conclude that a managed service is safe by construction. Cloud Storage is a managed service; a bucket with allUsers on it is a public data breach that Google's half of the model does not touch.
1.3 Infrastructure, Platform, and Managed Services §
The practical distinction between the three tiers is what you are allowed to see and therefore obliged to secure.
- Infrastructure services hand you a machine boundary. Compute Engine gives you a VM whose guest OS you patch, whose disks you encrypt or accept default encryption on, and whose network interface you place in a subnet you designed. Everything above the hypervisor is yours.
- Platform services hand you a workload boundary. GKE Standard gives you nodes you can still shell into; GKE Autopilot and Cloud Run do not, and in exchange Google patches the node image and enforces a hardened runtime. The tradeoff is real: you lose the ability to install an agent, and you gain the inability to forget to patch.
- Managed data and security services hand you an API boundary only. BigQuery, Spanner, Secret Manager, and Cloud KMS expose no host at all. Your entire security surface is IAM, encryption key selection, network reachability (VPC Service Controls, §5.19 and Chapter 20), and audit logging.
The SecDevOps decision rule: move down the list until you hit a real requirement to move back up. Every step toward the managed end removes a class of misconfiguration you can no longer make. The common legitimate reasons to stay at the infrastructure tier are licensing, kernel-level agents, and workloads with hard latency or hardware requirements.
1.4 Regions, Zones, and Global Services §
A region is an independent geographic area; a zone is a deployment and failure-isolation domain within a region. Both are documented as logical abstractions over physical resources, and Compute Engine maps zones to underlying clusters independently for each organization — so us-central1-a in your organization need not be the same physical cluster as us-central1-a in someone else's. Within one organization the mapping is consistent, but never assume a zone letter means the same physical failure domain across organizational boundaries, and never infer anything about physical adjacency from the letter.
Standard zones are named REGION-LETTER (us-central1-a). Google also publishes AI zones, specialized for ML workloads, with extended names such as us-west4-ai2b.
Resources have one of three scopes, and scope determines both availability and blast radius:
| Scope | Examples | Failure domain |
|---|---|---|
| Zonal | VM instances, zonal Persistent Disk, zonal NEGs | one zone |
| Regional | regional MIGs, regional disks, static external IPs, Cloud SQL HA | one region |
| Global | VPC networks, images, global load balancer forwarding rules, IAM policies, Cloud DNS zones | multi-region |
Attaching a zonal resource to another requires them to share the zone. A regional resource can be used by any zone in its region.
For security design, the important consequence is that the VPC network and the IAM policy are global. A firewall policy mistake is not contained by a region. Conversely, a data residency requirement is satisfied at the resource location level, enforced with the constraints/gcp.resourceLocations organization policy constraint (§2.30) — not by hoping engineers pick the right region.
gcloud compute regions list --format="table(name,status)"
gcloud compute zones list --filter="region:us-central1" --format="value(name)"
1.5 Projects as the Fundamental GCP Boundary §
A project is the container that owns:
- Billing — a project links to exactly one billing account.
- Quota — per-service quotas are counted per project.
- API enablement — a service is off until enabled on that project.
- The default IAM boundary — a role granted at the project applies to every resource in it.
- Default network reachability — resources in a project use that project's VPCs unless the project is a Shared VPC service project (§5.29).
That combination makes the project the natural blast-radius unit. Two workloads that must not be able to reach each other's data, exhaust each other's quota, or be administered by the same operator belong in two projects. Projects are free; the cost of a project is the automation required to create it consistently, which is exactly what a project factory solves (§2.26).
A project carries three identifiers, and confusing them causes real outages:
| Identifier | Set by | Mutable | Example |
|---|---|---|---|
| Project ID | you, at creation | no | rc-saas-prod-app-01 |
| Project number | Google, at creation | no | 123456789012 |
| Display name | you | yes | SaaS Prod App |
Service agent emails and many API paths use the project number; almost every command you type uses the project ID. Never key automation on the display name.
Chapter 2 covers creating, naming, and retiring projects. This section fixes only the principle: the project is the boundary, and boundary decisions are architecture, not bookkeeping.
1.6 The Google Cloud Resource Hierarchy §
Every Google Cloud resource sits in a single-parent tree: organization → folder(s) → project → resource. The tree exists to do two jobs, and both are security jobs.
The first is policy inheritance. An IAM allow policy or an organization policy set at any node applies to every descendant of that node. This is what makes it possible to enforce a control once for ten thousand projects.
The second is delegated administration. A folder is the unit you hand to a business unit or platform team so they can administer their own projects without touching anyone else's.
The tree is constrained: folders nest up to 10 levels deep, and a single parent holds at most 300 direct child folders (observed 2026-09). Those numbers are generous enough that hierarchy depth should be driven by policy needs, not by limits — and in practice a hierarchy deeper than four levels becomes impossible for a human to reason about when auditing effective access.
1.7 Organizations, Folders, Projects, and Resources §
- Organization — the root node, one per Cloud Identity or Google Workspace account. It is created automatically the first time a user in your verified domain creates a project. Everything above it (domain ownership, user lifecycle) lives in Cloud Identity, not in GCP.
- Folder — an optional grouping node. Folders can nest. They hold IAM bindings, organization policies, tag bindings, and hierarchical firewall policies (§5.14).
- Project — the mandatory container for actual resources (§1.5).
- Resource — the service-level object: a VM, a bucket, a topic, a key. Many resources carry their own IAM policy, which is additive to everything inherited from above.
The additive rule is the single most important sentence in this chapter: effective allow access is the union of every binding from the resource up to the organization. You cannot revoke an organization-level grant by omitting it at the project. Subtraction requires an IAM deny policy (§3.17), which is evaluated before allow policies and wins.
Chapter 2 covers each node's operational surface in detail.
1.8 Control Plane vs. Data Plane §
The control plane is the set of API calls that create, modify, or describe configuration: compute.instances.insert, storage.buckets.setIamPolicy, container.clusters.update. The data plane is the traffic that reads or writes the content the resource holds: an HTTP GET of an object, a query against a table, a packet to a VM.
The distinction is operationally load-bearing on GCP for three reasons:
- Different audit logs. Control-plane writes land in Admin Activity logs, which are always on, free, and retained 400 days. Data-plane reads and writes land in Data Access logs, which are off by default outside BigQuery, billable, and retained 30 days (§1.20).
- Different network paths. Control-plane calls go to
*.googleapis.comregardless of where the resource lives; data-plane traffic may go over your VPC. Restricting one does not restrict the other — this is precisely why VPC Service Controls exists (Chapter 20). - Different permissions.
storage.buckets.get(control) andstorage.objects.get(data) are separate permissions, and roles that look administrative frequently grant both.
What goes wrong. A team enables Admin Activity monitoring, declares audit coverage complete, and then cannot answer "who read the customer table" because Data Access logging was never turned on for that service.
1.9 Google APIs and Service Endpoints §
Every Google Cloud service is reached at a service endpoint, conventionally SERVICE.googleapis.com — compute.googleapis.com, storage.googleapis.com, cloudresourcemanager.googleapis.com. The same hostname carries the service's REST and gRPC surface, and it is the name you enable, restrict, and audit against.
Three endpoint families matter for network design:
- Default public endpoints —
*.googleapis.com, resolvable and reachable from the internet, subject only to IAM. private.googleapis.com— a private VIP range, 199.36.153.8/30 (IPv62600:2d00:0002:2000::/56), reaching most Google APIs including Workspace APIs, usable from VMs with no external IP.restricted.googleapis.com— 199.36.153.4/30 (IPv62600:2d00:0002:1000::/56), which reaches only APIs supported by VPC Service Controls and refuses everything else, making it the correct choice inside a service perimeter.
Reaching either private VIP requires Private Google Access on the subnet, a private Cloud DNS zone mapping googleapis.com to the chosen VIP, a route to the range via the default internet gateway, and egress firewall permission (§5.17).
Enabling a service is itself a control-plane action and should be governed:
gcloud services enable compute.googleapis.com --project=PROJECT_ID
gcloud services list --enabled --project=PROJECT_ID --format="value(config.name)"
The constraints/gcp.restrictServiceUsage organization policy constraint restricts which services may be used at all, at any node in the hierarchy (§2.30).
1.10 Service Accounts and Machine Identities §
A service account is a principal that represents a workload rather than a person. Its email has the form NAME@PROJECT_ID.iam.gserviceaccount.com, and it appears in IAM policies as serviceAccount:NAME@PROJECT_ID.iam.gserviceaccount.com.
Three kinds exist, and they are governed differently:
- User-managed — you create them; you decide their roles and lifecycle. These are the ones your workloads should use.
- Default — created automatically when certain services are enabled. The default Compute Engine and App Engine service accounts are historically granted the basic Editor role on the project at creation. Disable that behavior with the
constraints/iam.automaticIamGrantsForDefaultServiceAccountsorganization policy constraint, which is enforced by default on organizations created on or after 2024-05-03, and give workloads purpose-built accounts instead. - Service agents — created and managed by Google so a service can act on your behalf (for example, the Cloud Build or GKE service agent). You do not manage their keys; you occasionally grant them a role on a resource in another project.
The correct way for code to authenticate as a service account is to attach the account to the resource that runs the code — a VM, a GKE workload via Workload Identity Federation, a Cloud Run service — and let Application Default Credentials fetch short-lived tokens from the metadata server. Downloaded JSON keys are a long-lived bearer credential with no built-in expiry, no binding to a network location, and a history of ending up in Git. This book treats them as an anti-pattern throughout (§3.25, §3.26).
1.11 How GCP Differs from AWS and Azure §
The differences that change designs, not the ones that change vocabulary:
| Dimension | Google Cloud | AWS | Azure |
|---|---|---|---|
| Account/boundary unit | Project (many per org, cheap) | Account | Subscription / resource group |
| Hierarchy | Org → folders (10 deep) → projects | Org → OUs → accounts | Mgmt groups → subscriptions → RGs |
| VPC scope | Global, with regional subnets | Regional | Regional |
| Deny semantics | Additive allow + separate deny policies | SCPs + policy Deny in the same document | Deny assignments |
| Workload identity | Attached service account, no keys | Instance profile / IRSA | Managed identity |
| Cross-cloud federation | Workload Identity Federation, first class | IAM roles + OIDC | Workload identity federation |
| Default encryption at rest | Always on, all services | Varies by service | Varies by service |
| Org-wide guardrails | Organization Policy constraints | Service Control Policies | Azure Policy |
The three that cause the most rework: the global VPC (you need far fewer networks than an AWS design would produce — see §5.3); additive-only allow policies (a project-level grant cannot narrow an org-level grant, so guardrails must be deny policies or organization policies, not omissions); and cheap projects (the correct GCP answer to "should this be isolated" is usually yes, whereas the AWS account-per-workload equivalent carries real overhead).
1.12 Security by Default vs. Security by Configuration §
Some GCP behavior is secure whether or not you act. Some is not. Knowing which is which is the difference between an audit finding and a clean run.
Secure by default (no action required):
- Encryption at rest for all persistent data, with Google-managed keys.
- Encryption in transit between Google data centers.
- Admin Activity and System Event audit logging, which cannot be disabled.
- Deny-by-default ingress on every VPC network (the implied ingress rule).
- No public access to newly created resources unless you grant it.
Organizations created on or after 2024-05-03 additionally receive a set of security baseline organization policies enforced automatically, including constraints/iam.managed.disableServiceAccountKeyCreation, constraints/iam.managed.disableServiceAccountKeyUpload, constraints/iam.automaticIamGrantsForDefaultServiceAccounts, constraints/iam.allowedPolicyMemberDomains, constraints/essentialcontacts.managed.allowedContactDomains, constraints/compute.managed.restrictProtocolForwardingCreationForTypes, and constraints/storage.uniformBucketLevelAccess. An older organization does not have these and must set them explicitly (§2.30).
Insecure or permissive by default (action required):
- The
defaultVPC network created with a new project, which ships with permissive rules includingdefault-allow-sshon0.0.0.0/0. Suppress it withconstraints/compute.skipDefaultNetworkCreation. - Data Access audit logs, off by default for every service except BigQuery.
- External IP addresses on VMs, permitted unless
constraints/compute.managed.vmExternalIpAccessrestricts them. - Interactive SSH by metadata key, unless
constraints/compute.managed.requireOsLoginis enforced. - Resource creation in any region, unless
constraints/gcp.resourceLocationsrestricts it. - Public buckets, unless
constraints/storage.publicAccessPreventionis enforced. - On an organization predating 2024-05-03, everything in the baseline list above.
The pattern is consistent: cryptography and the audit trail are Google's defaults; reachability and privilege are yours. Chapter 2 turns this into a concrete organization policy baseline.
1.13 The SecDevOps Operating Model §
The operating model this book assumes has five properties, and every later chapter is written to be compatible with all five:
- No standing human write access to production. Humans get read access continuously and write access temporarily, through Privileged Access Manager (§3.27) or an approved break-glass path.
- All change arrives through a pipeline. The pipeline's identity, not the engineer's, mutates production, and it federates in without keys (§4.7).
- The desired state is in Git. Divergence between Git and the platform is a defect to be detected, not a fact to be documented (§1.14).
- Policy runs twice. Once in the pipeline as a pre-merge check, once on the platform as an organization policy or deny policy that cannot be bypassed by skipping the pipeline (§1.16).
- Detection is independent of the actor. Security Command Center and log-based alerting observe the platform, not the pipeline, so a change made outside the pipeline is still seen.
The distinguishing property is the second half of point 4. A control that exists only in CI is a control that an engineer with console access can bypass in twelve seconds. Every guardrail in this book is stated with an answer to "what enforces this when the pipeline is skipped?"
1.14 Infrastructure as Code as the Source of Truth §
"Source of truth" is a claim about reconciliation, not about file location. Terraform state in a bucket is not a source of truth if an engineer's console change is never noticed.
Three practices make it true:
- Everything relevant is in code. Projects, IAM bindings, networks, org policies, log sinks, alerts. This book uses Terraform with the
hashicorp/googleandhashicorp/google-betaproviders, pinned to the current major:
terraform {
required_version = ">= 1.9"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 8.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 8.0"
}
}
}
- State is remote, locked, versioned, and encrypted. A Cloud Storage backend with object versioning and uniform bucket-level access, in a dedicated project no workload can read. State contains secrets by construction; treat the state bucket as a secrets store (§2.21).
- Drift is detected on a schedule. A periodic
terraform planthat reports a non-empty diff, plus Cloud Asset Inventory feeds for changes to resources you do not manage in code.
What goes wrong. Granting the Terraform service account broad project-level admin so that apply never fails. The pipeline identity then becomes the most privileged principal in the organization, and it authenticates from wherever a workflow file says it can. Scope it per-stage and federate it (§4.7, §3.34).
1.15 Immutable Infrastructure §
Immutable infrastructure means a running instance is never modified in place; a new one is built from a new artifact and the old one is destroyed. On GCP the primitives are direct: build images with Cloud Build and Packer, publish to Artifact Registry, and roll out with managed instance group rolling updates or a new Cloud Run revision.
The security argument is stronger than the reliability argument. Immutability gives you:
- A single patching path. The image is patched; instances are replaced. There is no per-host divergence to inventory.
- A provenance chain. The artifact is signed and attested at build time and verified at admission (Binary Authorization, §9.27 and Chapter 37). A mutated host has nothing to verify against.
- Meaningful integrity monitoring. Shielded VM integrity monitoring and file integrity checks are noise on a mutable host and signal on an immutable one.
- Short credential lifetimes. Instances that live hours rather than months mean stolen instance credentials expire on their own.
The practical enforcement point is preventing interactive access: no SSH keys in project metadata, OS Login required via constraints/compute.managed.requireOsLogin, and administrative access through Identity-Aware Proxy TCP forwarding only (§4.16).
1.16 Policy as Code §
Policy as code means the rules are executable and versioned, and they run in more than one place. On GCP there are four distinct enforcement points, and a mature program uses all of them:
| Point | Mechanism | Runs when | Bypassable by |
|---|---|---|---|
| Pre-merge | OPA/Rego, Terraform validation, gcloud beta terraform vet | pull request | skipping the pipeline |
| Pre-apply | Policy validation in the deploy job | terraform plan | pipeline write access |
| Platform admission | Organization Policy constraints, custom constraints | any API call | org policy admin only |
| Runtime | IAM deny policies, VPC Service Controls, Policy Controller in GKE | any API call | nobody, by design |
A rule that exists only in the top two rows is advisory. Wherever a constraint can be expressed as an organization policy custom constraint or an IAM deny policy, express it there and treat the pipeline check as a fast-feedback convenience.
Organization Policy supports dry-run mode, where violations are audit-logged but not blocked. Every new constraint in this book is introduced dry-run first, measured, then enforced (§2.30).
1.17 GitOps and GCP §
GitOps applies the reconciliation loop to deployment: a controller continuously compares a Git-declared desired state to the live state and converges the difference. On GCP the well-supported paths are Config Sync (part of GKE Enterprise) for Kubernetes resources, and Terraform driven by a pipeline for platform resources.
Security properties worth having:
- The cluster pulls, rather than CI pushing. No inbound credential to the cluster, no CI identity with cluster-admin.
- The Git repository is the audit trail. Signed commits and required reviews become change control, and the reconciler makes bypassing them visible as drift.
- Rendering is separated from applying. Hydrate manifests in a build step, store the rendered output, and let the reconciler apply only reviewed artifacts.
The gap GitOps does not close is platform configuration — IAM at the folder level, organization policy, VPC design. Those are Terraform's job, and Chapter 26 covers keeping the two loops from fighting over the same resource.
1.18 DevSecOps vs. SecDevOps §
The two terms are used interchangeably in the market. This book uses SecDevOps deliberately, to signal ordering: security constraints are inputs to the design, not a stage appended to the pipeline.
The practical difference shows up in where a control lives. A DevSecOps reading of "prevent public buckets" produces a CI check that scans Terraform for allUsers. A SecDevOps reading produces constraints/storage.publicAccessPrevention enforced at the organization, so the API refuses the call regardless of how it arrives — and then adds the CI check so the developer learns about it in ninety seconds rather than at apply time.
Neither term implies a separate team. The security team's deliverable in this model is guardrails, defaults, and evidence — not review queues.
1.19 Designing for Automation §
A design is automatable when every object it creates has a stable name, a declarable configuration, and an API. On GCP that is nearly always true; what breaks automation is human-shaped decisions embedded in the design.
Rules this book follows:
- Names are computed, not chosen.
PREFIX-ENV-FUNCTION-NN, derived from inputs, so a project factory can generate them (§2.10, §2.11). - No click-only steps in a documented procedure. Where a feature is genuinely console-only, this book says so explicitly rather than describing a manual step as normal.
- Identity for automation is federated, never keyed. Every pipeline in this book authenticates with Workload Identity Federation (§4.3).
- Idempotency over imperative sequences. Prefer a declarative resource to a script that checks-then-creates.
- Everything emits an event. Cloud Asset Inventory feeds, Pub/Sub notifications, and log sinks let downstream automation react without polling.
1.20 Designing for Auditability §
Auditability is the ability to answer, after the fact, who did what, to which resource, from where, and when — and to prove the record is complete.
The GCP audit surface has four log types with materially different defaults (observed 2026-09):
| Log type | Default | Charged | Retention |
|---|---|---|---|
| Admin Activity | always on, cannot be disabled | no | 400 days |
| System Event | always on, cannot be disabled | no | 400 days |
| Policy Denied | on by default | storage billable | 30 days |
| Data Access | off except BigQuery | billable | 30 days |
Three design consequences:
- Enable Data Access logging deliberately, per service. Turning it on organization-wide for every service produces a bill nobody approves. Turn it on for the services holding regulated data and for IAM itself.
- Aggregate at the organization. An aggregated log sink at the org node, writing to a bucket or BigQuery dataset in a dedicated logging project, survives the deletion of the project that generated the logs.
- Make the log store tamper-evident. Bucket lock or a locked retention policy on the sink destination, and no write access for any principal that can also make changes in the audited projects.
gcloud logging read \
'logProtoPayload.methodName="SetIamPolicy"' \
--project=PROJECT_ID --limit=10 --freshness=1d
1.21 Designing for Failure §
Failure design on GCP is largely a question of matching resource scope (§1.4) to the failure you intend to survive.
| Failure to survive | Minimum design |
|---|---|
| Machine failure | Managed instance group with autohealing |
| Zone failure | Regional MIG across ≥3 zones; regional disks; regional Cloud SQL |
| Region failure | Multi-region deployment behind a global load balancer; multi-region or dual-region buckets |
| Control-plane dependency failure | Cached credentials, no synchronous dependency on a foreign region's API |
| Human/automation error | Versioned state, soft-delete, org policy preventing the destructive call |
The security-adjacent failures are the ones teams forget. Deletion is a failure mode: projects have a 30-day recovery window (§2.29), Cloud Storage supports soft delete and object versioning, and Cloud KMS key versions can be destroyed with a scheduled delay you should not shorten. Your logging pipeline is a failure domain: if the sink destination is in the project that failed, you lose the evidence of the failure.
1.22 Designing for Least Privilege §
Least privilege on GCP is a design activity with four levers, applied in this order:
- Boundary first. Put the workload in its own project (§1.5). No amount of role tuning compensates for two systems sharing a project.
- Predefined roles, scoped to the smallest resource that works. Grant on the bucket, not the project; on the project, not the folder. Basic roles (Owner, Editor, Viewer) are never the answer outside a sandbox.
- Conditions. IAM conditions narrow a grant by resource name, tag, or time (§3.18–3.20).
- Deny policies. For rules that must hold regardless of who grants what below, a deny policy is the only mechanism that subtracts (§3.17).
Then verify rather than assume: IAM Recommender surfaces roles whose granted permissions have gone unused, and Policy Analyzer answers "who can do X on Y" across the hierarchy (§3.31, §3.32).
What goes wrong. Granting a predefined role at the folder to "keep it simple," then discovering during an incident that the effective set includes every project the folder will ever contain. Inheritance is forward-dated: a grant at a node silently applies to resources created under it years later.
1.23 Designing for Zero Trust §
Zero trust means no principal is trusted because of its network position. Google's own implementation of this idea is BeyondCorp, and the platform exposes the same primitives to you (Chapter 4):
- Strong identity for every principal, human and machine — Cloud Identity with phishing-resistant MFA for people, federated workload identities for machines (§4.3).
- Device signals — Endpoint Verification feeding access levels, so an unmanaged laptop is a different principal context than a managed one (§4.17).
- Access decisions at the request, not at the perimeter — Identity-Aware Proxy in front of applications and administrative SSH/RDP (§4.16, §7.17).
- Context-Aware Access binding IP, device, and location into access levels evaluated per request (§4.15).
- Data-perimeter enforcement independent of identity — VPC Service Controls, which stops an authorized identity from exfiltrating data to an unauthorized project (Chapter 20).
The last item is the one most zero-trust programs omit. Identity controls answer "should this principal be allowed"; VPC Service Controls answers "may this data leave," which is a different question with a different failure mode.
The concrete end state for administration: no VPN required, no bastion with a public IP, no standing SSH keys. Administrative access is IAP TCP forwarding to a private VM, authorized by IAM plus an access level, logged, and time-bounded (§4.18, §4.19).
1.24 Designing for Cost Awareness §
Cost is a security concern in three specific ways, and this book treats it only in those terms.
- Cost is a detection signal. A sudden spend change in a project is one of the earliest indicators of cryptomining after a credential compromise. Budget alerts routed to security, not only to finance, are cheap detection.
- Cost caps are blast-radius controls. Billing budgets with Pub/Sub notifications, quota overrides on expensive services, and
constraints/compute.vmExternalIpAccesslimit what a compromised principal can spend. - Logging and telemetry cost shapes coverage. Data Access logs are billable, so the design decision "which services log data access" is simultaneously a budget decision and a coverage decision. Make it explicitly, per service, and write down the residual risk for the services you excluded.
Attribution requires labels on every project and resource — env, owner, cost-center, data-class, system (§2.12) — and those same labels drive security queries, which is why the book treats labeling as a control rather than as hygiene.
1.25 Reference Architecture: Modern GCP Environment §
Every subsequent chapter fits into the following environment. The book carries two reference architectures: a multi-tenant SaaS estate (prefix rc-saas, org 123456789012, domain rickcollette.domain) and an enterprise estate (prefix rc-ent, org 210987654321, domain ent.rickcollette.domain). Identifiers are stable across every chapter.
Hierarchy.
Organization: rickcollette.domain (123456789012)
├── fldr-bootstrap seed project, Terraform state, org-level CI identity
├── fldr-common org-wide shared services
│ ├── rc-saas-shared-net-01 Shared VPC host project (§5.28)
│ ├── rc-saas-shared-log-01 aggregated log sink destinations (§1.20)
│ ├── rc-saas-shared-sec-01 SCC, KMS, Secret Manager (§2.21)
│ └── rc-saas-shared-cicd-01 Cloud Build / Cloud Deploy, WIF pools (§2.24)
└── fldr-environments
├── fldr-development → rc-saas-dev-app-01, rc-saas-dev-data-01
├── fldr-nonproduction → rc-saas-stg-app-01, rc-saas-stg-data-01
└── fldr-production → rc-saas-prod-app-01, rc-saas-prod-data-01
Controls applied at the organization node. Domain-restricted sharing, constraints/compute.skipDefaultNetworkCreation, constraints/compute.managed.vmExternalIpAccess (deny by default), constraints/iam.managed.disableServiceAccountKeyCreation, constraints/iam.automaticIamGrantsForDefaultServiceAccounts, constraints/storage.publicAccessPrevention, constraints/storage.uniformBucketLevelAccess, constraints/gcp.resourceLocations restricted to us-central1 and europe-west1, constraints/gcp.restrictServiceUsage, and constraints/compute.managed.requireOsLogin. Each is introduced dry-run first (§2.30).
Network. One Shared VPC per environment, hosted in rc-saas-shared-net-01, with regional subnets in us-central1 (10.128.0.0/20) and europe-west1 (10.129.0.0/20), Private Google Access on every subnet, Cloud NAT for egress, and no external IPs on workload VMs (Chapter 5). Hybrid connectivity for the enterprise estate uses HA VPN or Dedicated Interconnect terminating in a hub (Chapter 6).
Identity. People authenticate to Cloud Identity federated from the corporate IdP; production write access is granted just-in-time through Privileged Access Manager. Pipelines authenticate with Workload Identity Federation and impersonate per-environment service accounts (Chapter 3, Chapter 4).
Delivery. Code and Terraform in Git; Cloud Build renders and validates; Binary Authorization gates admission; Cloud Deploy promotes across environments; Config Sync reconciles Kubernetes state (Chapter 9, Chapter 37).
Detection. Aggregated org-level log sink into rc-saas-shared-log-01; Security Command Center at the organization; Data Access logs enabled for IAM, Cloud KMS, Secret Manager, Cloud Storage, and BigQuery; budget alerts routed to the security team.
Chapter 2 builds the hierarchy and the policy baseline this architecture assumes.
Chapter Summary §
- Google Cloud is one uniform API surface, so IAM, Cloud Audit Logs, and Organization Policy apply to every service the same way; the console is a client, never a privileged path.
- Shared responsibility shifts by service class, but access policy and data are always yours; shared fate is Google's set of secure defaults and blueprints that make your half easier.
- The project owns billing, quota, API enablement, and the default IAM boundary — it is the blast-radius unit, and projects are cheap enough to use generously.
- The hierarchy is organization → folders (≤10 deep, ≤300 children per parent) → projects → resources, and it exists for policy inheritance and delegated administration.
- Allow policies are additive and inherited downward; only IAM deny policies subtract.
- VPC networks and IAM policies are global; regions and zones bound only the resources scoped to them, and zone letters are per-project mappings.
- Control-plane and data-plane actions have different logs, different network paths, and different permissions; Data Access logs are off by default outside BigQuery.
private.googleapis.com(199.36.153.8/30) reaches most Google APIs;restricted.googleapis.com(199.36.153.4/30) reaches only VPC Service Controls–supported APIs and is the right choice inside a perimeter.- Attach service accounts to workloads and use short-lived tokens; downloaded keys are an anti-pattern throughout this book.
- Encryption and the core audit trail are secure by default; reachability, privilege, and the
defaultVPC are not. - Every guardrail needs a platform-side enforcement point, because a control that lives only in CI is bypassed by using the console.
- Least privilege is boundary → scoped predefined role → condition → deny policy, in that order, then verified with IAM Recommender and Policy Analyzer.
- Zero trust on GCP requires both identity controls (IAP, Context-Aware Access) and a data perimeter (VPC Service Controls); they answer different questions.
- Cost telemetry is a detection signal and a blast-radius control, not only a finance concern.
Security Checklist §
| Control | Why it matters | How to verify (CLI + Console) |
|---|---|---|
| Organization resource exists and owns all projects | Without an org node there is no place to enforce inherited policy | gcloud organizations list; Console → IAM & Admin → Settings |
| Default network suppressed on new projects | The default VPC ships permissive rules including SSH from 0.0.0.0/0 | gcloud org-policies describe compute.skipDefaultNetworkCreation --organization=ORG_ID --effective; Console → IAM & Admin → Organization policies |
| Automatic role grants to default service accounts disabled | Otherwise default SAs receive a basic role granting broad project write | gcloud org-policies describe iam.automaticIamGrantsForDefaultServiceAccounts --organization=ORG_ID --effective |
| Service account key creation disabled | Long-lived keys are the most common credential-leak vector | gcloud org-policies describe iam.managed.disableServiceAccountKeyCreation --organization=ORG_ID --effective |
| Data Access audit logs enabled for data-bearing services | Admin Activity alone cannot answer "who read this" | gcloud projects get-iam-policy PROJECT_ID --format="value(auditConfigs)"; Console → IAM & Admin → Audit Logs |
| Aggregated org-level log sink to a separate logging project | Logs must survive deletion of the audited project | gcloud logging sinks list --organization=ORG_ID; Console → Logging → Log Router |
| Resource locations constrained | Data residency must be enforced, not requested | gcloud org-policies describe gcp.resourceLocations --organization=ORG_ID --effective |
| Terraform state bucket versioned, private, and isolated | State contains secrets and is a full-control target | gcloud storage buckets describe gs://BUCKET --format="value(versioning.enabled,iamConfiguration.uniformBucketLevelAccess.enabled)" |
| Budget alerts routed to security | Spend anomalies are early compromise indicators | gcloud billing budgets list --billing-account=BILLING_ACCOUNT_ID; Console → Billing → Budgets & alerts |
| No external IPs on workload VMs | Removes direct internet reachability of the guest OS | gcloud org-policies describe compute.managed.vmExternalIpAccess --organization=ORG_ID --effective |
Sources §
- Google Cloud resource hierarchy — https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy (last validated 2026-09-03)
- Resource Manager quotas and limits — https://cloud.google.com/resource-manager/docs/limits (last validated 2026-09-03)
- Regions and zones, including per-organization zone-to-cluster mapping — https://cloud.google.com/compute/docs/regions-zones (last validated 2026-09-03)
- Shared responsibility and shared fate — https://cloud.google.com/architecture/framework/security/shared-responsibility-shared-fate (last validated 2026-09-03)
- Service accounts overview — https://cloud.google.com/iam/docs/service-account-overview (last validated 2026-09-03)
- Private Google Access configuration and endpoint ranges — https://cloud.google.com/vpc/docs/configure-private-google-access (last validated 2026-09-03)
- Cloud Audit Logs overview — https://cloud.google.com/logging/docs/audit (last validated 2026-09-03)
- Google Cloud enterprise foundations blueprint — https://cloud.google.com/architecture/security-foundations (last validated 2026-09-03)
- Organization Policy Service overview — https://cloud.google.com/resource-manager/docs/organization-policy/overview (last validated 2026-09-03)
- Security baseline organization policies — https://cloud.google.com/organization-policy/manage-baseline-constraints (last validated 2026-09-03)
- Restrict resource service usage — https://cloud.google.com/resource-manager/docs/organization-policy/restricting-resources (last validated 2026-09-03)
hashicorp/googleprovider releases — https://releases.hashicorp.com/terraform-provider-google/ (last validated 2026-09-03)- Cloud SDK command surface resolved offline against Google Cloud SDK 583.0.0 (core 2026.08.31), 2026-09-03