iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🚡

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.

https://twitter.com/CircleCIJapan/status/1507524861396422657?s=20&t=p2gpua2mHzXZxrEKDd6GgA

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.

https://circleci.com/developer/orbs/orb/tetsuya28/gcp-oidc-orb

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.

https://dev.classmethod.jp/articles/circleci-supported-oidc-so-i-tried-linking-it-with-aws/

Discussion