OpenID Connect
Workload Identity Federation through a Service Account
-
(Optional) Create a Google Cloud Service Account. If you already have a Service Account, take note of the email address and skip this step.
-
Create a Workload Identity Pool:
-
Get the full ID of the Workload Identity Pool:
gcloud iam workload-identity-pools describe "github" \ --project="${PROJECT_ID}" \ --location="global" \ --format="value(name)"
This value should be of the format:
-
Create a Workload Identity Provider in that pool:
gcloud iam workload-identity-pools providers create-oidc "my-repo" \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github" \ --display-name="My GitHub repo 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"
Warning
Using "name" fields in Attribute Conditions or IAM Bindings like repository and repository_owner increase the chances of cybersquatting and typosquatting attacks. If you delete your GitHub repository or GitHub organization, someone could claim that same name and establish an identity. To protect against this situation, use the numeric *_id fields instead, which GitHub guarantees to be unique and never re-used.
To get your numeric organization ID:
ORG="my-org" # TODO: replace with your org curl -sfL -H "Accept: application/json" "https://api.github.com/orgs/${ORG}" | jq .id
To get your numeric repository ID:
REPO="my-org/my-repo" # TODO: replace with your full repo including the org curl -sfL -H "Accept: application/json" "https://api.github.com/repos/${REPO}" | jq .id
These can be used in an Attribute Condition:
-
Allow authentications from the Workload Identity Pool to your Google Cloud Service Account.
gcloud iam service-accounts add-iam-policy-binding "my-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \ --project="${PROJECT_ID}" \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/${REPO}"
Note
${REPO}
is the full repo name including the parent GitHub organization, such asmy-org/my-repo
.Note
${WORKLOAD_IDENTITY_POOL_ID}
is the full pool id, such asprojects/123456789/locations/global/workloadIdentityPools/github
.Abstract
If you want to admit all repos in an organization, map on
attribute.repository_owner
(which will be the org name): -
Extract the Workload Identity Provider resource name:
gcloud iam workload-identity-pools providers describe "my-repo" \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github" \ --format="value(name)"
Use this value as the workload_identity_provider value in the GitHub Actions YAML:
-
As needed, grant the Google Cloud Service Account permissions to access Google Cloud resources. This step varies by use case. The following example shows granting access to a secret in Google Secret Manager.
References
- https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform
- https://cloud.google.com/iam/docs/workload-identity-federation-with-deployment-pipelines
- GitHub Action: Authenticate to Google Cloud
- https://github.com/google-github-actions/auth/issues/77