When a GitHub Actions workflow needs to read or mutate resources on Google Cloud it must first authenticate to the platform. Traditionally this is used by storing a long-lived JSON service account key in the GitHub repository secrets.
Not only does this cause a security risk for leaking this key, but it might also be that the creation of this key is blocked by your organization’s policy.
By using Terraform, we can create a workload identity pool that GitHub can use to authenticate workflows. The following example only works when you already have a way to authenticate to your Google Cloud project when running Terraform.
If GitHub Actions is responsible for the creation of your Terraform resources I advise you to create a temporary service account and grab the JSON key to put in your action. Once the Workload Identity pool has been created you can switch to using workload identity federation instead of the JSON key. Don’t forget to delete the service account key after switching.
This first block creates the workload identity pool and provider. Don’t forget to change your project_id
and repo
in the locals.
locals {
project_id = "my-google-project"
organization = "my-github-organization"
repo = "my-github-repository"
}
resource "google_iam_workload_identity_pool" "github_pool" {
project = local.project_id
workload_identity_pool_id = "github-pool"
display_name = "GitHub pool"
description = "Identity pool for GitHub deployments"
}
resource "google_iam_workload_identity_pool_provider" "github" {
project = local.project_id
workload_identity_pool_id = google_iam_workload_identity_pool.github_pool.workload_identity_pool_id
workload_identity_pool_provider_id = "github-provider"
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.actor" = "assertion.actor"
"attribute.aud" = "assertion.aud"
"attribute.repository" = "assertion.repository"
}
attribute_condition = "assertion.repository_owner==\"${local.organization}\""
oidc {
issuer_uri = "https://token.actions.githubusercontent.com"
}
}
The second section creates the service account that will be used by GitHub Actions workflows and grants the workload identity pool access to use the service account:
resource "google_service_account" "github_actions" {
project = local.project_id
account_id = "github-actions"
display_name = "Service Account used for GitHub Actions"
}
resource "google_service_account_iam_member" "workload_identity_user" {
service_account_id = google_service_account.github_actions.name
role = "roles/iam.workloadIdentityUser"
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github_pool.name}/attribute.repository/${local.organization}/${local.repo}"
}
The following two outputs can be used in your GitHub Actions workflow file:
output "workload_identity_provider" {
value = "${google_iam_workload_identity_pool.github_pool.name}/providers/${google_iam_workload_identity_pool_provider.github.workload_identity_pool_provider_id}"
}
output "service_account" {
value = google_service_account.github_actions.email
}
When you run a terraform apply
you can use these outputs in your GitHub Actions workflow file. Don’t forget to grant the newly created service account (google_service_account.github_actions
) any desired roles.
name: GitHub Actions Workload Identity Demo
on: [push]
jobs:
List-Buckets:
permissions:
contents: "read"
id-token: "write"
runs-on: ubuntu-latest
steps:
- uses: "actions/checkout@v3"
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v0"
with:
workload_identity_provider: <workload_identity_provider>
service_account: <service_account>
- name: "Set up Cloud SDK"
uses: "google-github-actions/setup-gcloud@v0"
- name: "List buckets"
run: "gcloud storage ls"
Conclusion
You have learned how to set up workload identity federation for GitHub Actions. You can now securely authenticate your GitHub Actions to your Google Cloud projects without having to deal with service account keys.