GCP Organization Policy vs IAM: What Each One Actually Controls
Verdict: Use IAM to control what a specific identity can do on a specific resource. Use Organization Policy to make a configuration structurally impossible regardless of who's asking.
They both live in GCP's resource hierarchy. They both inherit from organization to folder to project. They both produce an "access denied" response when they block something. That's where the similarity ends.
IAM answers the question of who can act. Organization Policy answers the question of what configurations are allowed to exist at all. Treating them as alternatives, or assuming one handles what the other is designed to do, produces environments where structural guardrails look complete on paper but aren't being enforced at the layer that matters.
Key Takeaways
- IAM manages the relationship between a principal and a resource. Organization Policy manages what configurations are permitted to exist, regardless of which principal is requesting them.
- An Organization Policy constraint takes precedence over IAM permissions. A project Owner still can't create a service account key if
iam.disableServiceAccountKeyCreationis enforced at a higher level. - Both controls operate within GCP's resource hierarchy and both can be set at the organization, folder, or project level. They're designed to be layered, and most well-governed GCP environments use both.
- The most common mistake isn't choosing the wrong control. It's trying to handle structural guardrails with IAM alone, which requires managing exceptions across every project rather than setting a constraint once at the org level.
What GCP IAM Controls
IAM manages the relationship between a principal and a resource. A principal is any identity that can authenticate to GCP: a user account, a service account, a Google group, or a Workspace domain. A role is a named bundle of permissions. An IAM policy binding connects a principal to a role at a specific point in the resource hierarchy, and that binding determines what the principal can do on that resource and everything below it.
When you want to give a developer read access to a Cloud Storage bucket, that's IAM. When you want a CI/CD service account to deploy to a staging project but not delete resources, that's IAM. When you want to ensure only your security audit team can access Cloud Audit Logs, that's IAM.
IAM policies are additive and inherited. A binding set at the organization level is inherited by every project under that organization. A binding added at the project level adds to whatever was inherited from above. Allow policies can't be subtracted lower down: a project can't remove a role binding it inherited from the organization. IAM deny policies are the exception, and because they're evaluated before allow policies they're the tool for carving out an inherited permission. Neither mechanism stops a configuration from existing, though, which is one reason the two controls solve different problems.
What IAM doesn't do: it doesn't prevent configurations from being created. If a principal has a role that permits creating a VM with an external IP, or generating a service account key, or making a Cloud Storage bucket public, IAM doesn't provide a way to say that configuration itself is prohibited regardless of role. That's the gap Organization Policy fills.
What GCP Organization Policy Controls
Organization Policy operates on configurations, not identities. It defines what is allowed to happen in your GCP environment through constraints applied to resources across the hierarchy, regardless of what any IAM policy grants.
A constraint is a restriction on a specific resource behavior. The constraint iam.disableServiceAccountKeyCreation prevents any principal from creating a service account key, even if their IAM role explicitly includes that permission. The constraint compute.vmExternalIpAccess controls which VMs can have external IPs. The constraint gcp.resourceLocations prevents resources from being created outside approved regions. Google now ships newer managed constraints alongside these legacy ones, such as compute.managed.vmExternalIpAccess, so check which form your organization is standardizing on. None of these depend on per-identity configuration, and none of them can be bypassed by a more permissive IAM binding.
Organization Policy constraints are set at the organization, folder, or project level and inherit downward. Enforcing a constraint at the organization root applies it to every project in the environment automatically, including projects created in the future. A folder or project can set its own policy that overrides what it inherited, which is how controlled exceptions get carved out without relaxing org-wide defaults. Nothing in the parent policy grants or withholds that ability. What controls it is who holds Organization Policy Administrator (roles/orgpolicy.policyAdmin) on the lower node. For list constraints, denied values always win on merge, so a child can't re-allow a value the parent denied.
Google Cloud also provides a dry-run mode for organization policies. In dry-run mode, violations are logged but the action isn't blocked, which makes it possible to understand a constraint's impact on existing workflows before enforcing it. This matters especially for constraints that affect automation, because CI/CD pipelines are usually the first thing to break when a new constraint is applied too broadly.
What Organization Policy doesn't do: it can't grant access. Constraints are restrictive only. They can prevent a configuration from being created, require a specific setting, or block a behavior category, but they don't authorize actions. IAM remains the mechanism for granting permissions.
GCP Organization Policy vs IAM: Side-by-Side Comparison
| GCP IAM | GCP Organization Policy | |
|---|---|---|
| What it controls | Who can perform which actions on which resources | What configurations and resource behaviors are allowed at all |
| Enforcement target | Principals (users, service accounts, groups) | Resources and configurations across the hierarchy |
| Enforcement mechanism | Role bindings attached to resources at hierarchy level | Constraints applied to org, folder, or project nodes |
| Can it grant access? | Yes | No. Constraints are restrictive only |
| Overridden by IAM? | N/A | No. A constraint blocks an action even if IAM grants the permission |
| Inheritance model | Additive. Permissions accumulate down the hierarchy | Inherited. Constraints propagate down, and a lower level can override only if someone there holds Organization Policy Administrator |
| Applies to future resources? | Only if bindings exist at the relevant hierarchy level | Yes. Constraints apply automatically to new resources in scope |
| Typical use cases | Granting deployment access to a service account; scoping read access to a specific project | Blocking service account key creation org-wide; preventing external IPs on VMs; restricting resource locations |
| How failures surface | Permission denied due to missing role binding | Constraint violation, though both often surface as "access denied" in the console |
Decision Framework: Which One to Use
A single question reliably separates the two: if a sufficiently privileged IAM principal tried to do this, should they be able to?
If the answer is yes, IAM is the right control. Grant or restrict based on identity, role, and resource scope.
If the answer is no regardless of who's asking, Organization Policy is the right control. The configuration itself should be structurally prevented, not just access-controlled per identity.
Three questions worth running for any new security requirement:
Is this about who can act, or what's allowed to happen? Scoping access for a specific team or service account is an IAM problem. Preventing a configuration from being possible at all is an Organization Policy problem. The distinction matters because one is identity-scoped and the other is architecture-scoped.
Should this restriction hold even if someone has admin-level permissions? IAM admin roles can always override IAM restrictions within their scope. If the restriction needs to hold regardless of IAM grants, it needs to be an Organization Policy constraint. This is the clearest signal that you're looking at an Organization Policy use case.
Does this need to apply automatically to new projects as the environment grows? IAM bindings are explicit. Every new project needs bindings set if you want access rules to apply to it. Organization Policy at the org level applies automatically to every project created in the future without additional configuration, which matters a lot in environments where new projects are being spun up frequently.

Worked Scenario: Using Both Controls Together
Consider a team managing a GCP environment with production, staging, and development folders. Their requirements include: no service account keys in production, deployment access limited to a CI/CD service account, and no resources deployed outside their approved regions.
The region restriction and the key creation prohibition belong to Organization Policy. Both are configurations that should be structurally impossible regardless of who's operating in the environment. Setting gcp.resourceLocations at the organization level and iam.disableServiceAccountKeyCreation on the production folder handles both without any per-project IAM configuration. These constraints will also apply to any new project created under those folders without requiring additional setup.
The CI/CD deployment access belongs to IAM. It's a specific principal (the CI/CD service account) that needs specific permissions (deploy, not delete) scoped to specific projects (staging and production). An IAM role binding scoped to the relevant projects handles this precisely.
Neither control alone covers the full picture. Organization Policy makes structural constraints hold regardless of identity. IAM makes the access model specific to the identities and resources that need it. Together, they're what a layered cloud security controls architecture actually requires.
Where Teams Get This Wrong
Treating the two controls as alternatives. Organization Policy and IAM are complementary layers, not competing approaches. Scoping IAM roles tightly and assuming that's sufficient won't prevent misconfiguration. IAM governs what identities can do. It doesn't stop configurations that a permissioned principal is allowed to create but shouldn't.
A useful rule of thumb from GCP's own documentation: if a security requirement can be violated by a sufficiently privileged IAM user, Organization Policy should enforce it instead. That framing cuts through a lot of confusion about which control to reach for.
Assuming the error message tells you which control failed. Both IAM permission failures and Organization Policy violations often surface as "access denied" in the console and in API responses. When a deployment fails with an access error, the cause could be a missing IAM binding, a constraint violation, or both. Checking only IAM when a deployment breaks and ignoring Organization Policy is a consistent source of debugging confusion. If correcting an IAM binding doesn't resolve the error, the next step is checking whether an Organization Policy constraint is blocking the operation at the hierarchy level.
Applying constraints too broadly without dry-run testing first. Organization Policy constraints apply immediately across their scope. Enabling iam.disableServiceAccountKeyCreation at the org level without first auditing whether any existing automation depends on service account keys can break CI/CD pipelines silently. Google Cloud's dry-run mode lets you log violations without blocking actions, which makes it possible to understand the actual impact before enforcing. Running a constraint in dry-run against staging first is worth the step, particularly in environments where infrastructure automation is spread across multiple teams and may not be fully inventoried.
Managing structural guardrails through per-project IAM review. If you're reviewing IAM bindings across fifty projects to prevent public Cloud Storage buckets, that's a maintenance problem that compounds as the environment grows. The storage.publicAccessPrevention constraint handles it once at the org level. The structural rule is: if a restriction needs to hold everywhere, set it in Organization Policy at the highest appropriate level of the hierarchy, not in IAM across every project.
Frequently Asked Questions
What's the core difference between GCP IAM and Organization Policy?
IAM controls who can perform an action on a specific resource. Organization Policy controls what configurations are allowed to exist at all, regardless of who's asking. IAM grants access. Organization Policy restricts behavior. Both operate within GCP's resource hierarchy and both can be configured at the organization, folder, or project level, but they enforce at different layers and aren't interchangeable.
Can Organization Policy override IAM permissions?
Yes, in specific cases. If an Organization Policy constraint prevents an action, the action is blocked even if the requesting principal has an IAM role that includes the relevant permission. A user with the Storage Admin role can't make a bucket public if storage.publicAccessPrevention is enforced at a higher hierarchy level. Organization Policy takes precedence.
Does Organization Policy apply to existing resources?
It depends on the specific constraint. Some constraints apply only to resources created after enforcement and don't retroactively change existing configurations. Others apply immediately to existing resources in scope. For example, enforcing storage.publicAccessPrevention blocks public reads immediately, but it doesn't delete the existing allUsers or allAuthenticatedUsers bindings. They stay in place, overridden, and they take effect again if the constraint is ever removed, so those bindings still need to be cleaned up separately. Checking the behavior documented for each specific constraint before enforcing it is important, particularly for constraints that may modify existing configurations.
Can I use Organization Policy to grant access?
No. Organization Policy constraints are restrictive only. They can block behaviors, require settings, and prevent configurations, but they can't grant permissions or authorize actions. IAM handles access grants.
What's the right way to layer both controls?
Set Organization Policy constraints at the highest hierarchy level that makes sense for your structural guardrails. Use them to enforce configurations that should hold regardless of identity, particularly around key creation, resource location, public access, VM external IPs, and other defaults that are convenient but insecure. Use IAM for everything identity-scoped: who can deploy, who can read logs, which service accounts can act on which resources. The two controls are built to work together, and a well-governed GCP environment uses both.
How do I keep both aligned as the environment grows?
The structural challenge isn't defining the controls initially. It's keeping them aligned as new projects are added, new teams spin up workloads, and existing constraints accumulate exceptions. Native helps organizations maintain this layer across GCP, AWS, Azure, and OCI: expressing architectural intent through zones, boundaries, and baselines and connecting that intent to the native controls already present in each provider. See how Native works on your environment.