FirebaseExtended / action-hosting-deploy

Automatically deploy shareable previews for your Firebase Hosting sites
https://firebase.google.com/docs/hosting/github-integration
Apache License 2.0
695 stars 202 forks source link

Authenticate with workload federation credential file instead of service account key #174

Open steveoh opened 2 years ago

steveoh commented 2 years ago

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/auth@v0.3.1
   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 
rockwotj commented 2 years ago

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

enchorb commented 2 years ago

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

rockwotj commented 2 years ago

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

steveoh commented 2 years ago

This may end up being relevant

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

rockwotj commented 2 years ago

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.

steveoh commented 2 years ago

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

steveoh commented 2 years ago

@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/auth@v0.4.4
        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?"

rockwotj commented 2 years ago

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/auth@v0.4.4'
      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: 'redacted@redacted.iam.gserviceaccount.com'
        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"
steveoh commented 2 years ago

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!

rockwotj commented 2 years ago

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.

steveoh commented 2 years ago

Do we have the attention of any project maintainers?

Hallerf commented 2 years ago
steveoh commented 2 years ago

@Hallerf that works?

I can confirm it does not with the following error

{
    "status": "error",
    "error": "Failed to authenticate, have you run firebase login"
}
zakariazuck commented 2 years ago

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

rasendubi commented 1 year ago

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 }}"