GitHub Actions is a third-party CI/CD solution popular among many Google Cloud customers and developers. When a GitHub Actions Workflow needs to read or mutate resources on Google Cloud – such as publishing a container to Artifact Registry or deploying a new service with Cloud Run – it must first authenticate.

Traditionally, authenticating from GitHub Actions to Google Cloud required exporting and storing a long-lived JSON service account key, turning an identity management problem into a secrets management problem. Not only did this introduce additional security risks if the service account key were to leak, but it also meant developers would be unable to authenticate from GitHub Actions to Google Cloud if their organization has disabled service account key creation (a common security best practice) via organization policy constraints like constraints/iam.disableServiceAccountKeyCreation.

But now, with GitHub’s introduction of OIDC tokens into GitHub Actions Workflows, you can authenticate from GitHub Actions to Google Cloud using Workload Identity Federation, removing the need to export a long-lived JSON service account key.

 

  • Fine-grained scoping. Workload Identity Pools and Providers can define fine-grained attribute mappings between the OIDC token and the available permissions in Google Cloud. Whereas a JSON service account key is either accessible or inaccessible, Workload Identity Federation can be configured to selectively allow authentication based on properties in the downstream OIDC tokens. For GitHub Actions, that means you can, for example, restrict authentication to certain repositories, usernames, branch names, or published claims. You can also combine and build more complex and compound constraints using CEL.
  • Short-lived credentials. Unlike JSON service account keys, Workload Identity Federation generates short-lived OAuth 2.0 or JWT credentials. By default, these credentials automatically expire one hour after they are created, potentially reducing the time a malicious actor would be able to exploit a compromised credential.
  • Minimal management overhead. JSON service account keys must be securely stored, rotated, and managed. Even at a small scale, this can be toilsome and prone to errors. Because Workload Identity Federation uses short-lived credentials, there are no secrets to rotate or manage beyond the initial configuration.

A new GitHub Action – auth!

To ease the process of authenticating and authorizing GitHub Actions Workflows to Google Cloud via Workload Identity Federation, we are introducing a new GitHub Action – auth! The auth action joins our growing collection of Google-managed GitHub Actions and makes it simple to set up and configure authentication to Google Cloud:

steps:
- id: 'auth'
  name: 'Authenticate to Google Cloud'
  uses: 'google-github-actions/[email protected]'
  with:
    workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
    service_account: '[email protected]'

 

This will use the configured workload_identity_provider and service_account to authenticate future steps. The gcloud command-line tool, official Google Cloud client libraries, and popular third-party tools like Terraform will automatically detect and use this authentication. Additionally, all the Google GitHub Actions support this authentication mechanism. For example, you can use the auth GitHub Action with the get-gke-credentials GitHub Action:

steps:
- id: auth
  uses: google-github-actions/[email protected]
  with:
    workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
    service_account: '[email protected]'

- id: get-gke-credentials
  uses: google-github-actions/[email protected]
  with:
    cluster_name: my-cluster
    location: us-central1-a

- id: get-pods
  run: kubectl get pods

 

If you are using third-party tools that do not support Application Default Credentials, or if you want to invoke Google Cloud APIs manually via curl, the auth GitHub Action can create OAuth 2.0 tokens and JWTs for use in future steps. The following example creates a short-lived OAuth 2.0 access token and then uses that token to access a secret from Google Secret Manager using curl:

 

steps:
- id: 'auth'
  name: 'Authenticate to Google Cloud'
  uses: 'google-github-actions/[email protected]'
  with:
    token_format: 'access_token'
    workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
    service_account: '[email protected]'

- name: 'Access secret'
  run: |-
    curl https://secretmanager.googleapis.com/v1/projects/my-project/secrets/my-secret/versions/1:access \
      --header "Authorization: Bearer ${{ steps.auth.outputs.access_token }}"

 

To ease in migration and to support legacy workflows, the auth GitHub Action also supports authenticating via a Google Cloud service account key JSON file:

 

steps:
- id: 'auth'
  name: 'Authenticate to Google Cloud'
  uses: `google-github-actions/[email protected]'
  with:
    credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}'

 

Learn more about the auth GitHub Action and check out the examples at google-github-actions/auth.

Setting up Identity Federation for GitHub Actions

To use the new GitHub Actions auth action, you need to set up and configure Workload Identity Federation by creating a Workload Identity Pool and Workload Identity Provider:

gcloud iam workload-identity-pools create "my-pool" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --display-name="Demo pool"

 

gcloud iam workload-identity-pools providers create-oidc "my-provider" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --workload-identity-pool="my-pool" \
  --display-name="Demo provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.aud=assertion.aud" \
  --issuer-uri="https://token.actions.githubusercontent.com"

 

The attribute mappings map claims in the GitHub Actions JWT to assertions you can make about the request (like the repository or GitHub username of the principal invoking the GitHub Action). These can be used to further restrict the authentication using --attribute-condition flags. For example, you can map the attribute repository value (which can be used later to restrict the authentication to specific repositories):

--attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository"

 

Finally, allow authentications from the Workload Identity Provider to impersonate the desired Service Account:

gcloud iam service-accounts add-iam-policy-binding "[email protected]${PROJECT_ID}.iam.gserviceaccount.com" \
  --project="${PROJECT_ID}" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/my-org/my-repo"

 

For more configuration options, see the Workload Identity Federation documentation. If you are using Terraform to automate your infrastructure provisioning, check out the GitHub OIDC Terraform module too.

Towards invisible security

At first, authenticating to Google Cloud from a GitHub Action without a long-lived JSON service account key might seem like magic, but it’s all part of Google Cloud’s ongoing efforts to make security invisible and our platform secure-by-default. Using Workload Identity Federation to replace long-lived JSON service account keys in GitHub Actions delivers  improvements in security and auditability.

To get started, check out the auth GitHub Action today!

 

By: Seth Vargo (Developer Advocate and Product Manager) and Bharath Baiju (Solutions Architect)
Source: Google Cloud Blog

Previous Ensuring Scale And Compliance Of Your Terraform Deployment With Cloud Build
Next AI For All Humans: A Course To Delight And Inspire!