GitHub Actions + GCP Authentication without Secrets
Workload Identity Federation lets GitHub Actions authenticate with Google Cloud without storing service account keys. Instead, GitHub's OpenID Connect (OIDC) token is exchanged for a short-lived GCP access token. This way, there is no secrets to rotate, as tokens are short-lived and generated on demand
The following placeholders are used in the commands below:
| Placeholder | Description |
|---|---|
PROJECT_ID | GCP project ID (e.g. playground-12345) |
PROJECT_NUMBER | GCP project number (e.g. 123456789012) obtained from step 1 |
GITHUB_ORG | GitHub organization or user name |
GITHUB_REPO | GitHub repository name |
Obtain the project number:
gcloud projects describe PROJECT_ID --format="value(projectNumber)"Create a Workload Identity Pool
gcloud iam workload-identity-pools create "github" \ --project="PROJECT_ID" \ --location="global" \ --display-name="GitHub Actions Pool"Create a Workload Identity Provider
gcloud iam workload-identity-pools providers create-oidc "my-repo" \ --project="PROJECT_ID" \ --location="global" \ --workload-identity-pool="github" \ --display-name="GitHub Actions Provider" \ --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \ --attribute-condition="assertion.repository_owner == 'GITHUB_ORG'" \ --issuer-uri="https://token.actions.githubusercontent.com"The
--attribute-conditionrestricts access to the specified GitHub org/user. With these attribute mappings, you can use them as a principal identifier when granting access to GCP resources.For example, to only allow a specific repository (
GITHUB_ORG/GITHUB_REPO) to access a GCP resource, you can grant access to the principal identifier:principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github/attribute.repository/GITHUB_ORG/GITHUB_REPOgcloud iam service-accounts create "SERVICE_ACCOUNT_NAME" \ --project="PROJECT_ID" \ --display-name="GitHub Actions - my-repo"Grant Permissions to the Service Account
gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/bigquery.dataEditor" \ --condition=NoneAllow GitHub to Impersonate the Service Account
gcloud iam service-accounts add-iam-policy-binding \ "SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com" \ --project="PROJECT_ID" \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github/attribute.repository/GITHUB_ORG/GITHUB_REPO"Enable the IAM Credentials API
gcloud services enable iamcredentials.googleapis.com --project=PROJECT_IDjobs: my-job: runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - uses: actions/checkout@v4 - uses: google-github-actions/auth@v2 with: workload_identity_provider: projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github/providers/my-repo service_account: SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com # Now authenticated with GCPThe
id-token: writepermission is required for the OIDC token exchange.