Configuring GCP Workload Identity Federation for Bitbucket Pipelines

Alexander Rodriguez
Google Cloud - Community
6 min readJan 17, 2024

written in collaboration with BJ Bloemker

Workload Identity Federation allows Bitbucket Pipelines to authenticate to GCP without Service Account keys

Workload Identity Federation can be used to grant workloads outside of Google Cloud access to cloud resources, without using a Service Account key. This allows organizations to securely access their Google Cloud resources without the inherent risks surrounding Service Account key storage. This blog will demonstrate how to configure a secure Workload Identity Federation connection to Bitbucket Pipelines.

Prerequisites

  • Existing Bitbucket workspace and repository
  • Google Cloud account
  • Terraform
  • Google Cloud Storage Bucket to store the Terraform state
  • Google Cloud user/Service Account with access to the Terraform state bucket and the following IAM permissions:
  • Project Creator
  • Service Usage Consumer

Instructions

1. Working Environment Setup

For our examples, we will be using Cloud Shell for our working environment which includes Terraform. We will begin by setting up our Bitbucket environment with the required setup Workload Identity Federation.

Start by navigating to a working directory and cloning the gcp-wif-bucket repo from GitHub.

git clone https://github.com/GoogleCloudPlatform/gcp-bitbucket-wif.git

This repository contains the Terraform code required to support a Workload Identity Federation connection to Bitbucket.

  • GCP Project to host WIF resources
  • Workload Identity Federation Pool
  • Workload Identity Federation Provider
  • Service Account that is connected to the Workload Identity Federation Provider
  • An example Bitbucket directory that includes a pipeline to test WIF and deploy a GCS bucket (optional)
  • Enables the required APIs on the GCP project:
    - Cloud Resource Manager API — cloudresourcemanager.googleapis.com
    - Cloud Billing API — cloudbilling.googleapis.com
    - Identity and Access Management API — iam.googleapis.com
    - Admin SDK — admin.googleapis.com

2. Variable Configuration

Before executing this Terraform code, we need to correctly configure the variable inputs in terraform.tfvars.

bitbucket_workspace

This value is the name of your workspace. Provide the appropriate name of the workspace that contains the repository and pipeline that will be deploying to GCP. The Bitbucket workspaces you have access to can be found here.

allowed_audiences

This parameter defines which client repositories are allowed to receive and use the ID token issued by Google Cloud. This value can be found by navigating to the your “Repository Settings” page and looking in the “OpenID Connect Settings”

sa-roles

This Terraform variable allows you to instantiate additional roles attached to the Service Account that is linked to the Workload Identity Provider. This Service Account will need permissions to deploy all the GCP resources that you intend to create, as this account will serve as the identity that Terraform assumes.

For this example, we will give the Service Account `roles/storage.admin` so our Bitbucket pipeline can deploy a sample GCS Bucket to test the connection. Adjust this list based on your use case for WIF.

org_id

The Organization ID for your GCP environment. This value can be found within Resource Manager inside the Google Cloud Console.

parent

This variable specifies the parent organization or folder where the WIF created project should be created. If the project will reside at the base level of an organization this would be the organization ID (ex: organizations/123456789012). If the project will reside in a folder this would be the folder ID (ex: folders/9876543210)

billing_account

This value should be populated with your Organization’s Billing ID. This information can be found in the Billing section of the Google Cloud Console.

project_name

The project name for the created WIF project. The Terraform code will append 4 random digits to the end of project_name for uniqueness.

backend_bucket_name

This Terraform code will also deploy a GCS Bucket that can be used to hold the state files for your Bitbucket pipelines. The name of the Google Cloud Storage Bucket that will be used as a Terraform backend for the Bitbucket pipelines.

Example terraform.tfvars:

org_id = "123456789012"
parent = "folders/123456789012"
billing_account = "00AA11-BB22CC-DD33EE"
bitbucket_workspace = "myworkspace"
allowed_audiences = ["ari:cloud:bitbucket::workspace/12345678–90ab-cdef-1234"]
project_name = "my-project"
backend_bucket_name = "my-backend-bucket"
sa_roles = [
"roles/storage.admin",
]

3. Execute Terraform

The GitHub package includes the Terraform required to deploy these resources, however this code must be deployed directly from the Cloud Shell console. Deploy the Terraform using the following commands inside the root of the cloned repo:

  1. terraform init — Initializes the Terraform environment, installs necessary providers, and prepares the configuration.
  2. terraform plan — Shows a preview of the changes that Terraform will make to your infrastructure according to the configuration.
  3. terraform apply — Applies the changes to your infrastructure based on the configuration and the plan.

After applying your Terraform configuration, remember to note down the following output values, which will be displayed in the Cloud Shell terminal where you ran the terraform apply:

  • Project Name (project_name)
  • State Bucket (state_bucket)
  • WIF Provider ID for Bitbucket (wif_provider_id_bitbucket)
  • Service Account Principal (service_account_principle)

4. Configuring Bitbucket Workspace

We have now successfully configured Workload Identity Federation in Google Cloud and we’re ready to configure our Bitbucket Workspace to use the Workload Identity Provider.

Enable Pipelines in Your Bitbucket Repository

  1. Create Bitbucket repository
  2. Navigate to a Repository Settings.
  3. Go to Pipelines > Settings.
  4. Enable the “Pipelines” feature.

Set Up Required Environment Variables

  1. In your repository, navigate to Repository Settings.
  2. Go to Pipelines > Repository variables.
  3. Add the following environment variables using the Terraform outputs from the previous step:
    - STATE_BUCKET: The Google Cloud Storage bucket for storing your Terraform state files
    - GCP_WORKLOAD_IDENTITY_PROVIDER: Enter your Google Cloud Workload Identity Provider
    - GCP_SERVICE_ACCOUNT: Provide the email address of your Google Cloud Service Account
    - PROJECT_NAME: Include your Google Cloud project ID
    - TERRAFORM_VERSION: (Not an explicit output of github package, set this value to desired Terraform version ex: 1.4.2)

5. Authenticate Securely Using Workload Identity Federation from Bitbucket

The repository is now set up and ready to connect to GCP using the Workload Identity Federation. We will need to create a sample Bitbucket pipeline to test our work. A sample directory named Bitbucket can be found inside the GitHub repo with an example deployment. Copy the files of this directory into your Bitbucket repository.

The Bitbucket pipeline must be able to use gcloud and terraform commands. This pipeline will first download and install these binaries (alternatively this could be prebaked into a pipeline image). Next, the pipeline will execute a predefined shell script that uses the repository variables to authenticate to GCP using gcloud commands.

The included example pipeline does not need to be modified so long as the repository variables have been set.

Deploying Terraform Code

Add the Terraform Code you would like the Workload Identity Service Account to securely deploy from your Bitbucket Repository. In the gcp-bitbucket-wif example we deploy a simple GCS bucket.

The Service Account specified in the initial terraform will need to have the proper permissions to deploy all the resources you intend to deploy through the Workload Identity provider. If the Service Account is lacking a certain permission, add it to the sa_roles variable in terraform.tfvars from the previous steps and rerun terraform apply.

Run the Bitbucket Pipeline

The pipeline can now be triggered. Our example will do this on a commit to the main branch but the pipeline can also be triggered manually. Our pipeline is successful!

Summary

In this blog, we saw how a Bitbucket can be attached to a Workload Identity Federation provider in order to authenticate with Google Cloud resources. Workload Identity Federation in GCP facilitates secure, keyless authentication to GCP Service Accounts. By leveraging external identity providers, like Bitbucket, it enables applications to authenticate directly without the need for managing Service Account keys, significantly enhancing security and simplifying credential management.

--

--