Prepare and test your skills
Prepare and test your skills
Policy as code in Google Cloud means the Organization Policy Service centrally defines and programmatically enforces restrictions on resource creation and modification. An organization policy administrator defines an organization policy as a set of constraints that apply to Google Cloud resources and their descendants in the Google Cloud resource hierarchy. Policies can be attached at the organization, folder, or project level, so development, staging, and production environments inherit the same guardrails without manual checks in each project.
The Organization Policy Service provides centralized, programmatic control over resources across organization, folder, and project nodes. A constraint defines the restriction, while the organization policy attaches that constraint to a node in the hierarchy. By default, organization policies are inherited by descendants, so a policy enforced on a folder is enforced by Google Cloud on all projects in that folder unless inheritance is explicitly changed.
| Constraint type | Level of control | Choose when |
|---|---|---|
| Managed constraint | Built-in best practice for a Google Cloud service | The desired guardrail already exists, such as blocking external IPs on VMs |
| Custom constraint | Granular control over specific resource fields and operations | Built-in constraints are not specific enough, such as restricting machine family, disk type, or label values |
Managed constraints let platform teams apply proven recommendations quickly, while custom constraints express organization-specific compliance, cost, and security rules as code. Both types travel with the hierarchy, which keeps environments consistent and causes a create or update request that violates policy to fail with an error.
Custom constraints restrict specific fields and operations on supported resource types before the resource persists. The request flows from the caller to the Google Cloud API, the Organization Policy Service evaluates the custom constraint (opens in a new tab) before creation, and only compliant resources are created or updated. Custom constraints therefore extend managed constraints when field-level control is required for cost, isolation, and governance.
Supported resources span compute, containers, data, and automation:
compute.googleapis.com/Disk, compute.googleapis.com/Image, compute.googleapis.com/Instance, compute.googleapis.com/InstanceGroupcontainer.googleapis.com/Cluster, container.googleapis.com/NodePoolspanner.googleapis.com/Instance and spanner.googleapis.com/Database, BigQuery Data Transfer bigquerydatatransfer.googleapis.com/TransferConfig, Dataproc Metastore services, backups, and metadata importsworkflows.googleapis.com/Workflow, Backup and DR (opens in a new tab) vaults, plans, and associations, and VMware Engine clusters, private clouds, network policies, and peeringsPractical uses include restricting VM instance and disk sizes, types, and machine families for cost control, requiring sole-tenant nodes for hardware isolation, requiring specific firewall port rules, and verifying that automation labels match specified expressions. Limits are service-specific, such as no custom-constraint support for metastore.googleapis.com/Federation, use of resource.dataSourceId to specify a BigQuery Data Transfer data source, and no support for output-only GKE fields like masterAuth.clientKey and masterAuth.password.
Exam tip: Tags on projects and folders can drive conditional organization policy enforcement, but tags attached directly to GKE clusters cannot be used for conditional enforcement.
Foundational Google Cloud-wide constraints establish data residency, encryption, and service-availability boundaries that all workloads inherit. The gcp.resourceLocations constraint restricts creation of new resources to allowed values such as us and specific US regions including us-central1, us-east1, and us-west1. The gcp.restrictNonCmekServices constraint requires customer-managed encryption keys (CMEK) for listed services such as bigquerydatatransfer.googleapis.com, so at-rest data uses a customer-managed key instead of Google default encryption. The gcp.restrictServiceUsage constraint determines which services remain usable by restricting runtime access to their resources.
| Constraint | What it controls | Risk if made less restrictive |
|---|---|---|
gcp.resourceLocations | Where new resources and data can be created | Data may be created outside the compliant boundary and residency effects may be difficult or impossible to reverse |
gcp.restrictNonCmekServices | Which services require CMEK for at-rest data | New at-rest data is encrypted with Google-owned keys instead of customer-managed keys |
gcp.restrictServiceUsage | Which services and API endpoints remain usable | Unauthorized or out-of-scope services become available for runtime use |
These guardrails are intentionally difficult to reverse because relaxing them can undermine residency or sovereignty after data has spread. Automated mechanisms that manage organization policies must be protected against unintentional changes, and relaxation should be reviewed with the authorizing agency.
Exceptions to broadly enforced policies must be narrow, reviewed, and compensated when risk remains. A blueprint may enforce iam.disableServiceAccountKeyCreation because leaked keys have significant impact, yet an on-premises server that cannot use Workload Identity Federation may legitimately require a key. The exception workflow (opens in a new tab) moves from workload request to technical review to a narrowly scoped policy change, plus compensating controls such as best practices for managing service account keys. Conditional enforcement can implement this pattern by defining a tag for exception or enforcement and applying that tag to specific projects and folders.
Organization-wide changes should first be validated in a separate test organization because identity, hierarchy, and policy changes have no separate development copy in production. Workload resources can use development, non-production, and production environments, but organization-level configuration affects production directly. A separate organization provides an isolated boundary where policy edits, identity provider changes, and pipeline behavior can be tested before rollout.
Two additional boundaries complement hierarchy policy when hierarchy policy alone is insufficient. A VPC Service Controls perimeter controls exfiltration between the Google Cloud organization and external sources by denying access to restricted services from traffic that originates outside the perimeter, including the console, developer workstations, and deployment pipelines. Perimeters should start in dry-run mode and move to enforced mode only after planning exceptions, break-glass access for pipeline recovery, and a process for adding new projects, with a common unified perimeter preferred unless distinct threats justify multiple perimeters. For GKE workloads, admission control enforces policy when authenticated and authorized requests reach the Kubernetes API before they persist, with Policy Controller controlling admission at scale across multiple clusters and the PodSecurity admission controller enforcing Kubernetes Pod Security Standards on clusters or namespaces.
Declarative configuration and environment isolation represents each Google Cloud environment as versioned code with its own separated state. Terraform bulk export implements this pattern by exporting live Google Cloud resources as Terraform configurations and importing existing resources into Terraform state (opens in a new tab), so future changes are managed through code rather than manual edits. Each environment, typically a separate project for development, staging, and production, is exported to its own output directory and state, which maintains consistency while preventing drift and cross-environment interference.
The end-to-end workflow moves resources from live infrastructure into managed code in order:
Preparing the export environment establishes the tooling and project boundary that keeps each environment isolated. All export work runs from Cloud Shell, with the target project set once per project, so resources from development, staging, and production are never mixed in a single export.
export GOOGLE_CLOUD_PROJECT=PROJECT_ID for the project being exported. An explicit value set in a Terraform configuration file overrides this environment variable.gcloud components install config-connector, which enables the bulk-export tool. If the component manager is disabled, use sudo apt-get install google-cloud-sdk-config-connector instead.gcloud services enable cloudasset.googleapis.com, which the bulk-export operation depends on to inventory project resources.Exam tip: Bulk export is not supported on Windows operating systems — run the export workflow from Cloud Shell.
Generating declarative Terraform configuration converts the live state of one project into files that can be versioned and reused. First create a dedicated directory with mkdir OUTPUT_DIRECTORY to hold that environment's configuration separately from other environments. Then run gcloud beta resource-config bulk-export --path=OUTPUT_DIRECTORY --project=PROJECT_ID --resource-format=terraform to write the project's entire configuration into that directory. Because the --project and --path flags scope the export to one project and one directory, repeating the same command with different values produces parallel, isolated baselines for development, staging, and production.
Converting exported output into reusable modules and isolated state makes generated files manageable and binds them to existing infrastructure. The bulk-export output directory is the source, and Terraform state is the destination that tracks ownership and detects drift. Running gcloud beta resource-config terraform generate-import OUTPUT_DIRECTORY creates two artifacts: a gcloud-export-modules.tf file that declares a module block with a source path for each exported resource type, such as ComputeFirewall and ComputeBackendService, and an executable shell script such as terraform_import_20220331-19-12-33.sh containing terraform import commands that map each module resource to its live resource ID. Only after the modules exist, run terraform init and then execute the import script to import each resource, such as projects/PROJECT_ID/zones/us-central1-a/instances/instance-1, into state. Once imported, Terraform manages that environment declaratively, so manual changes appear as drift and each environment's state remains independent.
Automate GitOps-driven configuration and drift reconciliation defines desired cluster state once centrally and continuously pushes that state to every environment. GKE attached clusters (opens in a new tab) extends this model beyond Google Cloud by registering externally created Kubernetes clusters as centrally managed resources. Once attached, staging, production, and external clusters can receive the same fleet-wide configuration and policy enforcement without manual per-cluster changes.
Attaching a cluster unlocks fleet tools that operate through the central management plane:
Because these tools act from Google Cloud toward attached clusters, drift between intended state and actual cluster state can be detected centrally and corrected by reapplying the fleet definition.
Config Sync is the fleet service that deploys cluster configurations consistently across multiple environments. The fleet groups Google Kubernetes Engine (GKE) clusters and attached external clusters under one operational scope, so one configuration change applies to staging and production together. The AttachedCluster resource in the GKE Multi-Cloud API makes this possible by representing each external cluster inside the Google Cloud resource hierarchy. Central operations depend on that resource: without the AttachedCluster representation, Config Sync has no fleet target to reconcile.
| Tool | What it applies to the fleet | Consistency role |
|---|---|---|
| Config Sync | Cluster configurations | Distributes the desired configuration to every fleet cluster |
| Policy Controller | Policy and security controls | Enforces guardrails so clusters stay compliant with organizational rules |
Config Sync handles what clusters should look like, while Policy Controller handles what clusters are allowed to do.
Policy Controller is the fleet service that automates policy and security across all clusters within a fleet. Policy Controller applies the same constraints to GKE clusters and to attached Amazon Elastic Kubernetes Service (EKS), Azure Kubernetes Service (AKS), and other conformant Kubernetes clusters. This separation matters because configuration distribution alone does not prevent local changes that violate security requirements. When Policy Controller evaluates every fleet cluster against the same policies, noncompliant drift is surfaced consistently whether the cluster runs in Google Cloud, AWS, Azure, or on premises.
Exam tip: Choose Config Sync when the goal is to deploy shared configuration across the fleet, and choose Policy Controller when the goal is to automate policy and security enforcement across the fleet.
The secure control plane for multi-environment reconciliation is the GKE attached clusters architecture built on a regional AttachedCluster resource and an in-cluster agent. When GKE attached clusters is installed, a new AttachedCluster resource is created in the Google Cloud project as a regional resource. All metadata associated with the cluster is stored in the Google Cloud region associated with that resource, which places Google Cloud on one side of a data-residency boundary and keeps cluster metadata inside the selected region for compliance.
Reconciliation traffic flows from the external cluster to Google Cloud first, then from Google Cloud back to the cluster. GKE attached clusters deploys a workload called the Connect Agent inside the external Kubernetes cluster. The Connect Agent connects back to the Connect API service on Google Cloud to create a secure link, and GKE attached clusters uses that secure tunnel to manage Config Sync, Policy Controller, and Cloud Service Mesh features. Because the tunnel is initiated outward from the cluster to Google Cloud, central teams can monitor and control attached clusters through the Google Cloud CLI or Google Cloud console without exposing the clusters through separate inbound management paths.
gcp.resourceLocations, gcp.restrictNonCmekServices, and gcp.restrictServiceUsage constraints control resource location, CMEK encryption requirements, and usable services.Managed constraints are built-in best practices for a Google Cloud service, such as blocking external IPs on VMs, while custom constraints provide granular control over specific resource fields and operations, such as restricting machine family, disk type, or label values. Both types attach to organization, folder, or project nodes and are inherited by descendants, and a create or update request that violates policy fails with an error.
Use Config Sync when the goal is to deploy shared cluster configurations consistently to every fleet cluster, and use Policy Controller when the goal is to automate policy and security enforcement across the fleet. Config Sync distributes what clusters should look like, while Policy Controller enforces what clusters are allowed to do and surfaces noncompliant drift whether clusters run in Google Cloud, AWS, Azure, or on premises.
Terraform bulk export exports one project at a time into a dedicated output directory and isolated Terraform state, so development, staging, and production remain separate and manual changes appear as drift. The workflow prepares Cloud Shell for one project, bulk-exports the configuration, generates reusable modules and an import script, then runs terraform init and the import script to bind live resources to state for declarative management.
Your enterprise manages three separate Google Cloud environments (development, staging, and production) deployed across distinct GCP projects. The security team requires uniform Sensitive Data Protection (Cloud DLP) inspection rules—such as scanning for national identifiers, credentials, and sensitive customer data—across storage repositories in all environments. Currently, individual teams define inline inspection configurations inside their local continuous integration and continuous deployment (CI/CD) pipelines, which has caused severe configuration drift and high operational maintenance.
You need to implement a declarative Infrastructure as Code (IaC) configuration architecture that enforces standardized inspection policies across all environments, isolates deployment states, and allows policy updates without modifying downstream jobs. What should you do?
Last updated