GCP: Enabling keyless authentication from GitHub Actions

Mahendran
5 min readMar 3, 2024

--

Introduction

Workload Identity Federation (WIF) is a pivotal method for utilizing an external authentication system to authorize access to Google Cloud Platform (GCP) resources such as AWS, Azure, GitHub or with any identity provider (IdP) that supports OpenID Connect (OIDC).

In the context of GitHub Actions, it involves leveraging GitHub’s OpenID Connect (OIDC) system to issue a JWT token with predefined claims. This token serves as a temporary credential for accessing GCP resources throughout a job.

Keyless Authentication for Service Accounts

One of the core aspects of WIF is its capability to provide keyless authentication for Service Accounts (SAs). Instead of relying on keys with expiration, SAs are assigned identifiers associated with specific applications, and then permissions are granted accordingly. This enhances security and simplifies the management of authentication mechanisms.

Prerequisite

Enable the IAM, Resource Manager, Service Account Credentials, and Security Token Service APIs.

  • Identity and Access Management (IAM) API
  • Cloud Resource Manager API
  • IAM Service Account Credentials API
  • Security Token Service API

Setup Project

gcloud config set account <Service-Account>@<project-id>.iam.gserviceaccount.com
gcloud config set project <project-id>
gcloud auth login

Workload Identity Pool

A workload identity pool is an entity that lets you manage external identities.

1. Create a Workload Identity Pool

For instance, Pool id is dataproc-github-identity-pool

gcloud iam workload-identity-pools create dataproc-github-identity-pool \
--location="global" \
--display-name="Mahendran Workload Identity Pool" \
--description="Mahendran Workload Identity Pool" --disabled

You can set up mappings between JWT token claims and WIF custom attributes.

2. Create a Workload Identity Provider dataproc-github-idp and to the Pool dataproc-github-identity-pool

See Attribute Mapping and Conditions for attribute-mapping="MAPPINGS"

gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
--location="global" \
--workload-identity-pool="POOL_ID" \
--issuer-uri="https://token.actions.githubusercontent.com/" \
--attribute-mapping="MAPPINGS" \
--attribute-condition="CONDITIONS"

2.1 For example, Create a pool `dataproc-github-idp`

gcloud iam workload-identity-pools providers create-oidc dataproc-github-idp \
--location="global" \
--workload-identity-pool="dataproc-github-identity-pool" \
--display-name="GitHub workload pool provider" \
--description="Mahendran's github workload pool provider" \
--issuer-uri="https://token.actions.githubusercontent.com/" \
--attribute-mapping="google.subject=assertion.sub" \
--attribute-condition="attribute.owner==assertion.repository_owner" \
--project data-proc-poc

2.2 List the Pool created

gcloud iam workload-identity-pools providers list --workload-identity-pool="dataproc-github-identity-pool" --location="global" --show-deleted

2.3 Get the name

gcloud iam workload-identity-pools list --location global --format "get(name)"

3. Attribute Mapping and Conditions

Attribute mapping allows you to establish connections between JWT token claims and WIF custom attributes. By defining attribute conditions, you can refine access controls based on specific criteria. This ensures granular control over resource access within the GCP environment.

The tokens issued by your external identity provider contain one or more attributes. Some identity providers refer to these attributes as claims.

Google STS tokens also contain one or more attributes, as listed in the following table:

References:

  1. Example subject claims
  2. Filtering for a specific environment

You may set up mappings between JWT token claims and WIF custom attributes

Example OIDC Claims:

Refer Attribute Mapping and Conditions

google.subject=assertion.sub
attribute.repository==assertion.repository

3.2 Verification

Go To the GCloud console, and verify the Provider and the attributes

Verify the pool and the provider attached to the pool
Verify the Audience, And Attributes

Authenticate a workload

1. Create a service account for the external workload

Use an existing service account or create a new Service Account

1.1 Add roles to the Service Account

1.2 Principals vs PrincipalSet

Principals, which represent incoming requests to WIF, can be assigned roles based on various attributes and conditions. This enables fine-grained access control, enhancing security and compliance measures.

To grant the Workload Identity User role (roles/iam.workloadIdentityUser) to external identities that meet a certain criteria:

First lets look at a regular principal. A regular principle is the basic way of identifying an incoming request to WIF and essentially just uses the subject.

Choose one of the following or both

Add a Principal

gcloud iam service-accounts add-iam-policy-binding <service-account>@<project-id>.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="principal://iam.googleapis.com/projects/1334884267/locations/global/workloadIdentityPools/dataproc-github-identity-pool/subject/repo:mahen-github/iac-gcp:pull_request"

Add a Principal-set to the Service Account

Here, I’m adding attribute.repository/mahen-github/iac-gcp

gcloud iam service-accounts add-iam-policy-binding <service-account>@<project-id>.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="principalSet://iam.googleapis.com/projects/1334884267/locations/global/workloadIdentityPools/dataproc-github-identity-pool/attribute.repository/mahen-github/iac-gcp"

Add a Workflow to the github project

Refer the Project for example Workflow

The below workflow uses google-github-actions to authenticate and google-github-actions/upload-cloud-storage@v2 to upload a file from github

  build:
runs-on: ubuntu-latest
environment: dev # Fetches the env variables for dev
permissions:
contents: read
id-token: write
steps:
- name: Checkout actions-oidc-debugger
uses: actions/checkout@v3
- id: auth
name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
create_credentials_file: true
workload_identity_provider: '${{ vars.WORKLOAD_IDENTITY_PROVIDER }}'
service_account: '${{ secrets.SERVICE_ACCOUNT }}'
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2
- name: set credentials file
run: >-
gcloud auth login
--cred-file=${{steps.auth.outputs.credentials_file_path}}
- name: Use gcloud CLI
run: gcloud info
- id: upload-file
uses: google-github-actions/upload-cloud-storage@v2
with:
path: CHANGELOG.md
destination: '${{ vars.GCP_BUCKET }}'
process_gcloudignore: false

Conclusion

Workload Identity Federation, coupled with GitHub Actions integration, offers a robust solution for managing access to GCP resources securely. By leveraging OIDC providers, attribute mappings, and role assignments, organizations can establish streamlined authentication mechanisms while adhering to stringent security standards.

References

--

--

Mahendran
Mahendran

Written by Mahendran

A Software/Data Engineer, Photographer, Mentor, and Traveler

No responses yet