-
Notifications
You must be signed in to change notification settings - Fork 280
Description
TL;DR
When using this action to obtain impersonated credentials I can setup my docker compose override to update my credential path (GOOGLE_APPLICATION_CREDENTIALS) path variable via volume mounting which I can inspect upon running container exec commands alongside printenv to confirm my docker service has resolved the mounted credentials. My issue is the OIDC flow does not work inside the container which I am running...
here is a breakdown of my workflow
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
cache-dependency-path: "./app/package-lock.json"
- uses: "google-github-actions/auth@v2"
id: auth
with:
token_format: 'access_token'
workload_identity_provider: ${{ vars.WORKLOAD_IDENTITY_PROVIDER }}
service_account: [email protected]
create_credentials_file: true
- name: Generate docker-compose.override.yml
run: |
CREDENTIALS_PATH=${{ steps.auth.outputs.credentials_file_path }}
echo "Using credentials file at $CREDENTIALS_PATH"
# Create the override file
cat <<EOF > docker-compose.override.yml
services:
firebase-functions:
volumes:
- $CREDENTIALS_PATH:/root/.config/gcloud/application_default_credentials.json:ro
environment:
GOOGLE_APPLICATION_CREDENTIALS: "/root/.config/gcloud/application_default_credentials.json"
EOF
echo "docker-compose.override.yml created with dynamic volume and environment variable."
- name: cat dockerfile.functions
run: cat dockerfile.functions
- name: Run Docker Compose
run: |
docker compose down
docker compose up -d
- name: confirm volume mounting
run: |
docker exec firebase-functions-1 printenv && \
docker exec firebase-functions-1 cat /root/.config/gcloud//application_default_credentials.json
from debug.logs:
[warn] ⚠ functions: Your GOOGLE_APPLICATION_CREDENTIALS environment variable points to /root/.config/gcloud/application_default_credentials.json. Non-emulated services will access production using these credentials. Be careful! {"metadata":{"emulator":{"name":"functions"},"message":"Your GOOGLE_APPLICATION_CREDENTIALS environment variable points to /root/.config/gcloud/application_default_credentials.json. Non-emulated services will access production using these credentials. Be careful!"}}
above docker commands / logs confirm volume mouting is there inside the container and credentials are picked up, however any calls to my service inside the container running in github action fail on authentication
Does the OIDC auth pattern persist when working in github actions with docker? I do not see why this would fail other than if something has been configured with the resulting credentials provided by auth action step
Expected behavior
calls to dockerized app would use service account impersonsation, just as it does with running any app with the credentials provided on the github action runner
Observed behavior
I get failed to impersonated errors:
[info] > ('Unable to acquire impersonated credentials', '{\n "error": {\n "code": 403,\n "message": "Caller does not have required permission to use project abc. Grant the caller the roles/serviceusage.serviceUsageConsumer role, or a custom role with the serviceusage.services.use permission, by visiting https://console.developers.google.com/iam-admin/iam/project?project=abc and then retry. Propagation of the new permission may take a few minutes.",\n "status": "PERMISSION_DENIED",\n "details": [\n {\n "@type": "type.googleapis.com/google.rpc.ErrorInfo",\n "reason": "USER_PROJECT_DENIED",\n "domain": "googleapis.com",\n "metadata": {\n "containerInfo": "abc",\n "service": "iamcredentials.googleapis.com",\n "consumer": "projects/abcv"\n }\n },\n {\n "@type": "type.googleapis.com/google.rpc.LocalizedMessage",\n "locale": "en-US",\n "message": "Caller does not have required permission to use project abc. Grant the caller the roles/serviceusage.serviceUsageConsumer role, or a custom role with the serviceusage.services.use permission, by visiting https://console.developers.google.com/iam-admin/iam/project?project=abc and then retry. Prop
Action YAML
name: (run-e2e-tests) with docker
on:
workflow_call:
inputs:
environment:
description: environment to run e2e tests against
required: true
type: string
default: dev
push:
branches:
- my-branch
permissions:
contents: read
id-token: write
jobs:
run-e2e-tests:
environment: ${{ inputs.environment || 'dev' }}
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
app: ["highways"]
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
cache-dependency-path: "./app/package-lock.json"
- uses: "google-github-actions/auth@v2"
id: auth
with:
token_format: 'access_token'
workload_identity_provider: ${{ vars.WORKLOAD_IDENTITY_PROVIDER }}
service_account: [email protected]
create_credentials_file: true
- name: Generate docker-compose.override.yml
run: |
CREDENTIALS_PATH=${{ steps.auth.outputs.credentials_file_path }}
echo "Using credentials file at $CREDENTIALS_PATH"
# Create the override file
cat <<EOF > docker-compose.override.yml
services:
firebase-functions:
volumes:
- $CREDENTIALS_PATH:/root/.config/gcloud/application_default_credentials.json:ro
environment:
GOOGLE_APPLICATION_CREDENTIALS: "/root/.config/gcloud/application_default_credentials.json"
EOF
echo "docker-compose.override.yml created with dynamic volume and environment variable."
- name: cat dockerfile.functions
run: cat dockerfile.functions
- name: Run Docker Compose
run: |
docker compose down
docker compose up -d
- name: confirm volume mounting
run: |
docker exec firebase-functions-1 printenv && \
docker exec firebase-functions-1 cat /root/.config/gcloud//application_default_credentials.json
- name: Install Frontend Dependencies
working-directory: ./app
run: |
cp ".env.dev" .env || true
npm ci
npm list
- name: Create cypress.env.json
run: |
echo '{
"USERNAME": "${{ secrets.USERNAME }}",
"PASSWORD": "${{ secrets.PASSWORD }}",
"CHAT_URL": "http://127.0.0.1:5173",
"LOGIN_URL": "${{ vars.CYPRESS_B2C_ENVIRONMENT }}"
}' > ./cypress.env.json
shell: bash
working-directory: ./e2e-tests
- name: Configure hosts file
run: |
echo "127.0.0.1 ipv4-localhost" | sudo tee -a /etc/hosts
cat /etc/hosts | grep ipv4-localhost
working-directory: ./app
- name: Start server in the background
run: |
npm run start -- --host 127.0.0.1 &
sleep 5
netstat -tulpn | grep 5173
working-directory: ./app
- name: Wait for server
run: |
# Force IPv4 resolution
export NODE_OPTIONS="--dns-result-order=ipv4first"
npx wait-on http://127.0.0.1:5173 --timeout 180000 --interval 5000
working-directory: ./app
- name: Confirm server is up
run: curl -v http://localhost:5173
- name: Cypress run
uses: cypress-io/github-action@v6
with:
working-directory: ./e2e-tests
browser: chrome
spec: cypress/e2e/${{ matrix.app }}/Jailbreak.feature
wait-on: "http://127.0.0.1:5173"
wait-on-timeout: 120
env:
DEBUG: 'cypress:*'
CYPRESS_BASE_URL: "http://127.0.0.1:5173"
NODE_OPTIONS: "--dns-result-order=ipv4first"
- name: Get Debug Logs
if: failure()
run: |
docker exec firebase-functions-1 cat firebase-debug.log
- name: Upload Cypress Videos
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-videos
path: ./e2e-tests/cypress/videosLog output
Additional information
regarding error message roles/serviceusage.serviceUsageConsumer impersonated service account is working via docker compose locally and has all relevant permissions