How to Setup Google Workload Identity Federation for Github Actions Runners


When using GHA(Github Actions) for CI/CD purposes, the Github-hosted runners are free unless you use it quite a lot. But if I want to use GHA to build a docker container image and save it to my private repository in Google Artifact Registry, I have to grant the permission to some VMs I don’t even know where they are running from. So I would hesitate to load a JSON key of my Google service account to the runner VM.

Things are getting easier now, as the Workload Identity Federation is available for the use case. I followed this blog and got my setup working quickly, then I discovered it’s even quicker to do it with an existing terraform module:

service_accounts:
  github-runner:
    roles:
      - roles/artifactregistry.writer
    wif: {}
locals {
  workload_identity_pool = {
    for k, v in local.manifest.service_accounts : k => {
      sa_name   = "projects/${var.project}/serviceAccounts/${k}@${var.project}.iam.gserviceaccount.com"
      attribute = try(v.wif.attribute, "*")
    }
    if can(v.wif)
  }
}

module "gh_oidc" {
  source = "terraform-google-modules/github-actions-runners/google//modules/gh-oidc"
  count  = length(local.workload_identity_pool) > 0 ? 1 : 0

  project_id  = var.project
  pool_id     = "github-wif-pool"
  provider_id = "github-wif-pool-provider"
  sa_mapping  = local.workload_identity_pool
}

# the provider name will be needed in GHA workflow
output "wif_provider_name" {
  value = try(module.gh_oidc[0].provider_name, "N/a")
}

Then in the GHA workflow, only a few additional lines are needed to use this new authentication provider

name: My CI

on:
  workflow_dispatch:
  push:
    branches:
      - 'master'
jobs:
  build-docker:
    permissions:
      contents: 'read'
      id-token: 'write' # this is needed to write a new token
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      # this must be after checkout
      - id: 'auth'
        name: 'Authenticate to Google Cloud'
        uses: 'google-github-actions/auth@v1'
        with:
          workload_identity_provider: '<the provider name from the output of the terraform code above>'
          service_account: '[email protected]'
          token_format: access_token
      - name: Login to GCR
        uses: docker/login-action@v3
        with:
          registry: asia.gcr.io
          username: oauth2accesstoken
          password: ${{ steps.auth.outputs.access_token }}
      # it's authenticated from now on, so do whatever docker build and push stuff that are needed.

I like this keyless approach 🙂