Google Cloud
Setup guide for the Common Fate GCP integration.
This guide will walk you through integrating Common Fate with Google Cloud (GCP). At the end of this guide you’ll have a functioning integration with Common Fate reading your account inventory and provisioning access to entitlements.
GCP Setup
Common Fate is hosted in your AWS account, and uses Workload Identity Federation to authenticate to GCP Service Accounts. By default, we use two Service Accounts: one for reading available entitlements and a separate one for assigning access. If you want to keep things simple you can combine these into a single role, but we recommend using two separate roles to give you easy visibility as to when the provisioning role is being used.
Before you deploy any resources you’ll need to created a dedicated project in Google Cloud for our integration. You can call this project “Common Fate”.
You’ll also need access to a role with the ability to create role bindings in your GCP organization.
The permissions that the read role uses are:
- iam.roles.get
- iam.roles.list
- resourcemanager.folders.get
- resourcemanager.folders.list
- resourcemanager.organizations.get
- resourcemanager.projects.get
- resourcemanager.projects.list
- resourcemanager.tagKeys.list
- resourcemanager.tagValues.list
- cloudasset.assets.listResource
The permissions that the provision role uses are:
- resourcemanager.projects.getIamPolicy
- resourcemanager.projects.setIamPolicy
- resourcemanager.folders.getIamPolicy
- resourcemanager.folders.setIamPolicy
We have developed a reference integration Terraform module which deploys the following resources:
- A Workload Identity Pool
- A Workload Identity Pool Provider linked to the Common Fate AWS account
- Custom IAM Roles for the reader and provisioner, deployed to the organization
- Service Accounts for the reader and provisioner, deployed to the dedicated Common Fate GCP project you created above
- Role bindings with attribute bindings allowing the Common Fate Control Plane and Provisioner roles to obtain Service Account credentials.
This Terraform module requires sensitive organizational-level GCP permissions. Because of this, we recommend deploying this module in a separate Terraform root module to your Common Fate deployment. This avoids having a single Terraform deployment with privileged access to both your Common Fate deployment, and to your GCP organization.
-
To deploy the reference integration first, create a dedicated project in Google Cloud called “Common Fate”
-
Follow this link to enable the required APIs on your new project: https://console.cloud.google.com/flows/enableapi?apiid=cloudasset.googleapis.com,iam.googleapis.com,cloudresourcemanager.googleapis.com,iamcredentials.googleapis.com,sts.googleapis.com&redirect=https://console.cloud.google.com
-
Create a new Terraform root module with the following module:
module "common-fate-gcp-roles" {
source = "common-fate/common-fate-deployment/aws//modules/gcp-integration/workload-identity-roles"
version = "1.38.0"
gcp_project = "<ID of the GCP project you created above, excluding the '/project' prefix>"
common_fate_aws_account_id = "<Common Fate AWS Account ID>"
gcp_organization_id = "<Your GCP organization ID>"
common_fate_aws_reader_role_name = "common-fate-prod-control-plane-ecs-tr"
common_fate_aws_provisioner_role_name = "common-fate-prod-provisioner-ecs-tr"
}
If you’ve customised the names of your reader and provisioner roles from our defaults, you’ll need to update the common_fate_aws_reader_role_name
and common_fate_aws_provisioner_role_name
above.
Configuring Common Fate
In this section, you will register the GCP integration with your Common Fate deployment. At the end of this section you should have Common Fate reading GCP resources and see them inside of the web dashboard. You’ll need to have set up the Common Fate Application Configuration repository using our Terraform provider.
Obtain your GCP organization ID (it should look like organizations/12312324167
). Obtain your Google Workspace Customer ID (it should look like C02abcde123
).
You can find your Google Workspace Customer ID in the Google Admin console (https://admin.google.com). Log in using the same email as used in GCP. You’ll find the customer ID under >Account >Account settings.
Inside your Application Configuration repository, add the following module:
resource "commonfate_gcp_integration" "main" {
name = "GCP"
organization_id = "<Your GCP organization ID, including the 'organizations/' prefix>"
google_workspace_customer_id = "<Your Google Workspace Customer ID>"
reader_workload_identity_config = jsonencode(<your reader Workload Identity Config>)
}
Apply the changes. If the apply succeeds, you should see the integration appear on the settings page in the web dashboard, and GCP resources should populate within 10 minutes.
If after 10 minutes you do not see resources appear, check the logs of the common-fate-prod-control-plane
service in ECS. You can search for gcp
to filter for structured logs containing data about the GCP integration.
Provisioning access to GCP
To make GCP projects available for Just-In-Time (JIT) access you can add a commonfate_gcp_project_selector
Selector resource to your Common Fate application Terraform code. As shown below, the when
clause in the resource is a Cedar expression. You can use any Cedar operator in the when
clause, such as &&
and ||
to combine conditions.
You’ll need to use the commonfate_gcp_project_selector
in conjunction with a commonfate_gcp_project_availabilities
and commonfate_access_workflow
resources.
We’ve included some examples below.
Select a project by ID
resource "commonfate_gcp_project_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource == GCP::Project::"replace-this-with-your-project-id"
EOT
}
Select multiple projects by ID
resource "commonfate_gcp_project_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource == GCP::Project::"replace-this-with-your-project-id" || resource == GCP::Project::"some-other-project-id"
EOT
}
Select projects based on a naming pattern
Select projects with a name ending in -prod
:
resource "commonfate_gcp_project_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource.name like "*-prod"
EOT
}
Select projects with a name beginning with develop
:
resource "commonfate_gcp_project_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource.name like "develop*"
EOT
}
Select projects belonging to a particular folder
resource "commonfate_gcp_project_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource in GCP::Folder::"folders/1234567890"
EOT
}
Select projects belonging to a particular tag key
resource "commonfate_gcp_project_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource in GCP::TagKey::"tagKeys/1234567890123"
EOT
}
Select projects belonging to a particular tag value
resource "commonfate_gcp_project_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource in GCP::TagValue::"tagValues/1234567890123"
EOT
}
GCP folder selectors
To make GCP folders available for Just-In-Time (JIT) access you can add a commonfate_gcp_folder_selector
Selector resource to your Common Fate application Terraform code. As shown below, the when
clause in the resource is a Cedar expression. You can use any Cedar operator in the when
clause, such as &&
and ||
to combine conditions.
You’ll need to use the commonfate_gcp_folder_selector
in conjunction with a commonfate_gcp_folder_availabilities
and commonfate_access_workflow
resources:
// the selector resource chooses which targets
resource "commonfate_gcp_folder_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource == GCP::Folder::"replace-this-with-your-folder-id"
EOT
}
// the availability resource binds the targets to an Access Workflow
// with a particular role.
resource "commonfate_gcp_folder_availabilities" "demo" {
workflow_id = commonfate_access_workflow.demo.id
gcp_folder_selector_id = commonfate_gcp_folder_selector.example.id
gcp_role = "roles/resourcemanager.folderAdmin"
google_workspace_customer_id = "<Your Google Customer ID>"
}
We’ve included some examples below.
Select a folder by ID
resource "commonfate_gcp_folder_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource == GCP::Folder::"replace-this-with-your-folder-id"
EOT
}
Select multiple folders by ID
resource "commonfate_gcp_folder_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource == GCP::Folder::"replace-this-with-your-folder-id" || resource == GCP::Folder::"some-other-folder-id"
EOT
}
Select folders based on a naming pattern
Select folders with a name ending in -prod
:
resource "commonfate_gcp_folder_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource.name like "*-prod"
EOT
}
Select folders with a name beginning with develop
:
resource "commonfate_gcp_folder_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource.name like "develop*"
EOT
}
Select folders belonging to a particular folder
resource "commonfate_gcp_folder_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
when = <<EOT
resource in GCP::Folder::"folders/1234567890"
EOT
}
Organization-level access
Common Fate optionally supports provisioning just-in-time organization-level access to GCP. To provision access, the Common Fate provisioner role needs the following additional permissions:
- resourcemanager.organizations.getIamPolicy
- resourcemanager.organizations.setIamPolicy
If you used our reference integration Terraform module to deploy the GCP roles, you can add these permissions by providing the permit_organization_provisioning
variable:
module "common-fate-gcp-roles" {
source = "common-fate/common-fate-deployment/aws//modules/gcp-integration/workload-identity-roles"
version = "1.38.0"
gcp_project = "<ID of the GCP project you created above, excluding the '/project' prefix>"
common_fate_aws_account_id = "<Common Fate AWS Account ID>"
gcp_organization_id = "<Your GCP organization ID>"
common_fate_aws_reader_role_name = "common-fate-prod-control-plane-ecs-tr"
common_fate_aws_provisioner_role_name = "common-fate-prod-provisioner-ecs-tr"
+ permit_organization_provisioning = true
}
To make organization roles available for Just-In-Time (JIT) access you can add a commonfate_gcp_organization_selector
Selector resource to your Common Fate application Terraform code.
You’ll need to use the commonfate_gcp_folder_selector
in conjunction with a commonfate_gcp_folder_availabilities
and commonfate_access_workflow
resources:
// the selector resource chooses which targets
resource "commonfate_gcp_organization_selector" "example" {
id = "example"
name = "Example"
gcp_organization_id = = "<Your GCP Organization ID>"
}
// the availability resource binds the targets to an Access Workflow
// with a particular role.
resource "commonfate_gcp_organization_availabilities" "demo" {
workflow_id = commonfate_access_workflow.demo.id
gcp_organization_selector_id = commonfate_gcp_folder_selector.example.id
gcp_role = "roles/editor"
google_workspace_customer_id = "<Your Google Customer ID>"
}
You’ll additionally need to add the following Provisioner registration inside your Application Configuration repository:
resource "commonfate_webhook_provisioner" "prod" {
url = "http://common-fate-prod-builtin-provisioner.common-fate-prod-builtin.internal:9999"
capabilities = [
{
target_type = "GCP::Organization"
role_type = "GCP::Role"
belonging_to = {
type = "GCP::Organization"
id = "organizations/123456789123"
}
},
]
}
GCP Role Group access
Common Fate allows you to streamline permissions across multiple GCP roles by defining role groups. Role groups enable you to bundle multiple predefined roles, such as folder admin
and owner
, into a single entity. Users can then request access to these role groups, for GCP projects or folders.
To define a role group, use the commonfate_gcp_role_group
resource:
resource "commonfate_gcp_role_group" "example" {
name = "example"
gcp_organization_id = "<Your GCP organization ID>"
role_ids = ["roles/editor", "roles/owner"]
}
To make a GCP role group available for Just-In-Time (JIT) access, you can add a commonfate_gcp_role_group_folder_availabilities
or commonfate_gcp_role_group_project_availabilities
Availability resource to your Common Fate application Terraform code:
resource "commonfate_gcp_role_group_folder_availabilities" "gcp-role-group-folder" {
workflow_id = commonfate_access_workflow.demo.id
gcp_role_group = commonfate_gcp_role_group.example.id
gcp_folder_selector_id = commonfate_gcp_folder_selector.demo.id
google_workspace_customer_id = "<Your Google Customer ID>"
}
resource "commonfate_gcp_role_group_project_availabilities" "gcp-role-group-project" {
workflow_id = commonfate_access_workflow.demo.id
gcp_role_group = commonfate_gcp_role_group.example.id
gcp_project_selector_id = commonfate_gcp_project_selector.demo.id
google_workspace_customer_id = "<Your Google Customer ID>"
}
You’ll additionally need to add the following Provisioner registration inside your Application Configuration repository:
resource "commonfate_webhook_provisioner" "prod" {
url = "http://common-fate-prod-builtin-provisioner.common-fate-prod-builtin.internal:9999"
capabilities = [
{
target_type = "GCP::Project"
role_type = "GCP::RoleGroup"
belonging_to = {
type = "GCP::Organization"
id = "organizations/123456789123"
}
},
{
target_type = "GCP::Folder"
role_type = "GCP::RoleGroup"
belonging_to = {
type = "GCP::Organization"
id = "organizations/123456789123"
}
},
]
}