Skip to main content

Organization Policy Service

The Organization Policy Service restricts what any principal may configure, whatever IAM roles it holds. The GCP Enterprise Baseline sets 19 constraints at the organization node, so every folder and project inherits them and no project Owner can switch one off.

What it does​

An organization policy applies a constraint to a node of the resource hierarchy. Boolean constraints switch a behavior on or off, such as "no service account keys". List constraints allow or deny values, such as the regions resources may be created in. A policy set at the organization is inherited by every folder and project; a lower node can override it only where a policy says so. Custom constraints express a rule in CEL (Common Expression Language) over a resource's fields, and any policy can run as a dry run that logs violations without blocking them.

How BuiltForProd uses it​

The organizations unit sets every constraint at the organization node from two maps in modules/organizations/org-policies.tf:

GCP/acme-gcp-platform-baseline/modules/organizations/org-policies.tf (lines 18-43)
locals {
boolean_constraints = {
"iam.disableServiceAccountKeyCreation" = true
"iam.disableServiceAccountKeyUpload" = true
"iam.automaticIamGrantsForDefaultServiceAccounts" = true
"storage.publicAccessPrevention" = true
"storage.uniformBucketLevelAccess" = true
"compute.skipDefaultNetworkCreation" = true
"compute.requireOsLogin" = true
"compute.requireShieldedVm" = true
"compute.disableSerialPortAccess" = true
"sql.restrictPublicIp" = true
"sql.restrictAuthorizedNetworks" = true
}
network_project = "${var.namespace}-core-network${var.project_id_suffix}"
list_constraints = {
"iam.allowedPolicyMemberDomains" = { allowed = var.allowed_member_customer_ids }
"iam.workloadIdentityPoolProviders" = { allowed = ["https://token.actions.githubusercontent.com"] }
"compute.vmExternalIpAccess" = { denied_all = true }
"compute.restrictVpcPeering" = { allowed = ["under:projects/${local.network_project}"] }
"compute.restrictSharedVpcHostProjects" = { allowed = ["under:projects/${local.network_project}"] }
"run.allowedIngress" = { allowed = ["internal-and-cloud-load-balancing"] }
"essentialcontacts.allowedContactDomains" = { allowed = ["@${var.org_domain}"] }
"gcp.resourceLocations" = { allowed = var.allowed_locations }
}
}

The eleven boolean constraints block service account key creation and upload, automatic Editor grants to default service accounts, public buckets and per-object ACLs, the default network, VMs without OS Login or Shielded VM, serial port access, and public IPs or authorized networks on Cloud SQL. The eight list constraints:

ConstraintWhat it holds
iam.allowedPolicyMemberDomainsIAM members only from the organization's Cloud Identity customer
iam.workloadIdentityPoolProvidersWorkload Identity Federation trusts the GitHub Actions issuer only
compute.vmExternalIpAccessNo VM gets an external IP address
compute.restrictVpcPeeringPeering only with networks of acme-core-network
compute.restrictSharedVpcHostProjectsacme-core-network is the only Shared VPC host
run.allowedIngressCloud Run accepts internal and load-balancer traffic only
essentialcontacts.allowedContactDomainsEssential Contacts only on the organization's domain
gcp.resourceLocationsThe home region, every region with folders in the repository, and us

The region list is not typed by hand: the unit derives it from the home region and every region folder under environments/, plus the us multi-region that Artifact Registry and dual-region buckets need. Adding a region folder opens that region.

Exceptions. acme-core-public serves intentionally public objects, so it carries two project-level overrides: public access prevention off, and domain-restricted sharing open (allUsers is not a member of the organization's customer). Each stage project also receives a project-level compute.restrictSharedVpcSubnetworks policy from the shared-vpc-service unit, which lets it use only its own stage subnets of the Shared VPC.

Custom label constraints. Three custom constraints, custom.requirePlatformLabels{Instance,Cluster,Bucket}, deny Compute Engine instances, GKE clusters and Cloud Storage buckets created or updated without the namespace, stage and managed_by labels. They run as a dry run (enforce_label_policy = false): violations are logged and nothing is blocked until the switch is turned on once the log is clean.

Organization policies cannot protect log sinks, so the audit trail is guarded by an IAM deny policy instead. A change to modules/ needs a review from the infrastructure admins and the platform leads (CODEOWNERS).

Terms you will see​

TermMeaning
ConstraintA named restriction, such as iam.disableServiceAccountKeyCreation.
Boolean / listThe two built-in constraint types: on or off, or a set of allowed or denied values.
Custom constraintA constraint written in CEL over a resource's fields, named custom.<name>.
Dry runA policy spec that logs violations without enforcing them.
OverrideA project-level policy that replaces the inherited one, as on acme-core-public.
InheritanceA policy at the organization applying to every folder and project beneath it.

Where to read more​