iTranslated by AI
Authenticating with Google Cloud from CircleCI using OIDC
Overview
Today, I'll be introducing a study on how to authenticate to Google Cloud using the recently announced OIDC support in CircleCI.
Goal
The goal is to authenticate to Google Cloud using a Google Service Account (hereafter GSA) while restricting which CircleCI projects can impersonate that GSA.
How to
Let's start creating the necessary resources.
Create Workload Identity Pool / Provider
First, we will create a Pool and a Provider to use Workload Identity Federation, which is the service for authenticating to Google Cloud via OIDC.
For the creation, we will set the CircleCI Organization ID in local.circleci_org.
locals {
circleci_org = "****"
}
resource "google_iam_workload_identity_pool" "circleci" {
provider = google-beta
workload_identity_pool_id = "circleci"
display_name = "circleci"
}
resource "google_iam_workload_identity_pool_provider" "circleci" {
provider = google-beta
workload_identity_pool_id = google_iam_workload_identity_pool.circleci.workload_identity_pool_id
workload_identity_pool_provider_id = "circleci"
display_name = "circleci"
attribute_mapping = {
"attribute.project_id" = "assertion['oidc.circleci.com/project-id']" # Mapping to restrict CircleCI projects.
"google.subject" = "assertion.sub"
}
oidc {
issuer_uri = "https://oidc.circleci.com/org/${local.circleci_org}" # Issuer URL is issued for each CircleCI Organization.
allowed_audiences = [local.circleci_org]
}
}
Create GSA
Create a GSA and specify the Workload Identity Pool created earlier and the mapped CircleCI Project ID as the member allowed to impersonate it.
The attribute.project_id/*** part restricts the CircleCI project.
Then, use google_project_iam_member to grant the necessary permissions to the corresponding GSA.
locals {
gsa_name = "***"
}
resource "google_service_account" "default" {
account_id = local.gsa_name
display_name = local.gsa_name
}
resource "google_service_account_iam_member" "default" {
for_each = toset([
"principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.circleci.name}/attribute.project_id/<CircleCI Project ID>",
])
service_account_id = google_service_account.default.id
role = "roles/iam.workloadIdentityUser"
member = each.value
}
resource "google_project_iam_member" "default" {
for_each = toset([
"roles/editor", # Grant the permissions you want to operate
])
project = var.project
role = each.value
member = "serviceAccount:${google_service_account.default.email}"
}
Create CircleCI Context
Create a context from Organization Settings → Contexts in CircleCI.
Edit CircleCI Config
I have created a CircleCI Orb that consolidates the steps for performing OIDC authentication from CircleCI to GCP, so we will use it.
Configure the above Orb in the orbs section
of the CircleCI configuration file (.circleci/config.yaml). Also, add the following steps to jobs.*.steps.
In the step, call the initialize command of the Orb and pass the parameters required for OIDC authentication. The initialize command handles the installation of the gcloud CLI and the setup of GOOGLE_APPLICATION_CREDENTIALS. Therefore, after executing the step, you can perform operations on the target GCP project simply by running gcloud commands.
Finally, by specifying the Context in the workflows section of .circleci/config.yaml for the job where you want to use OIDC, all configurations will be complete. Specifying the Context allows the CIRCLECI_TOKEN environment variable required for OIDC authentication to be used within the CI.
Finally
Since there weren't many documents or articles yet about authenticating to Google Cloud using CircleCI's OIDC tokens, I had to go through some trial and error. I hope this helps someone in a similar situation.
Also, since this method might not be the best practice, if you know of a simpler way, please feel free to leave a comment or reach out to me on Twitter!
Personally, I wanted to handle the authentication nicely using Orbs, but I couldn't get it to work properly...
Others
Regarding the CircleCI OIDC support introduced today, Classmethod has published a detailed article on how to use it with AWS, so please be sure to check that out as well.
Discussion