google-github-actions / auth

A GitHub Action for authenticating to Google Cloud.
https://cloud.google.com/iam
Apache License 2.0
970 stars 207 forks source link

403: PERMISSION_DENIED #426

Closed phillipshaong closed 4 months ago

phillipshaong commented 4 months ago

TL;DR

I am getting "Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist)." when using 'google-github-actions/auth@v2'. I've already tried the items in the troubleshooting manual (https://github.com/google-github-actions/auth/blob/main/docs/TROUBLESHOOTING.md).

Expected behavior

Successful authentication

Observed behavior

Permission Denied.

Action YAML

# This workflow build and push a Docker container to Google Artifact Registry and deploy it on Cloud Run when a commit is pushed to the "main" branch
#
# Overview:
#
# 1. Authenticate to Google Cloud
# 2. Authenticate Docker to Artifact Registry
# 3. Build a docker container
# 4. Publish it to Google Artifact Registry
# 5. Deploy it to Cloud Run
#
# To configure this workflow:
#
# 1. Ensure the required Google Cloud APIs are enabled:
#
#    Cloud Run            run.googleapis.com
#    Artifact Registry    artifactregistry.googleapis.com
#
# 2. Create and configure Workload Identity Federation for GitHub (https://github.com/google-github-actions/auth#setting-up-workload-identity-federation)
#
# 3. Ensure the required IAM permissions are granted
#
#    Cloud Run
#      roles/run.admin
#      roles/iam.serviceAccountUser     (to act as the Cloud Run runtime service account)
#
#    Artifact Registry
#      roles/artifactregistry.admin     (project or repository level)
#
#    NOTE: You should always follow the principle of least privilege when assigning IAM roles
#
# 4. Create GitHub secrets for WIF_PROVIDER and WIF_SERVICE_ACCOUNT
#
# 5. Change the values for the GAR_LOCATION, SERVICE and REGION environment variables (below).
#
# NOTE: To use Google Container Registry instead, replace ${{ env.GAR_LOCATION }}-docker.pkg.dev with gcr.io
#
# For more support on how to run this workflow, please visit https://github.com/marketplace/actions/deploy-to-cloud-run
#
# Further reading:
#   Cloud Run IAM permissions                 - https://cloud.google.com/run/docs/deploying
#   Artifact Registry IAM permissions         - https://cloud.google.com/artifact-registry/docs/access-control#roles
#   Container Registry vs Artifact Registry   - https://cloud.google.com/blog/products/application-development/understanding-artifact-registry-vs-container-registry
#   Principle of least privilege              - https://cloud.google.com/blog/products/identity-security/dont-get-pwned-practicing-the-principle-of-least-privilege

name: Build and Deploy to Cloud Run

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:

env:
  PROJECT_ID: karmakard-d1935 
  GAR_LOCATION: us-central1
  SERVICE: main-app 
  REGION: us-central1 

jobs:
  deploy:
    # Add 'id-token' with the intended permissions for workload identity federation
    permissions:
      contents: 'read'
      id-token: 'write'

    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Google Auth
        id: auth
        uses: 'google-github-actions/auth@v2'
        with:
          token_format: 'access_token'
          workload_identity_provider: '${{ secrets.WIF_PROVIDER }}' # e.g. - projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider
          service_account: '${{ secrets.WIF_SERVICE_ACCOUNT }}' # e.g. - my-service-account@my-project.iam.gserviceaccount.com

      # NOTE: Alternative option - authentication via credentials json
      # - name: Google Auth
      #   id: auth
      #   uses: 'google-github-actions/auth@v2'
      #   with:
      #     credentials_json: '${{ secrets.GCP_CREDENTIALS }}'

      # BEGIN - Docker auth and build (NOTE: If you already have a container image, these Docker steps can be omitted)

      # Authenticate Docker to Google Cloud Artifact Registry
      - name: Docker Auth
        id: docker-auth
        uses: 'docker/login-action@v1'
        with:
          username: 'oauth2accesstoken'
          password: '${{ steps.auth.outputs.access_token }}'
          registry: '${{ env.GAR_LOCATION }}-docker.pkg.dev'

      - name: Build and Push Container
        run: |-
          docker build -t "${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.SERVICE }}:${{ github.sha }}" ./
          docker push "${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.SERVICE }}:${{ github.sha }}"

      # END - Docker auth and build

      - name: Deploy to Cloud Run
        id: deploy
        uses: google-github-actions/deploy-cloudrun@v0
        with:
          service: ${{ env.SERVICE }}
          region: ${{ env.REGION }}
          # NOTE: If using a pre-built image, update the image name here
          image: ${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.SERVICE }}:${{ github.sha }}

      # If required, use the Cloud Run url output in later steps
      - name: Show Output
        run: echo ${{ steps.deploy.outputs.url }}

Log output

##[debug]Evaluating condition for step: 'Google Auth'
##[debug]Evaluating: success()
##[debug]Evaluating success:
##[debug]=> true
##[debug]Result: true
##[debug]Starting: Google Auth
##[debug]Register post job cleanup for action: google-github-actions/auth@v2
##[debug]Loading inputs
##[debug]Evaluating: secrets.WIF_PROVIDER
##[debug]Evaluating Index:
##[debug]..Evaluating secrets:
##[debug]..=> Object
##[debug]..Evaluating String:
##[debug]..=> 'WIF_PROVIDER'
##[debug]=> '***'
##[debug]Result: '***'
##[debug]Evaluating: secrets.WIF_SERVICE_ACCOUNT
##[debug]Evaluating Index:
##[debug]..Evaluating secrets:
##[debug]..=> Object
##[debug]..Evaluating String:
##[debug]..=> 'WIF_SERVICE_ACCOUNT'
##[debug]=> '***'
##[debug]Result: '***'
##[debug]Loading env
Run google-github-actions/auth@v2
##[debug]Using workload identity provider "***"
##[debug]ID token url is https://pipelinesghubeus6.actions.githubusercontent.com/nPPR4F1gmim9xBq2gbEt9SrHoUseAysYAS0e0owjbEWVsLZZAx/00000000-0000-0000-0000-000000000000/_apis/distributedtask/hubs/Actions/plans/858d4431-c642-48ad-af54-85de1f2af3d5/jobs/e07742bd-189a-5079-918b-43f8b2f94b89/idtoken?api-version=2.0&audience=https%3A%2F%2Fiam.googleapis.com%2F***
::add-mask::***
##[debug]WorkloadIdentityFederationClient: Computed audience, //iam.googleapis.com/***
##[debug]Creating credentials file
##[debug]WorkloadIdentityFederationClient.createCredentialsFile: Enabling service account impersonation via https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/***:generateAccessToken
##[debug]WorkloadIdentityFederationClient.createCredentialsFile: Creating credentials, {
##[debug]  "outputPath": "/home/runner/work/karmakard-main-app/karmakard-main-app/gha-creds-3bc6da216881c597.json"
##[debug]}
Created credentials file at "/home/runner/work/karmakard-main-app/karmakard-main-app/gha-creds-3bc6da216881c597.json"
##[debug]WorkloadIdentityFederationClient.getToken: Built request, {
##[debug]  "method": "POST",
##[debug]  "path": "https://sts.googleapis.com/v1/token",
##[debug]  "body": {
##[debug]    "audience": "//iam.googleapis.com/***",
##[debug]    "grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
##[debug]    "requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
##[debug]    "scope": "https://www.googleapis.com/auth/cloud-platform",
##[debug]    "subjectTokenType": "urn:ietf:params:oauth:token-type:jwt",
##[debug]    "subjectToken": "***"
##[debug]  }
##[debug]}
##[debug]Successfully generated auth token
::add-mask::***
##[debug]Creating access token
##[debug]Using normal access token flow
##[debug]IAMCredentialsClient.generateAccessToken: Built request, {
##[debug]  "method": "POST",
##[debug]  "path": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/***:generateAccessToken",
##[debug]  "headers": {
##[debug]    "Authorization": "***"
##[debug]  },
##[debug]  "body": {
##[debug]    "scope": [
##[debug]      "https://www.googleapis.com/auth/cloud-platform"
##[debug]    ],
##[debug]    "lifetime": "3600s"
##[debug]  }
##[debug]}
Error: google-github-actions/auth failed with: failed to generate Google Cloud OAuth 2.0 Access Token for ***: {
  "error": {
    "code": 403,
    "message": "Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "IAM_PERMISSION_DENIED",
        "domain": "iam.googleapis.com",
        "metadata": {
          "permission": "iam.serviceAccounts.getAccessToken"
        }
      }
    ]
  }
}
##[debug]Node Action run completed with exit code 1
##[debug]CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE='/home/runner/work/karmakard-main-app/karmakard-main-app/gha-creds-3bc6da216881c597.json'
##[debug]GOOGLE_APPLICATION_CREDENTIALS='/home/runner/work/karmakard-main-app/karmakard-main-app/gha-creds-3bc6da216881c597.json'
##[debug]GOOGLE_GHA_CREDS_PATH='/home/runner/work/karmakard-main-app/karmakard-main-app/gha-creds-3bc6da216881c597.json'
##[debug]CLOUDSDK_CORE_PROJECT='karmakard-d1935'
##[debug]CLOUDSDK_PROJECT='karmakard-d1935'
##[debug]GCLOUD_PROJECT='karmakard-d1935'
##[debug]GCP_PROJECT='karmakard-d1935'
##[debug]GOOGLE_CLOUD_PROJECT='karmakard-d1935'
##[debug]Set output credentials_file_path = /home/runner/work/karmakard-main-app/karmakard-main-app/gha-creds-3bc6da216881c597.json
##[debug]Set output project_id = karmakard-d1935
##[debug]Set output auth_token = ***
##[debug]Finishing: Google Auth

Additional information

CleanShot 2024-07-14 at 18 06 17

CleanShot 2024-07-14 at 18 05 55

github-actions[bot] commented 4 months ago

Hi there @phillipshaong :wave:!

Thank you for opening an issue. Our team will triage this as soon as we can. Please take a moment to review the troubleshooting steps which lists common error messages and their resolution steps.

sethvargo commented 4 months ago

Did you grant the WIF identity (principalSet://...) permissions as Workload Identity User on your service account? Example from the README:

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}"
phillipshaong commented 4 months ago

Yup, that was the one! I did it manually via the console and I realized that instead of using the service account as a resource, I had added it as a principal. Thanks!