Home

Awesome

Authenticate to Google Cloud from GitHub Actions

This GitHub Action authenticates to Google Cloud. It supports authentication via a Google Cloud Service Account Key JSON and authentication via Workload Identity Federation.

Workload Identity Federation is recommended over Service Account Keys as it obviates the need to export a long-lived credential and establishes a trust delegation relationship between a particular GitHub Actions workflow invocation and permissions on Google Cloud. There are three ways to set up this GitHub Action to authenticate to Google Cloud:

  1. (Preferred) Direct Workload Identity Federation
  2. Workload Identity Federation through a Service Account
  3. Service Account Key JSON

[!IMPORTANT] The gsutil command will not use the credentials exported by this GitHub Action. Customers should use gcloud storage instead.

This is not an officially supported Google product, and it is not covered by a Google Cloud support contract. To report bugs or request features in a Google Cloud product, please contact Google Cloud support.

Prerequisites

Usage

jobs:
  job_id:
    # Add "id-token" with the intended permissions.
    permissions:
      contents: 'read'
      id-token: 'write'

    steps:
    - uses: 'actions/checkout@v4'

    - uses: 'google-github-actions/auth@v2'
      with:
        project_id: 'my-project'
        workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'

[!NOTE]

Changing the permissions block may remove some default permissions. See the permissions documentation for more information.

For more usage options, see the examples.

Inputs

Inputs: Workload Identity Federation

[!WARNING]

This option is not supported by Firebase Admin SDK. Use Service Account Key JSON authentication instead.

The following inputs are for authenticating to Google Cloud via Workload Identity Federation.

Inputs: Service Account Key JSON

[!CAUTION]

Service Account Key JSON credentials are long-lived credentials and must be treated like a password.

The following inputs are for authenticating to Google Cloud via a Service Account Key JSON.

Inputs: Generating OAuth 2.0 access tokens

The following inputs are for generating OAuth 2.0 access tokens for authenticating to Google Cloud as an output for use in future steps in the workflow. These options only apply to access tokens generated by this action. By default, this action does not generate any tokens.

Inputs: Generating ID tokens

The following inputs are for generating ID tokens for authenticating to Google Cloud as an output for use in future steps in the workflow. These options only apply to ID tokens generated by this action. By default, this action does not generate any tokens.

[!CAUTION]

ID Tokens have a maximum lifetime of 10 minutes. This value cannot be changed.

Inputs: Miscellaneous

The following inputs are for controlling the behavior of this GitHub Actions, regardless of the authentication mechanism.

Outputs

<a id="setup"></a>

Setup

This section describes the three configuration options:

  1. (Preferred) Direct Workload Identity Federation
  2. Workload Identity Federation through a Service Account
  3. Service Account Key JSON

[!IMPORTANT]

It can take up to 5 minutes for Workload Identity Pools, Workload Identity Providers, and IAM permissions to propagate. Please wait at least five minutes and follow all Troubleshooting steps before opening an issue.

<a name="direct-wif" id="direct-wif"></a>

(Preferred) Direct Workload Identity Federation

In this setup, the Workload Identity Pool has direct IAM permissions on Google Cloud resources; there are no intermediate service accounts or keys. This is preferred since it directly authenticates GitHub Actions to Google Cloud without a proxy resource. However, not all Google Cloud resources support principalSet identities, and the resulting token has a maximum lifetime of 10 minutes. Please see the documentation for your Google Cloud service for more information.

Authenticate to Google Cloud from GitHub Actions with Direct Workload Identity Federation

[!IMPORTANT]

To generate OAuth 2.0 access tokens or ID tokens, you must provide a service account email, and the Workload Identity Pool must have roles/iam.workloadIdentityUser permissions on the target Google Cloud Service Account. Follow the steps for Workload Identity Federation through a Service Account instead.

<details> <summary>Click here to show detailed instructions for configuring GitHub authentication to Google Cloud via a direct Workload Identity Federation.</summary>

These instructions use the gcloud command-line tool.

  1. Create a Workload Identity Pool:

    # TODO: replace ${PROJECT_ID} with your value below.
    
    gcloud iam workload-identity-pools create "github" \
      --project="${PROJECT_ID}" \
      --location="global" \
      --display-name="GitHub Actions Pool"
    
  2. Get the full ID of the Workload Identity Pool:

    # TODO: replace ${PROJECT_ID} with your value below.
    
    gcloud iam workload-identity-pools describe "github" \
      --project="${PROJECT_ID}" \
      --location="global" \
      --format="value(name)"
    

    This value should be of the format:

    projects/123456789/locations/global/workloadIdentityPools/github
    
  3. Create a Workload Identity Provider in that pool:

    🛑 CAUTION! Always add an Attribute Condition to restrict entry into the Workload Identity Pool. You can further restrict access in IAM Bindings, but always add a basic condition that restricts admission into the pool. A good default option is to restrict admission based on your GitHub organization as demonstrated below. Please see the security considerations for more details.

    # TODO: replace ${PROJECT_ID} and ${GITHUB_ORG} with your values below.
    
    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"
    

    ❗️ IMPORTANT You must map any claims in the incoming token to attributes before you can assert on those attributes in a CEL expression or IAM policy!

  4. Extract the Workload Identity Provider resource name:

    # TODO: replace ${PROJECT_ID} with your value below.
    
    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:

    - uses: 'google-github-actions/auth@v2'
      with:
        project_id: 'my-project'
        workload_identity_provider: '...' # "projects/123456789/locations/global/workloadIdentityPools/github/providers/my-repo"
    

    ❗️ IMPORTANT The project_id input is optional, but may be required by downstream authentication systems such as the gcloud CLI. Unfortunately we cannot extract the project ID from the Workload Identity Provider, since it requires the project number.

    It is technically possible to convert a project number into a project ID, but it requires permissions to call Cloud Resource Manager, and we cannot guarantee that the Workload Identity Pool has those permissions.

  5. As needed, allow authentications from the Workload Identity Pool to Google Cloud resources. These can be any Google Cloud resources that support federated ID tokens, and it can be done after the GitHub Action is configured.

    The following example shows granting access from a GitHub Action in a specific repository a secret in Google Secret Manager.

    # TODO: replace ${PROJECT_ID}, ${WORKLOAD_IDENTITY_POOL_ID}, and ${REPO}
    # with your values below.
    #
    # ${REPO} is the full repo name including the parent GitHub organization,
    # such as "my-org/my-repo".
    #
    # ${WORKLOAD_IDENTITY_POOL_ID} is the full pool id, such as
    # "projects/123456789/locations/global/workloadIdentityPools/github".
    
    gcloud secrets add-iam-policy-binding "my-secret" \
      --project="${PROJECT_ID}" \
      --role="roles/secretmanager.secretAccessor" \
      --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/${REPO}"
    

    Review the GitHub documentation for a complete list of options and values. This GitHub repository does not seek to enumerate every possible combination.

</details>

<a name="indirect-wif" id="indirect-wif"></a>

Workload Identity Federation through a Service Account

In this setup, the Workload Identity Pool impersonates a Google Cloud Service Account which has IAM permissions on Google Cloud resources. This exchanges the GitHub Actions OIDC token with a Google Cloud OAuth 2.0 access token by granting GitHub Actions permissions to mint tokens for the given Service Account. Thus GitHub Actions inherits that Service Account's permissions by proxy.

Authenticate to Google Cloud from GitHub Actions with Workload Identity Federation through a Service Account

<details> <summary>Click here to show detailed instructions for configuring GitHub authentication to Google Cloud via a Workload Identity Federation through a Service Account.</summary>

These instructions use the gcloud command-line tool.

  1. (Optional) Create a Google Cloud Service Account. If you already have a Service Account, take note of the email address and skip this step.

    # TODO: replace ${PROJECT_ID} with your value below.
    
    gcloud iam service-accounts create "my-service-account" \
      --project "${PROJECT_ID}"
    
  2. Create a Workload Identity Pool:

    # TODO: replace ${PROJECT_ID} with your value below.
    
    gcloud iam workload-identity-pools create "github" \
      --project="${PROJECT_ID}" \
      --location="global" \
      --display-name="GitHub Actions Pool"
    
  3. Get the full ID of the Workload Identity Pool:

    # TODO: replace ${PROJECT_ID} with your value below.
    
    gcloud iam workload-identity-pools describe "github" \
      --project="${PROJECT_ID}" \
      --location="global" \
      --format="value(name)"
    

    This value should be of the format:

    projects/123456789/locations/global/workloadIdentityPools/github
    
  4. Create a Workload Identity Provider in that pool:

    🛑 CAUTION! Always add an Attribute Condition to restrict entry into the Workload Identity Pool. You can further restrict access in IAM Bindings, but always add a basic condition that restricts admission into the pool. A good default option is to restrict admission based on your GitHub organization as demonstrated below. Please see the security considerations for more details.

    # TODO: replace ${PROJECT_ID} and ${GITHUB_ORG} with your values below.
    
    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"
    

    ❗️ IMPORTANT You must map any claims in the incoming token to attributes before you can assert on those attributes in a CEL expression or IAM policy!

  5. Allow authentications from the Workload Identity Pool to your Google Cloud Service Account.

    # TODO: replace ${PROJECT_ID}, ${WORKLOAD_IDENTITY_POOL_ID}, and ${REPO}
    # with your values below.
    #
    # ${REPO} is the full repo name including the parent GitHub organization,
    # such as "my-org/my-repo".
    #
    # ${WORKLOAD_IDENTITY_POOL_ID} is the full pool id, such as
    # "projects/123456789/locations/global/workloadIdentityPools/github".
    
    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}"
    

    Review the GitHub documentation for a complete list of options and values. This GitHub repository does not seek to enumerate every possible combination.

  6. Extract the Workload Identity Provider resource name:

    # TODO: replace ${PROJECT_ID} with your value below.
    
    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:

    - uses: 'google-github-actions/auth@v2'
      with:
        service_account: '...' # my-service-account@my-project.iam.gserviceaccount.com
        workload_identity_provider: '...' # "projects/123456789/locations/global/workloadIdentityPools/github/providers/my-repo"
    
  7. 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.

    # TODO: replace ${PROJECT_ID} with your value below.
    
    gcloud secrets add-iam-policy-binding "my-secret" \
      --project="${PROJECT_ID}" \
      --role="roles/secretmanager.secretAccessor" \
      --member="serviceAccount:my-service-account@${PROJECT_ID}.iam.gserviceaccount.com"
    
</details>

<a name="sake" id="sake"></a>

Service Account Key JSON

In this setup, a Service Account has direct IAM permissions on Google Cloud resources. You download a Service Account Key JSON file and upload it to GitHub as a secret.

Authenticate to Google Cloud from GitHub Actions with a Service Account Key

[!CAUTION]

Google Cloud Service Account Key JSON files must be secured and treated like a password. Anyone with access to the JSON key can authenticate to Google Cloud as the underlying Service Account. By default, these credentials never expire, which is why the former authentication options are much preferred.

<details> <summary>Click here to show detailed instructions for configuring GitHub authentication to Google Cloud via a Service Account Key JSON.</summary>

These instructions use the gcloud command-line tool.

  1. (Optional) Create a Google Cloud Service Account. If you already have a Service Account, take note of the email address and skip this step.

    # TODO: replace ${PROJECT_ID} with your value below.
    
    gcloud iam service-accounts create "my-service-account" \
      --project "${PROJECT_ID}"
    
  2. Create a Service Account Key JSON for the Service Account.

    # TODO: replace ${PROJECT_ID} with your value below.
    
    gcloud iam service-accounts keys create "key.json" \
      --iam-account "my-service-account@${PROJECT_ID}.iam.gserviceaccount.com"
    
  3. Upload the contents of this file as a GitHub Actions Secret.

    Use the name of the GitHub Actions secret as the credentials_json value in the GitHub Actions YAML:

    - uses: 'google-github-actions/auth@v2'
      with:
        credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' # Replace with the name of your GitHub Actions secret
    
</details>