Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with Workload Identity Federation in when service_account parameter is not specified and using gcloud run deploy #454

Open
vaisov-gemba opened this issue Nov 12, 2024 · 7 comments
Labels
bug Something isn't working

Comments

@vaisov-gemba
Copy link

TL;DR

The google-github-actions/auth@v2 action does not correctly authenticate using Workload Identity Federation if the service_account parameter is omitted, even though the documentation suggests it is optional.

Expected behavior

When configuring Workload Identity Federation in google-github-actions/auth@v2, the action should authenticate with the default Service Account in the Workload Identity Pool if service_account is not explicitly provided.

Observed behavior

When the service_account parameter is omitted, the action gcloud run deploy fails with PERMISSION_DENIED errors, specifically missing permissions such as run.services.get, despite the Service Account having the correct roles assigned. Deployment worked only when the service_account parameter was explicitly specified.

Action YAML

name: Deploy ExampleApp to Cloud Run

on:
  workflow_dispatch:
  push:
    branches:
      - development-pipeline

jobs:
  build:
    permissions:
      contents: 'read'
      id-token: 'write'

    runs-on: ubuntu-latest
    environment: ${{ github.ref == 'refs/heads/development' && 'development' || github.ref == 'refs/heads/testing' && 'testing' || github.ref == 'refs/heads/staging' && 'staging' || github.ref == 'refs/heads/main' && 'production' }}
        
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Authenticate to GCP
        uses: google-github-actions/auth@v2
        with:
          project_id: 'example-project-id'
          workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/runner-pool/providers/github'
          service_account: '[email protected]'

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v2
        with:
          project_id: 'example-project-id'

      - name: Configure Docker for Google Artifact Registry 
        run: gcloud auth configure-docker example-region-docker.pkg.dev

      - name: Build and Push Container
        run: |
          docker build -t "example-region-docker.pkg.dev/example-project-id/api-services-test/example-app:${{ github.run_id }}" -f Dockerfile_exampleapp .
          docker push "example-region-docker.pkg.dev/example-project-id/api-services-test/example-app:${{ github.run_id }}"

      - name: 'Deploy to Cloud Run'
        id: 'deploy'
        run: |
          gcloud run deploy example-app \
          --image example-region-docker.pkg.dev/example-project-id/api-services-test/example-app:${{ github.run_id }} \
          --update-secrets 'EXAMPLE_SECRET_ONE=example_secret_one:latest,EXAMPLE_SECRET_TWO=example_secret_two:latest,EXAMPLE_SECRET_THREE=example_secret_three:latest,EXAMPLE_SECRET_FOUR=example_secret_four:latest,/path/to/certificates/example-cert-path=example_cert_secret:latest,/path/to/creds/example-cred-path=example_cred_secret:latest' \
          --update-labels 'managed-by=github-actions,commit-sha=${{ github.run_id }}' \
          --format json \
          --region example-region \
          --ingress internal \
          --min-instances 1 \
          --max-instances 1 \
          --service-account [email protected] \
          --vpc-connector example-connector \
          --vpc-egress private-ranges-only

Log output

ERROR: (gcloud.run.deploy) PERMISSION_DENIED: Permission 'run.services.get' denied on resource 'namespaces/example-project-id/services/example-app' (or resource may not exist). This command is authenticated as principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/runner-pool/subject/repo:ORG/REPO:environment:false using the credentials in /home/runner/work/REPO/REPO/gha-creds-xyz123.json, specified by the [auth/credential_file_override] property.

Additional information

No response

@vaisov-gemba vaisov-gemba added the bug Something isn't working label Nov 12, 2024
Copy link

Hi there @vaisov-gemba 👋!

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
Copy link
Member

As documented, if service_account is omitted in the auth, then the GitHub Action uses Direct Workload Identity Federation, meaning you need to grant the federated identity (principal:// or principalSet://) permissions to deploy Cloud Run services.

The --service-account flag specifies the identity the service should run as, it does not specify the identity to use when making the API call to deploy to Cloud Run.

@vaisov-gemba
Copy link
Author

Yes, that's what I was using - just Direct WIF with principalSet, but maybe I'm setting my principalSet wrong. Also I meant specification of service_account in Authenticate to GCP step.

As documented, if service_account is omitted in the auth, then the GitHub Action uses Direct Workload Identity Federation, meaning you need to grant the federated identity (principal:// or principalSet://) permissions to deploy Cloud Run services.

The --service-account flag specifies the identity the service should run as, it does not specify the identity to use when making the API call to deploy to Cloud Run.

@sethvargo
Copy link
Member

In your original issue, you said:

When the service_account parameter is omitted, the action gcloud run deploy fails with PERMISSION_DENIED errors, specifically missing permissions such as run.services.get, despite the Service Account having the correct roles assigned.

When you omit the service_account parameter from the auth step, auth uses Direct WIF, which means the the principalSet:// must have IAM permissions to deploy to Cloud Run (roles/cloudrun.developer).


Here's an example using Direct WIF:

- uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/runner-pool/providers/github'

and you'd grant the WIF identity permission to deploy doing something like:

$ gcloud projects add-iam-policy-binding "my-project" \
    --role "roles/cloudrun.developer" \
    --member "principalSet://projects/PROJECT_NUMBER/locations/global/..."

Here's an example using service account impersonation:

- uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/runner-pool/providers/github'
    service_account: '[email protected]'

and you'd grant the WIF identity permission to deploy doing something like:

$ gcloud projects add-iam-policy-binding "my-project" \
    --role "roles/cloudrun.developer" \
    --member "serviceAccount:[email protected]"

Both of these are entirely independent of what you specify for the service_account on the Cloud Run service itself, which is the runtime service agent.

@emigre459
Copy link

I wasn't able to get the Direct WIF example above to work for my project, but I was able to get the following permissions-setting approach to work. Maybe the result of a recent update to gcloud? I'd be happy to submit a PR to the README for this if useful (seems more broadly useful in terms of service-permissions-setting than the secrets example currently in README):

# Uses BigQuery User role as example and grants any member of the github pool ability to interact with that service as a BQ User
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --role "roles/bigquery.user" \
    --member "principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/github/*"

@sethvargo
Copy link
Member

@emigre459 is the primary different the ian.googleapis.com?

@emigre459
Copy link

Yes I think that + the guidance I found elsewhere (specific to my project/risk profile to somd extent) to do /* at the end too. Sounds trivial but took me a lot of trial and error before I got it right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

3 participants