Google Cloud Organisation Policies — Get the “Restrict VPC Peering Usage” Organisation Policy Right !!!!!

--

Google Cloud has a very useful resource governance feature — the Organisation Policy Service which gives you centralised and programmatic control over your organisation’s cloud resources. As the organisation policy administrator, you will be able to configure restrictions across your entire resource hierarchy.

This helps centralise control to configure restrictions on how your organisation’s resources can be used, define and establish guardrails for your development teams to stay within compliance boundaries, and help project owners and their teams move quickly without worry of breaking compliance.

Concepts

An organisation policy is a configuration of restrictions. You, as the organisation policy administrator, define an organisation policy, and you set that organisation policy on a resource hierarchy node in order to enforce the restrictions on that resource hierarchy node and its descendants.

In order to define an organisation policy, you choose a constraint, which is a particular type of restriction against either a Google Cloud service or a group of Google Cloud services. You configure that constraint with your desired restrictions.

Descendants of the targeted resource hierarchy node inherit the organisation policy. By applying an organisation policy to the root organisation node, you are able to effectively drive enforcement of that organisation policy and configuration of restrictions across your organisation.

VPC Peering and why you need to worry

Google Cloud VPC Network Peering allows private RFC 1918 connectivity across two Virtual Private Cloud (VPC) networks regardless of whether they belong to the same project or the same organisation.

VPC Network Peering enables you to peer VPC networks so that workloads in different VPC networks can communicate in private RFC 1918 space. Traffic stays within Google’s network and doesn’t traverse the public internet.

VPC Network Peering is useful for:

  • SaaS (Software-as-a-Service) ecosystems in Google Cloud. You can make services available privately across different VPC networks within and across organisations.
  • Organisations with several network administrative domains can peer with each other.

This, given its a very powerful connectivity construct, does bring in some security concerns. What if someone peers your VPC network with a malicious entity? What if someone peers the development and production networks?

VPC Peering Controls

Towards this, Google has made available a bunch of VPC restriction policies, one of them being “Restrict VPC Peering Usage”. This list constraint defines the set of VPC networks that are allowed to be peered with the VPC networks belonging to this project, folder, or organisation. By default, a Network Admin for one network can peer with any other network. The allowed/denied list of networks must be identified in the form: under:organizations/ORGANIZATION_ID, under:folders/FOLDER_ID, under:projects/PROJECT_ID, or projects/PROJECT_ID/global/networks/NETWORK_NAME.

That sounds pretty awesome, an organisation’s information security team, could, at the topmost level, restrict peering to its own organisation IDs. And we did just that. Problem Solved. Ergghhh, not quite. Some Google products like Cloud SQL and Kubernetes Engine rely on customer VPCs peering with Google’s own VPCs. Hmm, getting interesting. Google would have taken care of these peerings then when allowing for controls. Not really, at least, at the time of this writing.

Does Google have one organisation ID (“0” would be my guess ;-)) we should additionally allow? So we started a dialog with Google Support to understand a way forward!

Workaround to use Google Services

While we waited, we could not afford to stop building our terraform scripts around Kubernetes Engine cluster and Cloud SQL instance creation. So we decided to leverage the terragrunt feature for before and after hooks. In the before hook, we would disable the VPC peering controls in the project we are creating the resource and in the after hook, we would revert to inheriting the limitations imposed by resources up in the hierarchy. Unfortunately the way it works with Google Cloud, this means the credentials used to run the script need Organisation Policy Administrator at Organisation Level. Not scaleable in any significant size organisation, to be honest.

-------------------- Before Hook --------------------
-------------------- override-vpc-peering --------------------
#!/usr/bin/env python3

from os import environ
from sys import exit

from argparse import ArgumentParser

from googleapiclient import discovery
from oauth2client.client import GoogleCredentials

from pprint import pprint

if 'OVERRIDE_VPC_PEERING' not in environ:
print('OVERRIDE_VPC_PEERING not set. Exiting without any changes.')
exit()

parser = ArgumentParser(description='change_owner command line parser')
parser.add_argument("--project-id", required=True, type=str, help='Your cloud project ID.')

args = parser.parse_args()

project_id = args.project_id

credentials = GoogleCredentials.get_application_default()

service = discovery.build('cloudresourcemanager', 'v1', credentials=credentials)

# Resource name of the resource to attach the `Policy`.
resource = 'projects/' + project_id

set_org_policy_request_body = {
"policy": {
"constraint": "constraints/compute.restrictVpcPeering",
"listPolicy": {
"allValues": "ALLOW"
}
}
}

request = service.projects().setOrgPolicy(resource=resource, body=set_org_policy_request_body)
response = request.execute()

pprint(response)
-------------------- After Hook --------------------
-------------------- inherit-vpc-peering --------------------
#!/usr/bin/env python3

from os import environ
from sys import exit

from argparse import ArgumentParser

from googleapiclient import discovery
from oauth2client.client import GoogleCredentials

from pprint import pprint

if 'OVERRIDE_VPC_PEERING' not in environ:
print('OVERRIDE_VPC_PEERING not set. Exiting without any changes.')
exit()

parser = ArgumentParser(description='change_owner command line parser')
parser.add_argument("--project-id", required=True, type=str, help='Your cloud project ID.')

args = parser.parse_args()

project_id = args.project_id

credentials = GoogleCredentials.get_application_default()

service = discovery.build('cloudresourcemanager', 'v1', credentials=credentials)

# Resource name of the resource to attach the `Policy`.
resource = 'projects/' + project_id

clear_org_policy_request_body = {
"constraint": "constraints/compute.restrictVpcPeering",
}

request = service.projects().clearOrgPolicy(resource=resource, body=clear_org_policy_request_body)
response = request.execute()

pprint(response)
-------------------- terragrunt.hcl --------------------
terraform {
source = "."
before_hook "override-vpc-peering" {
commands = ["apply"]
execute = ["override-vpc-peering", "--project-id", local.network_project]
}
after_hook "inherit-vpc-peering" {
commands = ["apply"]
execute = ["inherit-vpc-peering", "--project-id", local.network_project]
run_on_error = true
}
extra_arguments "extra_variables" {
commands = ["apply"]
env_vars = {
OVERRIDE_VPC_PEERING = ""
}
}
}

Current working solution

With some arm-twisting ;-)

We have managed to get the configuration from Google support which seems to be working.

constraint: constraints/compute.restrictVpcPeering
listPolicy:
inheritFromParent: false
allowedValues:
# Required if projects use services that rely on peering via service
networking. E.g., Cloud SQL.
- under:folders/832634261155 #
google.com/tenancy-units/service-networking folder.
- under:folders/1087601843002 # google.com/products/speckle/ folder for
the use of Cloud SQL
# Required if projects use GKE private clusters.
- under:folders/391150242170 # google.com/tenancy-units/gke/prod folder
for GKE master peering.

Effectively they have revealed the folders under which these VPCs can exist instead of the organisation ID.

References

  1. https://cloud.google.com/resource-manager/docs/organization-policy/overview
  2. https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints
  3. https://terragrunt.gruntwork.io/docs/features/before-and-after-hooks/

--

--