Github OpenID Connect¶
Overview¶
OpenID Connect (OIDC) enables GitHub Actions workflows to access Google Cloud Platform (GCP) resources without storing long-lived GCP credentials as GitHub secrets. This approach enhances security by eliminating the need for persistent credential storage.
- This guide provides:
End-to-end configuration of GitHub Actions OpenID Connect authentication with GCP using Workload Identity Federation.
Terraform Plan and Apply workflow to deploy Google Cloud Infrastructure.
GitHub Actions Workload Identity Federation Authentication¶
This guide uses the google-github-actions/auth GitHub action to handle OIDC authentication with GCP.
For each GitHub Actions job, an OIDC token is requested from GitHub’s OIDC provider. The provider responds with an automatically generated JSON Web Token (JWT). This JWT is unique for each GitHub Workflow job execution and contains claims about the job’s identity and context.
Google GitHub Actions¶
google-github-actions/auth provides 3 methods to authenticate with Google Cloud using Workload Identity Federation:
Workload Identity Federation Direct
Workload Identity Federation Service Account
Service Account Key JSON
Workload Identity Federation Direct is the recommended approach for this guide. It provides direct authentication of the GitHub workflow job to GCP without an intermediate service account. The google-github-actions/auth action uses the GitHub OIDC token to authenticate as the workload identity associated with the GitHub repository.
Workload Identity Federation Service Account is similar to the direct method but introduces an intermediate GCP service account. In this approach, the GitHub workflow impersonates the intermediate service account, which has been granted the necessary permissions on GCP resources. While this method adds an extra authentication step, it offers no significant advantages over direct authentication.
Service Account Key JSON uses a JSON private key file downloaded from GCP instead of GitHub’s OIDC token. This method eliminates the need to configure Workload Identity Federation. However, it is less secure because it requires storing long-lived credentials as GitHub secrets.
The difference between Workload Identity Federation Direct and Workload Identity Federation Service Account is illustrated in the following diagrams:
This guide focuses on the Workload Identity Federation Direct authentication method.
Workload Identity Federation Direct Setup¶
Source Code
Define Terraform Locals Variables
locals {
github_owner_id = "'59314971'" # Replace with GitHub `repository_owner_id`
github_repository = "kborovik/google-infra" # Replace with GitHub `repository_name`
}
Create GCP Workload Identity Pool
resource "google_iam_workload_identity_pool" "github" {
workload_identity_pool_id = "github"
display_name = "GitHub OIDC"
lifecycle {
prevent_destroy = true
}
}
Create GCP Workload Identity Pool Provider
When a GitHub Actions job runs, it presents an OIDC token to the Google Cloud OIDC provider for authentication. The Google Cloud provider validates this token by checking:
The token was issued by the trusted GitHub OIDC provider
The token’s
assertion.repository
claim matches the GitHub repository nameThe
assertion.repository_owner_id
claim in the attribute condition matches the GitHub repository owner ID
Warning
Security Warning
GitHub Actions OIDC tokens may contain claims that are not unique across different organizations or repositories. This lack of uniqueness could potentially allow tokens from other sources to establish an identity. To mitigate this risk, always use an attribute_condition
to restrict access to tokens issued by your specific GitHub organization.
Use a unique identifier for your organization, such as the repository_owner_id
, instead of relying solely on the repository name or other potentially non-unique values.
For more information on configuring OIDC trust definitions, see GitHub OIDC Token.
resource "google_iam_workload_identity_pool_provider" "github" {
workload_identity_pool_provider_id = "google-infra"
display_name = "GitHub Repo google-infra"
workload_identity_pool_id = google_iam_workload_identity_pool.github.workload_identity_pool_id
attribute_mapping = {
"attribute.repository" = "assertion.repository"
"google.subject" = "assertion.sub"
}
attribute_condition = "assertion.repository_owner_id == ${local.github_owner_id}"
oidc {
issuer_uri = "https://token.actions.githubusercontent.com"
}
lifecycle {
prevent_destroy = true
}
}
Grant IAM Permissions to Workload Identity
locals {
github_aim_roles = [
"roles/editor",
"roles/iam.securityAdmin",
]
}
resource "google_project_iam_member" "github_principal_set" {
count = length(local.github_aim_roles)
project = var.google_project
role = local.github_aim_roles[count.index]
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github.name}/attribute.repository/${local.github_repository}"
}
GitHub Actions Workflow¶
Source Code
Retrieve the complete identifier for the Workload Identity Pool
(0) > gcloud iam workload-identity-pools list \
--location=global
---
displayName: GitHub OIDC
name: projects/320561780581/locations/global/workloadIdentityPools/github
state: ACTIVE
(0) > gcloud iam workload-identity-pools providers list \
--location=global \
--workload-identity-pool=github
---
attributeCondition: assertion.repository_owner_id == '59314971'
attributeMapping:
attribute.repository: assertion.repository
google.subject: assertion.sub
displayName: GitHub Repo google-infra
name: projects/320561780581/locations/global/workloadIdentityPools/github/providers/google-infra
oidc:
issuerUri: https://token.actions.githubusercontent.com
state: ACTIVE
Configure Workload Identity Provider in GitHub Actions Workflow
After retrieving the Workload Identity Provider ID, incorporate it into your GitHub Actions workflow. This step is crucial for establishing the connection between your GitHub repository and Google Cloud Platform.
Use
google_project
value as theproject_id
valueUse
projects/320561780581/locations/global/workloadIdentityPools/github/providers/google-infra
value as theworkload_identity_provider
value
name: lab5-gcp-dev1
run-name: lab5-gcp-dev1
env:
google_project: lab5-gcp-dev1
workload_identity_provider: projects/320561780581/locations/global/workloadIdentityPools/github/providers/google-infra
jobs:
terraform-plan:
runs-on: ubuntu-latest
steps:
- id: checkout
name: Code Checkout
uses: actions/checkout@v4
- id: auth
name: Google Cloud Authentication
uses: google-github-actions/auth@v2
with:
project_id: ${{ env.google_project }}
workload_identity_provider: ${{ env.workload_identity_provider }}
Run GitHub Pipeline