action-hosting-deploy icon indicating copy to clipboard operation
action-hosting-deploy copied to clipboard

Authenticate with workload federation credential file instead of service account key

Open steveoh opened this issue 4 years ago • 18 comments

The use case you're trying to solve

I would like to use a federated credential file from the auth action to configure the firebase deploy

Change to the action that would solve that use case

- id: auth
   name: Authenticate to Google Cloud
   uses: google-github-actions/[email protected]
   with:
       create_credentials_file: true
       workload_identity_provider: ...
       service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }}

  - name: 🚀 Firebase Deploy
        uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          credentials_file_path: ${{ steps.auth.output.credentials_file_path }}
          projectId: '${{ secrets.PROJECT_ID }}'
          channelId: live
        env:
          FIREBASE_CLI_PREVIEWS: hostingchannels 

steveoh avatar Nov 24 '21 18:11 steveoh

Here's more info on keyless auth in Github Actions

FYI this is blocked on upgrading the google-auth-client library in the Firebase CLI, it's using 6.x.x which doesn't support authenticating this way. See this release: https://github.com/googleapis/google-auth-library-nodejs/releases/tag/v7.0.0

rockwotj avatar Dec 28 '21 16:12 rockwotj

Looking forward to having this merged, currently the only part of our CI/CD pipeline that doesn't work with WLIF

enchorb avatar Dec 29 '21 20:12 enchorb

FWIW I have confirmed version 10.1.0 of the cli works with this auth method

rockwotj avatar Jan 15 '22 03:01 rockwotj

This may end up being relevant

https://github.com/firebase/firebase-tools/issues/3926#issuecomment-1014591105

steveoh avatar Jan 17 '22 23:01 steveoh

Based on the usage of npx, this should already use the new CLI.

https://github.com/FirebaseExtended/action-hosting-deploy/blob/ff6e7dde58a4f7f1db590927596bf683250c6cc8/src/deploy.ts#L79

I think @steveoh you just need to add the right scopes and your snippet in the issue should work.

rockwotj avatar Jan 18 '22 03:01 rockwotj

To be fair, that is your code snippet that I cross posted :) I hope to try it this week.

steveoh avatar Jan 18 '22 17:01 steveoh

@rockwotj would firebaseServiceAccount still be required and if so would it be the email?

using

- id: auth
        name: 🗝️ Authenticate to Google Cloud
        uses: google-github-actions/[email protected]
        with:
          token_format: access_token
          access_token_scopes: 'email, openid, https://www.googleapis.com/auth/cloud-platform, https://www.googleapis.com/auth/firebase'
          workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }}
          service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }}
          create_credentials_file: true

- name: 🚀 Firebase Deploy
        uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.SERVICE_ACCOUNT_EMAIL }}'
          channelId: live
          projectId: '${{ secrets.PROJECT_ID }}'
          target: '${{ secrets.PROJECT_ID }}'
        env:
          FIREBASE_CLI_PREVIEWS: hostingchannels

shows a CI error of need to call "error": "Failed to authenticate, have you run \u001b[1mfirebase login\u001b[22m?"

steveoh avatar Jan 18 '22 19:01 steveoh

It seems this action requires the service account is a JSON blob that it writes to disk and then overrides the environment variable that the CLI uses for auth. If you really want to use this action you'll have to hack around by reading the file output in the auth command into that input.

To be perfectly honest, it's probably simpler to just run npx firebase-tools in a bash script in your action. Here my redacted full action to deploy a preview branch for PR, and adds the deployed URL to an environment named "preview". You also have to add a specific label to the PR to enable this action. Hopefully this is helpful

name: "Frontend Preview"
on: ["pull_request"]
jobs:
  preview_frontend:
    runs-on: ubuntu-latest
    if: contains(github.event.pull_request.labels.*.name, 'preview')
    environment:
      name: preview
      url: ${{ steps.deployment_url.outputs.url }}
    permissions:
      contents: 'read'
      id-token: 'write'
      deployments: 'write'
    steps:
    - uses: actions/checkout@v2
    - id: 'auth'
      name: 'Authenticate to GCP'
      uses: 'google-github-actions/[email protected]'
      with:
        token_format: 'access_token'
        access_token_scopes: 'email, openid, https://www.googleapis.com/auth/cloud-platform, https://www.googleapis.com/auth/firebase'
        workload_identity_provider: 'projects/redacted/locations/global/workloadIdentityPools/redacted/providers/redacted'
        service_account: '[email protected]'
        create_credentials_file: true
    - uses: actions/setup-node@v1
      with:
        node-version: '16.x'
    - name: Deploy
      run: npm ci && npx firebase-tools --project redacted hosting:channel:deploy ${{github.event.number}}
    - id: deployment_url
      name: Set Environment
      run: |
        URL="$(npx firebase-tools --json --project redacted --non-interactive hosting:channel:open ${{github.event.number}} | jq -r '.result.url')"
        echo "::set-output name=url::$URL"

rockwotj avatar Jan 18 '22 19:01 rockwotj

Ok, but this issue is for making this action work with identity federation, not dropping into the cli and doing it manually. I do appreciate knowing how it could work that way. Thanks!

steveoh avatar Jan 18 '22 19:01 steveoh

Sure - if you want to this action it will need to be modified to make the firebaseServiceAccount optional and not override the environment variable in that case.

rockwotj avatar Jan 18 '22 19:01 rockwotj

Do we have the attention of any project maintainers?

steveoh avatar Jan 18 '22 21:01 steveoh

  • id: auth name: Authenticate to Google Cloud uses: google-github-actions/[email protected] with: create_credentials_file: true workload_identity_provider: ... service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }}

    • name: 🚀 Firebase Deploy uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: '${{ secrets.GITHUB_TOKEN }}' credentials_file_path: ${{ steps.auth.output.credentials_file_path }} projectId: '${{ secrets.PROJECT_ID }}' channelId: live env: FIREBASE_CLI_PREVIEWS: hostingchannels
      • uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: "${{ secrets.GITHUB_TOKEN }}" firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_LAWVITE_DEV }}" expires: 20d projectId: lawvitedependabot/npm_and_yarn/babel/preset-env-7.16.11package-lock.json

Hallerf avatar Feb 09 '22 18:02 Hallerf

@Hallerf that works?

I can confirm it does not with the following error

{
    "status": "error",
    "error": "Failed to authenticate, have you run firebase login"
}

steveoh avatar Feb 09 '22 19:02 steveoh

Hi!

I was stuck in this problem. IDK if this concerns you: ⛔ Issue : I manually created the firebaseServiceAccount token using $ firebase login:ci and save it in github actions secrets and it didn't work. ✅ Solution : I ran $ firebase init hosting:github and in one of the steps it did automatically upload a new token to github actions secrets. And now it's working fine.

Cheers

zakariazuck avatar Mar 21 '22 00:03 zakariazuck

You can use the following snippet to use google-github-actions/auth-generated credential file with action-hosting-deploy:

- id: auth
  uses: 'google-github-actions/auth@v1'
  with:
    workload_identity_provider: ...
    service_account: ...
    create_credentials_file: true

- run: |
    echo "SERVICE_ACCOUNT_KEY=$(cat "${{ steps.auth.outputs.credentials_file_path }}" | tr -d '\n')" >> $GITHUB_ENV

- uses: FirebaseExtended/action-hosting-deploy@v0
  with:
    firebaseServiceAccount: "${{ env.SERVICE_ACCOUNT_KEY }}"

rasendubi avatar Nov 11 '22 23:11 rasendubi