Introduction to Resource Hierarchy
For a Professional Cloud Architect, the Resource Hierarchy is the "skeleton" of your Google Cloud environment. It determines how resources are grouped, how permissions are inherited, and how governance is enforced. A well-designed hierarchy is essential for managing complexity as an organization grows.
The logical structure of Google Cloud resources, consisting of the Organization node, Folders, Projects, and individual Resources. It enables centralized management of access control and configuration. Reference: https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy
Plain-Language Explanation: Resource Hierarchy & Policies
The resource hierarchy is like the organizational chart of a multinational corporation.
Analogy 1 — The Corporate Org Chart (Hierarchy)
Imagine a huge company. At the top is the Organization (The CEO). Under the CEO are Folders (Departments like "Sales," "R&D," and "Finance"). Inside each department are Projects (Specific initiatives like "2024 Ad Campaign"). Inside each project are the Resources (The tools used, like a specific laptop or a database). If the CEO makes a rule, it applies to everyone. If the Sales Manager makes a rule, it only applies to the Sales department.
Analogy 2 — The Genetic Inheritance (IAM)
The hierarchy works like Genetics. If the "Parent" (A folder) has a certain trait (An IAM role), the "Child" (A project) automatically inherits that trait. You can't "refuse" your parents' genes in IAM—if you're a viewer at the folder level, you are a viewer for everything inside it.
Analogy 3 — The Building Code (Organization Policies)
Organization Policies are like Building Codes or "Guardrails." Even if you own a house (A project) and have all the keys (IAM Owner role), you still can't build a 50-story skyscraper in a residential zone. The building code (Org Policy) says "No buildings higher than 2 floors." This keeps the entire neighborhood (The Organization) safe and compliant, regardless of what the individual house owners want to do.
The Four Levels of Hierarchy
1. The Organization Node
- The root of the hierarchy.
- Linked to a Google Workspace or Cloud Identity domain.
- Provides centralized visibility and control over all resources.
2. Folders
- Used to group projects or other folders.
- Can represent Departments (HR, Engineering), Environments (Prod, Dev), or Regions.
- Architect Tip: Design folders to match your IAM and Policy requirements, not just your internal company structure.
3. Projects
- The base level for enabling APIs, managing billing, and adding services.
- Every resource (VM, Bucket, SQL) must belong to exactly one project.
- Projects are the primary trust boundary for networking and IAM.
4. Resources
- The actual services you use: Compute Engine instances, Cloud Storage buckets, etc.
Organization Policy Service (Guardrails)
While IAM is about who can do something, Organization Policies are about what can be done. They provide centralized, constraint-based control.
- Constraints: Predefined rules you can enforce (e.g.,
constraints/compute.disableSerialPortAccess). - Boolean Constraints: Turn a feature on or off (True/False).
- List Constraints: Define an allowlist or denylist (e.g., "Only allow VMs to be created in
us-east1andus-central1"). - Inheritance and Overrides: Policies are inherited down the hierarchy. However, you can "override" a parent's policy at a lower level unless it is explicitly "reset" or "blocked."
The Organization Policy Service is enforced by the Resource Manager API before any service-specific API (Compute, GCS, BigQuery) accepts the request. That means even a roles/owner principal cannot bypass a constraints/compute.vmExternalIpAccess deny — the request fails at admission with FAILED_PRECONDITION, never reaching the Compute Engine control plane.
Boolean vs List Constraints (and inheritFromParent)
Knowing the shape of a constraint determines how you write it in Terraform or gcloud, and how inheritance behaves.
Boolean constraints
A simple on/off switch. The policy spec has a single enforce: true|false field.
# constraints/iam.disableServiceAccountKeyCreation
name: organizations/123456789/policies/iam.disableServiceAccountKeyCreation
spec:
rules:
- enforce: true
Common boolean slugs: iam.disableServiceAccountKeyCreation, iam.disableServiceAccountKeyUpload, compute.requireShieldedVm, compute.requireOsLogin, storage.uniformBucketLevelAccess, sql.restrictPublicIp.
List constraints
A policy that takes allowedValues / deniedValues, optionally combined with allValues: ALLOW|DENY. Example: constraints/gcp.resourceLocations to enforce data residency.
name: organizations/123456789/policies/gcp.resourceLocations
spec:
rules:
- values:
allowedValues:
- in:eu-locations
- in:us-locations
Common list slugs: gcp.resourceLocations, compute.vmExternalIpAccess, compute.trustedImageProjects, compute.restrictSharedVpcHostProjects, serviceuser.services, iam.allowedPolicyMemberDomains (domain restricted sharing).
inheritFromParent semantics
For list constraints only, child policies can set inheritFromParent: true to union with the parent allowlist instead of replacing it. Without this flag, a child policy completely overrides the parent at that node. For boolean constraints, the child simply replaces the parent — there is no merging. This is why teams often set inheritFromParent: true on gcp.resourceLocations at the folder level so engineering folders can add their own approved regions without losing the org-wide EU/US baseline.
A common architect mistake: applying constraints/compute.vmExternalIpAccess as a boolean. It is actually a list constraint that takes VM resource IDs in deniedValues (or allValues: DENY to block all). Treating it as boolean produces INVALID_ARGUMENT and a silently unenforced policy in Terraform plans.
Common Enterprise Organization Policies
For a production environment, architects typically implement the following "Golden Policies":
- Restrict Resource Usage: Only allow services in specific geographic regions to comply with data residency laws.
- Disable External IP Addresses: Prevent VMs from having public IPs by default to reduce the attack surface.
- Enforce Uniform Bucket-Level Access: Ensure that GCS buckets use IAM for all access control instead of legacy ACLs.
- Restrict Shared VPC Host Projects: Control which projects can be used as network hubs.
- Disable Service Account Key Creation: Force the use of short-lived credentials and Workload Identity.
Dry-Run Mode and Custom Constraints
Dry-run policies
Production rollouts of new constraints are risky — a misconfigured gcp.resourceLocations can break a CI/CD pipeline that creates buckets in us-central1. The Organization Policy Service supports dry-run mode for most constraints: the policy is evaluated and the would-be denial is logged to cloudaudit.googleapis.com/policy (Policy Denied audit log), but the actual API call is allowed through.
gcloud org-policies set-policy policy.yaml --update-mask=dryRunSpec
The dry-run spec lives separately from the live spec, so you can run them side-by-side. The recommended workflow: enable dry-run for 1-2 weeks, query the audit logs for protoPayload.metadata.dryRun=true, fix the offending workloads, then promote the dry-run spec to live.
Custom constraints
When no predefined constraint matches the rule you need (e.g., "all GKE clusters must have release_channel = REGULAR"), use Custom Organization Policies. You define a CEL (Common Expression Language) expression that evaluates against the resource's JSON representation at create/update time.
name: organizations/123456789/customConstraints/custom.gkeReleaseChannel
resourceTypes:
- container.googleapis.com/Cluster
methodTypes:
- CREATE
- UPDATE
condition: "resource.releaseChannel.channel == 'REGULAR'"
actionType: ALLOW
displayName: "Require REGULAR release channel on GKE clusters"
Custom constraints support a curated list of resource types (GCE, GKE, Cloud SQL, GCS, BigQuery, Cloud Run, and more — the list keeps growing). They run in the same admission path as predefined constraints, so they also support dry-run.
Always pair a new custom constraint with dry-run mode first, then ship the live version after one billing cycle of clean audit logs. CEL expressions that reference optional fields (resource.foo.bar) can throw NoSuchField and accidentally deny-all — dry-run catches this before it pages you at 3 AM.
IAM Deny Policies and IAM Conditions
Org Policy is the resource-level guardrail; IAM Deny Policies and IAM Conditions are the identity-level guardrails. PCA scenarios often hinge on picking the right tool.
IAM Deny Policies (iam.googleapis.com/DenyPolicy)
A deny policy attaches to an Organization, Folder, or Project node and explicitly denies permissions for a set of principals — even if they have roles/owner elsewhere. Deny rules evaluate before allow rules, so they are the only way to truly block a permission cluster-wide.
name: policies/cloudresourcemanager.googleapis.com%2Forganizations%2F123456789/denypolicies/block-key-creation
rules:
- denyRule:
deniedPrincipals:
- principalSet://goog/public:all
deniedPermissions:
- iam.googleapis.com/serviceAccountKeys.create
exceptionPrincipals:
- principal://iam.googleapis.com/projects/-/serviceAccounts/[email protected]
Use cases: enforce "no service account key creation" without relying on the boolean Org Policy, block a deprecated permission across all projects, implement break-glass exception principals.
IAM Conditions
Conditions are CEL expressions attached to an IAM allow binding that restrict when the role applies — based on request time, resource name, resource tag, or request attributes. Example: grant roles/storage.admin only on buckets whose name starts with prod- and only from 09:00-18:00 UTC.
- role: roles/storage.admin
members: ["group:[email protected]"]
condition:
title: "Only prod buckets in business hours"
expression: |
resource.name.startsWith("projects/_/buckets/prod-") &&
request.time.getHours("UTC") >= 9 &&
request.time.getHours("UTC") < 18
Three tools, three layers: Org Policy gates the resource shape, Deny Policies block permissions outright, Conditions narrow when an allow applies.
Resource Manager Tags vs Labels
GCP has two superficially similar key-value mechanisms attached to resources. PCA exam writers love confusing them.
Labels
Free-form key-value pairs ({"env": "prod", "team": "payments"}) on a resource. Labels are descriptive metadata — they flow into billing exports, log filters, and gcloud --filter queries, but they have no IAM or policy semantics. Anyone with edit permission on the resource can change a label.
Resource Manager Tags
Tags (tagKeys/tagValues under cloudresourcemanager.googleapis.com) are first-class governance objects with their own IAM. A tag is created at the Org or Project level, bound to a resource, and inherited down the hierarchy. Critically, tags are referenced by:
- IAM Conditions —
resource.matchTag('123456789/env', 'prod')lets you grant a role only on prod-tagged resources. - Org Policy Conditions — apply a constraint only when a tag matches, e.g., enforce
compute.vmExternalIpAccessdeny only onenv=prodVMs. - VPC Firewall rules — secure tags (a subset of Resource Manager tags) replace legacy network tags for firewall targeting.
- Hierarchical Firewall Policies — tag-based targeting at the folder/org level.
| Aspect | Labels | Resource Manager Tags |
|---|---|---|
| Scope | Per-resource | Hierarchical, inherited |
| IAM control | None | tagUser, tagAdmin roles |
| Policy hookable | No | Yes (IAM, Org Policy, FW) |
| Billing exports | Yes | Yes |
| Max per resource | 64 | 50 |
Three slug families to recognize on sight in PCA scenarios: iam.* (e.g., iam.disableServiceAccountKeyCreation, iam.allowedPolicyMemberDomains) governs identity surface; compute.* (e.g., compute.requireShieldedVm, compute.vmExternalIpAccess, compute.trustedImageProjects) governs VM shape; gcp.* (e.g., gcp.resourceLocations, gcp.restrictServiceUsage) governs cross-service controls like data residency and which APIs can even be enabled.
Designing the Hierarchy: Best Practices
- Production/Non-Production Separation: Use separate folders for Prod and Dev to apply stricter policies and IAM controls to Production.
- Shared Services Folder: Create a folder for centralized resources like Logging, Monitoring, and Hub networks (Shared VPC).
- Avoid Deep Nesting: Keep the hierarchy simple. 3-4 levels of folders are usually sufficient. Deep nesting makes troubleshooting IAM and Policies very difficult.
- Automation: Use Terraform to manage your hierarchy. Never create folders and projects manually in the console for an enterprise environment.
Org Policy vs IAM: Separation of Duties
A recurring PCA pattern: an organization wants the security team to define what can exist, and application teams to manage who can do what — with neither side able to undo the other.
The clean separation
- Org Policy Administrator (
roles/orgpolicy.policyAdmin): held by SecOps/governance. Can set constraints at the Org and Folder levels but cannot grant IAM roles. - Project IAM Admin (
roles/resourcemanager.projectIamAdmin): held by app teams within their project. Can grant any role on the project — except roles that would let users create resources blocked by Org Policy.
This works because Org Policy is evaluated at the Resource Manager admission layer, not via IAM permissions. An app team admin can grant roles/compute.admin all day long; if SecOps sets constraints/compute.disableNestedVirtualization, no compute admin can create a nested-virt VM regardless of IAM.
Where the model breaks
The separation breaks in two known cases:
roles/orgpolicy.policyAdmingranted at the project level — a project admin who also holds this role cansetOrgPolicyto override the parent folder's policy locally (for any constraint that doesn't carrydenyAll: truefrom above). Best practice: grantorgpolicy.policyAdminonly at the Org node.- Boolean constraints without
RESTORE_DEFAULT— if a folder setsenforce: falseto disable a parent's enforced constraint, a deep audit must catch that. Usegcloud org-policies list --show-unsetregularly to surface these overrides, or apply policies withinheritFromParentsemantics where supported.
Audit and detection
- Policy Analyzer (
policy-troubleshooterand the new Policy Analyzer for Org Policies) lets you ask "why was this request denied/allowed?" against the live policy graph. - Asset Inventory exports the full
OrgPolicyset per node — pipe into BigQuery and alert on diffs. - Cloud Audit Logs with
protoPayload.serviceName=orgpolicy.googleapis.comcapture everySetOrgPolicy/SetCustomConstraintchange.
PCA exam often phrases it like this: "SecOps must guarantee that no developer — even a project owner — can create a public GCS bucket." The right answer is always a layered combo: constraints/storage.publicAccessPrevention as an Org Policy at the org node plus an IAM Deny Policy on storage.buckets.setIamPolicy for non-admin principals. Picking only IAM is wrong (owners can edit IAM); picking only Org Policy is wrong (it doesn't stop legacy ACLs on pre-existing buckets from being weaponized).
FAQ — Resource Hierarchy and Org Policies
Q1. What is the difference between IAM and Organization Policies?
IAM focuses on "Who" (identities) and their "Permissions." Organization Policies focus on "What" (restrictions) and apply to the resources themselves, regardless of who is performing the action.
Q2. Can a project belong to two folders?
No. Every project has exactly one parent (either a folder or the organization node).
Q3. What happens if an Org Policy conflicts with an IAM permission?
The Org Policy wins. If a user has the IAM role "Compute Admin" (which allows creating VMs), but an Org Policy is in place that "Disables VM creation in Europe," the user will be blocked from creating a VM in Europe.
Q4. Can I test an Org Policy before enforcing it?
Yes, using Dry-run mode (for certain constraints). This allows you to see what would have been blocked without actually interrupting service.
Q5. How do I get an Organization Node?
You must have a Google Workspace or Cloud Identity account. When you create your first project under that domain, the Organization Node is automatically generated.
Final Architect Tip
For the PCA exam, the Resource Hierarchy is all about Governance at Scale. If a scenario involves "enforcing compliance across 500 projects," the answer is Organization Policy. If it involves "logical grouping for billing and access," the answer is Folders. Always remember that Policy inheritance is the key to enterprise-wide security. If you want to "stop all developers from creating public buckets," you apply that policy at the Organization or Folder level.