GCP for DevOps — Organization Policies

3 minute read

Organization Policies

Organization policies are guardrails that restrict what actions can be performed across your GCP organization. While IAM controls who can do something, organization policies control what can be done — regardless of IAM permissions.

IAM vs Organization Policies

┌─────────────────────────────────────────────────────────┐
│                                                         │
│  IAM:  "Alice CAN create VMs in project-prod"          │
│                                                         │
│  Org Policy: "Nobody CAN create VMs in us-west2        │
│               regardless of IAM permissions"            │
│                                                         │
│  Result: Alice can create VMs, but NOT in us-west2     │
│                                                         │
└─────────────────────────────────────────────────────────┘
Feature IAM Organization Policies
Controls Who can do what What can be done
Applied to Members (users, SAs) Resources (org, folder, project)
Inheritance Down the hierarchy Down the hierarchy
Override Cannot remove inherited allows Can override at lower levels
Example Grant roles/compute.admin Restrict VM locations to us-central1

Constraint Types

Type Description Example
List constraint Allow or deny specific values Allowed VM locations
Boolean constraint Enable or disable a behavior Disable SA key creation

Commonly Used Organization Policies for DevOps

Constraint ID Type Description
Restrict resource locations gcp.resourceLocations List Limit where resources can be created
Disable SA key creation iam.disableServiceAccountKeyCreation Boolean Prevent creating SA keys
Disable SA key upload iam.disableServiceAccountKeyUpload Boolean Prevent uploading SA keys
Require OS Login compute.requireOsLogin Boolean Enforce OS Login for SSH
Restrict VM external IPs compute.vmExternalIpAccess List Control which VMs get public IPs
Restrict Cloud SQL public IPs sql.restrictPublicIp Boolean Prevent public Cloud SQL instances
Restrict VPC peering compute.restrictVpcPeering List Control VPC peering targets
Uniform bucket-level access storage.uniformBucketLevelAccess Boolean Enforce uniform access on buckets

Viewing Organization Policies

# List all available constraints
$ gcloud org-policies list-available-constraints \
    --organization=123456789 \
    --format="table(constraint,listPolicy,booleanPolicy)"

CONSTRAINT                                    LIST_POLICY  BOOLEAN_POLICY
gcp.resourceLocations                         True         False
iam.disableServiceAccountKeyCreation          False        True
compute.requireOsLogin                        False        True
compute.vmExternalIpAccess                    True         False
...

# View the effective policy on a project
$ gcloud org-policies describe gcp.resourceLocations \
    --project=my-project --effective

constraint: constraints/gcp.resourceLocations
listPolicy:
  allowedValues:
  - in:us-central1-locations
  - in:us-east1-locations

Setting Organization Policies

# Restrict resource locations to US regions only
$ gcloud org-policies set-policy policy.yaml --organization=123456789

# policy.yaml:
constraint: constraints/gcp.resourceLocations
listPolicy:
  allowedValues:
    - in:us-locations
# Disable service account key creation (boolean)
$ gcloud org-policies set-policy disable-sa-keys.yaml --organization=123456789

# disable-sa-keys.yaml:
constraint: constraints/iam.disableServiceAccountKeyCreation
booleanPolicy:
  enforced: true
# Require OS Login for all VMs
$ gcloud org-policies set-policy require-oslogin.yaml --organization=123456789
constraint: constraints/compute.requireOsLogin
booleanPolicy:
  enforced: true

Overriding at Lower Levels

Organization policies can be overridden at the folder or project level — unless the parent policy is set with inheritFromParent: false.

# Override at project level — allow a specific region
$ gcloud org-policies set-policy override.yaml --project=dev-sandbox

# override.yaml:
constraint: constraints/gcp.resourceLocations
listPolicy:
  allowedValues:
    - in:us-central1-locations
    - in:europe-west1-locations
  inheritFromParent: true

Restrict VM External IPs

A common DevOps policy — prevent VMs from getting public IPs (force use of Cloud NAT or IAP).

# Deny all external IPs on VMs
$ gcloud org-policies set-policy no-external-ip.yaml --project=prod-project
constraint: constraints/compute.vmExternalIpAccess
listPolicy:
  allValues: DENY
# Allow external IPs only for specific VMs
$ gcloud org-policies set-policy limited-external-ip.yaml --project=prod-project
constraint: constraints/compute.vmExternalIpAccess
listPolicy:
  allowedValues:
    - projects/prod-project/zones/us-central1-a/instances/bastion-host

Custom Organization Policy Constraints

You can create custom constraints for services that support them.

# Create a custom constraint
$ gcloud org-policies set-custom-constraint custom-constraint.yaml
name: organizations/123456789/customConstraints/custom.disableLargeVMs
resourceTypes:
  - compute.googleapis.com/Instance
methodTypes:
  - CREATE
  - UPDATE
condition: "resource.machineType.contains('n2-highmem-128')"
actionType: DENY
displayName: "Deny very large VMs"
description: "Prevents creation of n2-highmem-128 instances"

Dry Run Mode

Test a policy before enforcing it:

# Set a dry-run policy (audit only, does not block)
$ gcloud org-policies set-policy dry-run.yaml --project=my-project
constraint: constraints/gcp.resourceLocations
listPolicy:
  allowedValues:
    - in:us-central1-locations
dryRunSpec: true
# View dry-run audit results in Cloud Logging
$ gcloud logging read 'resource.type="audited_resource" AND protoPayload.metadata.dryRunViolation=true' \
    --project=my-project --limit=10

Policy Hierarchy Example

Organization: example.com
├── Policy: gcp.resourceLocations = [us-locations]
├── Policy: iam.disableServiceAccountKeyCreation = true
│
├── Folder: Production
│   ├── Inherits: gcp.resourceLocations = [us-locations]  ✅
│   ├── Inherits: disableServiceAccountKeyCreation = true  ✅
│   │
│   └── Project: prod-web
│       └── Cannot override parent policies (inherit)
│
└── Folder: Development
    ├── Override: gcp.resourceLocations += [europe-west1]
    ├── Inherits: disableServiceAccountKeyCreation = true  ✅
    │
    └── Project: dev-sandbox
        └── Override: disableServiceAccountKeyCreation = false
            (only if parent allows override)

Common Mistakes

Mistake Why It’s Wrong Fix
Setting org policy without dry-run May break existing workloads Use dry-run first
Restricting locations after resources exist Existing resources are not affected Audit existing resources separately
Not documenting policy exceptions Hard to track why overrides exist Add descriptions to policies
Forgetting inheritFromParent Child policies may not include parent values Set explicitly
Setting policies at org level too strictly Blocks all projects including dev Use folders to scope policies

Quick Reference

Command Description
gcloud org-policies list-available-constraints --organization=ORG List all constraints
gcloud org-policies describe CONSTRAINT --project=PROJ --effective View effective policy
gcloud org-policies set-policy FILE --organization=ORG Set org-level policy
gcloud org-policies set-policy FILE --project=PROJ Override at project level
gcloud org-policies reset CONSTRAINT --project=PROJ Reset to inherited policy
gcloud org-policies set-custom-constraint FILE Create custom constraint

Next → Practice Exercises

Updated: