Prepare and test your skills
Prepare and test your skills
Managing folders and projects at scale is the design of a Google Cloud resource hierarchy that enforces governance from a single root down to workloads. The hierarchy starts at a single organization node (opens in a new tab) as the root, branches into folders (opens in a new tab) that group related work, and ends in projects that host resources such as virtual machines, storage buckets, and networking. Projects within folders (opens in a new tab) act as the core billing and trust boundary, while folders act as policy attach points and isolation boundaries for delegation.
How inheritance carries governance is through a single parent path where guardrails flow from the organization through folders to projects. Every folder or project has exactly one parent, so there is never a conflicting inheritance path. Organization policies are inherited by descendants but can be superseded by a policy defined at a lower folder or project, which allows central guardrails with targeted exceptions.
Identity and Access Management (IAM) allow policies are also inherited and are additive, so a grant on a folder applies to all projects in that folder. IAM deny policies are evaluated before allow policies and can supersede allows at the project, folder, and organization level. For example, a grant of Compute Instance Admin on a folder gives that role on all contained projects, while a deny placed higher in the tree can still block the action even when a lower-level allow grants it.
Exam tip: Allow policies inherit and add together down the hierarchy, but deny policies are applied first and can override an allow; organization policies inherit down but can be overridden by a lower-level organization policy.
Folder limits and project moves determine whether a resource hierarchy (opens in a new tab) can grow without breaking access. A parent folder can contain up to 300 direct child folders, folders can be nested up to 10 levels deep, and folder display names must be unique within the same level of the hierarchy. When tenant count exceeds 300, tenants must be arranged into nested hierarchies to stay within the direct-child limit.
Projects can be created at any level, and creating a project in a folder requires the Project Creator role on that folder. Moving a project into or out of a folder does not move inherited permissions with it, because directly attached IAM and organization policies move with the project while inherited policies stay with the source parent. If a service account receives Storage Object Creator from Folder A, moving a project from Folder A to Folder B removes that inherited access unless Folder B grants the same permission, which can cause an outage.
Choosing a hierarchy model means following business and security needs rather than copying the corporate organization chart. Key design factors are who is responsible for cloud resources, what compliance needs apply, and whether mergers, acquisitions, or spin-offs are expected. Most organizations use a hybrid approach at different levels, starting with the grouping that most affects policies and access.
The decision flow evaluates requirements in order. First, if subsidiaries, regional groups, or business units have very different policy requirements, use a region or subsidiary design. If not, evaluate team autonomy next: if workload or product teams require strong autonomy without a central security team setting policy, use an accountability-framework design, while central control favors an application-environment design. The three models trade central consistency for team autonomy:
| Hierarchy model | Top-level grouping | Control model and tradeoff |
|---|---|---|
| Based on application environments | Development, testing, and production folders | Centralized; central security enforces consistent production controls and separate IAM per environment, but teams have less policy autonomy |
| Based on regions or subsidiaries | Subsidiary and regional folders such as APAC, EMEA, and Americas | Federated; each region keeps independent processes and regulatory controls, but cross-region consistency requires more coordination |
| Based on accountability framework | Product or module folders such as Ecommerce Modules and Reconciliation and Billing | Decentralized; product owners control lifecycle and access for independent workloads, but organization-wide guardrails are harder to enforce |
Choose the environment model when development, testing, and production need different audit rules and access, such as stricter Payment Card Industry Data Security Standard controls only in production. Choose the region model when regions operate independently with different regulatory standards. Choose the accountability model when products are independent and share few common policies.
Enterprise separation of duties uses dedicated folder branches so each operational owner controls only its own scope. In the documented enterprise multi-tenancy (opens in a new tab) pattern, three top-level folders divide ownership: a Network Team folder hosts virtual private clouds (VPCs), a Cluster Team folder hosts platform clusters, and a Tenants folder hosts tenant non-cluster resources. The Network Team branch uses subfolders for tenant and cluster networks with one project per environment, while the Tenants branch uses one subfolder per tenant with one or more projects per tenant.
The Cluster Team branch uses per-environment folders that each group multiple projects, which supports both isolation and shared governance. Placing clusters in dedicated projects improves isolation for three related reasons:
Per-environment folders above those projects still allow low-risk policies and aggregated log sinks to apply to all production clusters at once. Best practices reduce overhead while preserving visibility: use a single organization node whenever possible, use standardized naming, start with a sandbox folder to validate the hierarchy, keep the bootstrap folder with infrastructure-as-code resources directly below the organization node, and place environment-specific shared services lower so production and non-production secrets carry different allow policies.
Continue with this study guide: Managing folders and projects at scale.
Managing organization policies for the organization, folders, and projects is the use of centralized guardrails that control how resources can be configured and used. The Organization Policy Service (opens in a new tab) stores constraints that cascade from the organization to folders to projects, so a policy attached high in the hierarchy controls all descendants unless a lower rule changes the result. Together with IAM controls, these policies enforce security, compliance, and cost controls without managing every project individually.
Custom organization policy constraints are administrator-defined rules that restrict specific resource fields when predefined constraints are not precise enough. A custom constraint (opens in a new tab) definition names the service resource, the field to control, and the allowed or denied condition for that field. The definition is written in YAML and uses a Constraint Template Language (CEL) expression to evaluate the resource value in the request, such as requiring a setting to be present or prohibiting a risky value.
The policy depends on the constraint, and the resource request depends on the policy. First the administrator defines the constraint, then the administrator creates the policy that uses it, and only after both exist does the control plane evaluate new requests against the CEL condition. A policy attached at the organization node flows to every folder and project beneath it, while a folder policy flows only to projects in that folder, and a project policy applies only inside that project. Enforcement happens when the service evaluates an incoming create or update request, and the request is allowed only when field values satisfy the policy.
How list and boolean constraints combine determines the effective policy that actually enforces on a resource after merging ancestor and local rules. List constraints use allowed values and denied values to control which services or resources can be used, and a child policy merges with the policy inherited from its parent. List policies using allowed or denied values cannot have more than 500 individual values and cannot be more than 32 KB in size.
Boolean constraints use a simple enforce: true or enforce: false rule to turn a restriction on or off, and a child resource resolves conflict by overriding the parent rather than merging. Some list constraints also support hierarchy subtree strings that expand enforcement to a whole branch with one value. A value with the under: prefix, such as under:folders/VALUE_A, acts on the named root resource and all of its children. The difference controls how conflicts resolve:
| Constraint type | How the child combines with the parent | Hierarchy result |
|---|---|---|
| List constraint | Child values merge with inherited values | Effective policy contains the combined allowed and denied values, including any under: subtree expansion |
| Boolean constraint | Child policy overrides the parent policy | Effective policy follows the child enforce setting for that branch, replacing the inherited setting |
Changes to organization policies can take up to 15 minutes to be fully enforced, and any project added later under an organization or folder automatically inherits constraints already enforced there. Policy evaluation is not retroactive, so existing non-compliant resources continue to run until they are created, updated, or remediated.
Exam tip: A list-constraint child merges with the inherited policy, while a boolean-constraint child overrides the parent policy for its own branch; a new policy affects only later create and update operations.
Testing policies before enforcement is the practice of moving a rule from simulation to observation to live denial without breaking production. The Organization Policy Service stores two parallel definitions for the same constraint on the same resource: spec for the live policy that denies violating actions, and dryRunSpec for the test policy that only audit-logs violations. The lifecycle moves in order from simulation to dry run to live enforcement.
Enforcement states control whether a violating CREATE or UPDATE request is blocked, observed, or ignored:
| State | Where it is stored | Effect on violating actions |
|---|---|---|
| Enforced | spec with enforce: true | The service denies the request from the caller to the Google Cloud service |
| Dry run | dryRunSpec with enforce: true | The requesting action is allowed, but the violation is audit-logged for review over the next 30 days |
| Disabled | spec with enforce: false | The service takes no enforcement action and the request flows normally |
Policy Simulator for Organization Policy scans current configurations in an organization scope and reports where a proposed constraint would already violate, so administrators see the blast radius before enforcement begins. Dry-run mode then extends that insight forward by audit-logging new violating actions as they occur without denying them. If a rule uses a tag-based condition to scope enforcement, the policy must also include at least one unconditional rule or the service will reject the policy on save.
Promoting and auditing policies is the ordered workflow that moves a rule from draft to live enforcement and verifies the resolved result. The child resource depends on its parent by inheritance, so an override at a lower level requires selecting Override parent's policy before adding rules. The promotion workflow runs in order:
gcloud policy-intelligence simulate orgpolicy, to preview violations against current resources.gcloud org-policies set-policy with --update-mask=dryRunSpec to start audit-logging violations without denial.gcloud org-policies set-policy with --update-mask=spec to begin denying violating actions, with full effect after up to 15 minutes.The effective policy is the final decision after inherited policies and any local merge or override are resolved together. A plain gcloud org-policies describe returns only the policy directly attached to the named resource, while describe --effective returns the resolved view. Policy Analyzer (opens in a new tab) for Organization Policy provides the same resolution at scale through a query composed of a scope and a constraint, returning consolidatedPolicy with the attachment resource and effective enforcement, plus project and ancestor folders context. AlloyDB custom constraints (opens in a new tab) and Application Integration custom constraints (opens in a new tab) follow the same attach, inherit, and evaluate pattern for their service resources.
Using the resource hierarchy for access control is the attachment of IAM allow and deny policies at organization, folder, and project levels to control who can act on descendant resources. An allow policy attached at a higher level automatically applies to every descendant, and the effective permissions for any resource are the union of its own policy plus all ancestor policies. Because inheritance only adds permissions, designs must combine broad allows with targeted denies, conditions, and boundaries to preserve least privilege.
How allow inheritance forms effective permissions is through additive flow from containers down to service resources. Identity and Access Management (IAM) (opens in a new tab) recognizes principals that receive access, roles that collect permissions, and allow policies that bind principals to roles on a specific resource. Organization, folder, and project resources are container resources that structure the hierarchy, while service-specific resources such as Pub/Sub topics or Compute Engine instances hold workloads.
A role granted on a container flows down to every service-specific resource it contains, while a role granted on a service-specific resource is limited to that resource. The scope widens as the attachment moves up:
| Hierarchy level | What a grant at that level controls |
|---|---|
| Organization | The company root node and all folders, projects, and service resources under it |
| Folder | That folder and all child folders, projects, and service resources it contains |
| Project | That project, which acts as a trust boundary, and all service resources inside it |
| Service-specific resource | Only that single resource, such as a Pub/Sub topic or Compute Engine instance |
To calculate effective permissions for a resource, collect policies down the single parent chain:
For example, access flows from project_1 to its topic_a when Kalani receives Editor on project_1 and Nur receives Publisher on topic_a, so topic_a gives Kalani Editor through inheritance plus Nur Publisher through direct grant. Inherited roles cannot be edited from the child view; the change must be made where the grant was created.
Exam tip: Allow inheritance is additive only, so a child cannot remove a parent grant — the grant must be removed where it was created, while a deny policy can still block it.
Deny policies are blocking rules that prevent principals from using specific permissions even when an inherited or direct allow grants them. A deny policy attachment point is the organization, folder, or project where the policy is attached and from which it is inherited downward the same way allows inherit. Each resource can have up to 500 deny policies attached, with a combined total of 500 deny rules, and each deny policy is evaluated independently.
Deny evaluation happens before allow evaluation, so a matching deny removes the ability to use the denied permission entirely. This override lets administrators set guardrails that prevent privilege escalation even when broad allow roles are inherited from above. Policy changes are eventually consistent and generally take effect within 2 minutes, although propagation can take 7 minutes or more. Each deny rule names who is blocked, what is blocked, and when the block applies:
deniedPrincipals: principals that are denied, including users, service accounts, groups, domains, and workforce or workload identities.exceptionPrincipals: principals exempt from the rule even if they match, such as specific admins or service agents.deniedPermissions: permissions that cannot be used, written as SERVICE_FQDN/RESOURCE.ACTION such as iam.googleapis.com/roles.delete.exceptionPermissions: permissions that remain usable even if included in a broad denial.denialCondition: optional Common Expression Language expression, such as !resource.matchTag('12345678/env', 'test'), that limits when denial applies.A common pattern is to deny broad sets while adding project admins to exceptionPrincipals, so only the exception group retains sensitive actions like project deletion.
Conditional and tag-based access grants roles dynamically instead of granting the same access to every resource under a policy. A conditional role binding attaches a Common Expression Language condition to an allow-policy binding, and IAM grants the permissions only when the condition evaluates to true for that request. Resource-based access (opens in a new tab) controls use attributes of the target resource, specifically resource.name, resource.type, and resource.service.
Inherited conditions are conditional bindings set on a container such as an organization, folder, or project that propagate down to child resources. This inheritance is useful when a child does not accept conditions in its own policy or has no policy at all. To avoid silently denying access, guard name checks with type checks so non-matching types bypass the name test. For example, resource.type != 'compute.googleapis.com/Disk' || resource.name.endsWith('devResource') evaluates to true for every non-disk type and only checks names for disks.
Resource Manager (opens in a new tab) tags extend this model by attaching annotations to organization, folder, or project nodes that are inherited by descendant resources. An IAM Condition then calls a tag function on the resource during authorization, and access flows from the binding to the resource only when the tag test returns true. Tag inheritance lets one folder policy grant the same conditional role to every tagged child without per-project bindings. Conditions that use permanent IDs call resource.matchTagId(keyId, valueId), while conditions that use human-readable names call resource.matchTag(namespacedKey, shortValue) such as resource.matchTag('123456789012/env', 'prod').
Choosing a tag identifier is a tradeoff between convenience and safety when keys are deleted and recreated:
| Identifier type | Reuse after delete and recreate | Risk if name is reused with new meaning |
|---|---|---|
| Namespaced name and short name | Condition continues to work without policy updates | Condition continues to apply to the new tag, which can grant unintended access |
Permanent ID such as tagKeys/123456789012 | Policy must be updated to new IDs to preserve access | Condition does not apply to the new tag, which reduces unintended access |
Use names when readability and stable declarative management with tools like Terraform matter most and tag lifecycle is controlled. Use permanent IDs when minimizing unintended grants matters most, especially for sensitive environments. Final access also depends on other layers: the request must pass IAM evaluation and must also satisfy applicable organization constraints, while Principal Access Boundary (PAB) policies define resources a principal is eligible to access and landing zone hierarchy (opens in a new tab) choices determine where those bindings attach. Parent-only *.list permissions are checked on the parent container rather than child resources, so list conditions must match the parent type where the check occurs.
spec and the test policy in dryRunSpec, and the effective policy is shown by describe --effective and Policy Analyzer results.Identity and Access Management (IAM) allow policies are inherited down the hierarchy and combine additively, so a grant on a folder applies to all projects in that folder and cannot be removed by a child. IAM deny policies are evaluated before allow policies and can block an inherited or direct allow at the organization, folder, or project level.
Directly attached IAM and organization policies move with the project while inherited policies stay with the source parent, so inherited access is lost unless the new parent grants the same permission. For example, if a service account received Storage Object Creator from Folder A, moving the project to Folder B removes that inherited access unless Folder B grants it, which can cause an outage.
A list-constraint child merges its allowed and denied values with the inherited policy to form a combined effective policy, while a boolean-constraint child overrides the parent policy for its own branch. Policy changes can take up to 15 minutes to be fully enforced and evaluation is not retroactive, so existing non-compliant resources continue to run until they are created, updated, or remediated.
Last updated