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: 'github-runner@my-gcp-project-name.iam.gserviceaccount.com'
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 🙂
