Skip to main content
Back
DateRead9 min

GCP Organization Policy Explained: Constraints, Inheritance, and Examples

Key Takeaways

  • Organization Policy governs configuration rather than identity. IAM decides who can act on a resource. Organization Policy decides what configurations are allowed to exist in the first place, and it applies to every principal, including the organization's own admins.
  • Every constraint is boolean or list, and that split determines what you can write. A boolean constraint turns a restriction fully on or off. A list constraint allows or denies specific values. The two types don't mix inside a single rule, and mistaking one for the other is the most common authoring error.
  • Policies inherit down the resource hierarchy by default, and inheritance is where most misconfigurations start. A policy set at the organization node applies to every folder and project beneath it unless something lower in the hierarchy explicitly overrides it, and GCP's override behavior doesn't work the way SCP inheritance does in AWS.
  • Custom constraints extend coverage beyond Google's managed catalog, but they only evaluate resource fields the target service exposes to Organization Policy. They don't add arbitrary logic on top of a resource type that hasn't been instrumented for it.

What Is GCP Organization Policy

Organization Policy is a Google Cloud Resource Manager service that lets administrators restrict how resources can be configured across an organization, folder, or project, independent of who's requesting the change. It works by attaching a policy to a constraint (a predefined or custom rule governing one specific configuration behavior) at a node in the resource hierarchy, and that policy takes effect for every resource created under that node from that point forward. Where IAM answers "who can do this," Organization Policy answers "is this configuration allowed to exist at all," and it holds even against a project owner or an organization admin acting through their own IAM permissions. It's one of the guardrail mechanisms cloud providers ship natively rather than something a security team has to bolt on separately. It's closer in spirit to the guardrails native to AWS, Azure, and GCP than to a third-party policy tool.

Where Organization Policy Sits in the Resource Hierarchy

Organization Policy attaches to nodes in Google Cloud's resource hierarchy rather than to individual resources. That hierarchy runs:

Text
Organization
  └── Folder (optional, can nest several levels deep)
        └── Folder
              └── Project
                    └── Resource (VM, bucket, dataset, service account, etc.)

A policy set at the organization node is the default for everything beneath it. A policy set at a folder applies to every project in that folder and every folder nested under it. A policy set at a project applies only to that project's resources.

Inheritance is evaluated per constraint, not globally. For a boolean constraint, the effective value at a given node is whichever policy is set closest to that node, walking up from the resource to the organization. If a project has no policy of its own for a constraint, it inherits the value set by the nearest ancestor that has one. A child node can override a parent's boolean policy outright: setting enforce: false at a project beneath an organization that set enforce: true is a valid configuration, unless something else in the organization (a separate policy locking who can edit policies) prevents it.

That's a meaningful difference from how AWS service control policies (SCPs) behave, and it matters for anyone working across both providers. SCPs evaluate as an intersection: a deny anywhere in the chain holds regardless of what's attached directly to the account, and a child can only narrow what a parent allows, never loosen it. GCP's default boolean-constraint inheritance is nearest-wins, not most-restrictive-wins. A security architect who assumes GCP Organization Policy combines like an AWS SCP will misjudge what's enforced on a given project.

List constraints behave differently again, because they carry an inheritFromParent field. When inheritFromParent is true (the default), the node's own allowed and denied values are merged with the effective policy inherited from its parent. When it's false, the node's policy replaces the inherited policy entirely, and the chain above it stops applying for that constraint at that node. There's also a resetToDefault option, which clears a node back to the constraint's original default state rather than either inheriting or overriding with new values. resetToDefault is the right tool for deliberately carving out an exception subtree, and it's easy to reach for inheritFromParent: false by accident when resetToDefault was the intent.

GCP Organization Policy Constraints: Boolean vs. List

Every constraint, managed or custom, is one of two types.

Boolean constraints turn a restriction fully on or fully off. There's no partial state and no list of exceptions inside the constraint itself; exceptions come from where in the hierarchy you set the opposing value.

List constraints allow or deny specific values, referenced either as literal strings or as items from a Google-managed list (regions grouped as in:us-locations, for example). A list constraint's rule can carry an allowedValues set, a deniedValues set, or both, and it can attach a CEL condition so the rule only applies to resources matching that condition.

Managed Constraints

Google ships a growing catalog of predefined constraints covering common security and compliance controls. Some of the most frequently used in production:

ConstraintTypeWhat it restricts
constraints/iam.disableServiceAccountKeyCreationBooleanBlocks creation of new user-managed service account keys
constraints/iam.allowedPolicyMemberDomainsListRestricts IAM principals to specified Cloud Identity or Workspace domains
constraints/compute.vmExternalIpAccessListRestricts which VM instances may be assigned an external IP
constraints/compute.disableSerialPortAccessBooleanBlocks serial port access to Compute Engine instances
constraints/compute.restrictVpcPeeringListRestricts which VPC networks a project's networks can peer with
constraints/gcp.resourceLocationsListRestricts the physical or regional locations where resources can be created
constraints/sql.restrictPublicIpBooleanBlocks Cloud SQL instances from being assigned a public IP
constraints/storage.uniformBucketLevelAccessBooleanRequires uniform bucket-level access on Cloud Storage buckets

Google adds to this catalog regularly. Check IAM & Admin > Organization Policies in the console, or the organization policy constraints reference, for the current full list before assuming a control has to be built as a custom constraint.

Custom Constraints

When a managed constraint doesn't cover what you need, a custom constraint defines a rule against a specific resource type and method using a CEL condition. Custom constraints are scoped to services Google has instrumented for Organization Policy support; they can't evaluate a resource type that hasn't been exposed to the service.

Real Organization Policy Examples

Enforcing a boolean managed constraint. Blocking service account key creation across the organization:

YAML
name: organizations/123456789012/policies/iam.disableServiceAccountKeyCreation
spec:
  rules:
  - enforce: true

Apply it with:

bash
gcloud org-policies set-policy policy.yaml

Enforcing a list managed constraint. Restricting where resources can be created to US and EU locations only:

YAML
name: organizations/123456789012/policies/gcp.resourceLocations
spec:
  rules:
  - values:
      allowedValues:
      - in:us-locations
      - in:eu-locations

Defining and applying a custom constraint. Restricting new Compute Engine instances to E2 machine types:

name: organizations/123456789012/customConstraints/custom.restrictMachineTypes

YAML
resourceTypes:
- compute.googleapis.com/Instance
methodTypes:
- CREATE
condition: "resource.machineType.matches('e2-')"
actionType: ALLOW
displayName: Restrict VM creation to E2 machine types

gcloud org-policies set-custom-constraint custom-constraint.yaml

You have to create a custom constraint before you can enforce it. Once it exists, attach a policy to it the same way you would a managed constraint:

YAML
name: organizations/123456789012/policies/custom.restrictMachineTypes
spec:
  rules:
  - enforce: true

How Organization Policy Rules Resolve

The numeric quotas around Organization Policy (custom constraints per organization, values per list constraint, and similar caps) are the kind of thing Google adjusts as the service matures, so check them directly rather than trusting a number frozen in an article. What's stable, and more useful to design around, is how a rule resolves once it's set:

ConfigurationApplies toEffective behavior
No policy set at this nodeAny constraintInherits the nearest ancestor's effective policy
Policy set at this nodeBoolean constraintsThis node's value wins outright; the parent's value no longer applies at or below this node
inheritFromParent: trueList constraintsThis node's allowed and denied values merge with the effective policy inherited from its parent
inheritFromParent: falseList constraintsThis node's policy replaces the inherited policy entirely; the parent's values stop applying here and below
resetToDefault: trueBoolean or list constraintsClears this node back to the constraint's original default state, ignoring both the parent's policy and any values defined at this node
Rule includes a CEL conditionBoolean or list constraintsThe rule applies only to matching resources; an unconditioned rule in the same policy acts as the fallback for everything else

For the numeric caps themselves, the Resource Manager quotas documentation has the current values. Check it before designing a policy structure that depends on being close to a limit.

Common Mistakes

Assuming boolean constraints combine like AWS SCPs. They don't, for the reasons covered above. Check the effective policy at the resource itself with gcloud org-policies describe, rather than assuming a setting made at the organization still holds several nodes down.

Setting inheritFromParent: false when resetToDefault was the actual intent. Turning off inheritance on a list constraint without supplying replacement values leaves that node with an empty policy, not the constraint's original default. The distinction matters most when someone tries to carve out a temporary exception and ends up removing enforcement entirely instead.

Writing a custom constraint condition against a field the service doesn't expose. A CEL condition can only reference fields Google has made available for that resource type's Organization Policy integration. Not every field on a resource is available to Organization Policy, even when it's visible elsewhere in the API.

Treating Organization Policy as a substitute for IAM. A constraint that blocks external IPs on VMs doesn't touch who can create a VM in the first place. The two systems answer different questions and have to be designed together. For how IAM handles its own conditional logic, see GCP IAM Conditions Explained.

Forgetting that policy changes apply going forward, not retroactively. Enforcing constraints/sql.restrictPublicIp blocks the creation of new noncompliant Cloud SQL instances. It doesn't remove a public IP from an instance that already has one.

Best Practices

Set default guardrails at the organization node and push overrides down to the narrowest folder or project that needs an exception, using resetToDefault or inheritFromParent: false deliberately rather than as a side effect of a broader policy change. Confirm the managed constraint catalog doesn't already cover your use case before building a custom constraint. Use Organization Policy's dry-run mode to evaluate a rule's effect against existing resources before enforcing it, especially for a constraint like gcp.resourceLocations that can touch a large share of an organization's footprint at once. And treat every override below the organization node as something with an owner and a reason, not a one-off exception: an override nobody remembers making behaves exactly like one with no owner at all, and the next audit can't tell the difference.

Why Native

Native maps Organization Policy constraints across a Google Cloud environment against the compliance frameworks a security team is accountable to, and surfaces drift the moment an inherited policy diverges from what's enforced on a given project. See how Native handles compliance enforcement across Google Cloud.

FAQ

What's the difference between GCP Organization Policy and IAM?

IAM controls which principals can perform which actions on which resources. Organization Policy controls which configurations are allowed to exist, regardless of who's requesting them. A principal with full IAM permissions can still be blocked by an Organization Policy constraint.

Can a project override an organization-level policy constraint?

For boolean constraints, yes by default: the nearest policy in the hierarchy wins, so a project can set a different value from its parent organization unless something else restricts who can edit policies. For list constraints, it depends on inheritFromParent. true merges the project's values with the inherited policy; false replaces it entirely.

What's the difference between a managed constraint and a custom constraint?

A managed constraint is predefined by Google and ready to enforce immediately. A custom constraint is defined by an organization against a specific resource type, method, and CEL condition, for a control the managed catalog doesn't cover.

How do I test an organization policy before enforcing it?

Organization Policy supports a dry-run mode that evaluates a policy's effect against existing resources without enforcing it, so you can see what would be blocked before switching enforcement on.

Is Organization Policy the same thing as Policy Controller?

No. Organization Policy is a Resource Manager service that governs configuration at the organization, folder, and project level. Policy Controller is a separate GKE and Anthos capability, built on the open-source Gatekeeper project, that enforces policies inside Kubernetes clusters. They solve related problems at different layers and aren't interchangeable.

Is there a limit to how many custom constraints I can create in an organization?

Yes, custom constraints are capped per organization, and Google has adjusted that cap over time. Check the Resource Manager quotas documentation for the current value before planning a large custom constraint rollout.

Ready to enforce secure-by-design?