Home > OS >  How can I authorize Cloud Build to deploy to Firebase Hosting in a different project?
How can I authorize Cloud Build to deploy to Firebase Hosting in a different project?

Time:04-02

I have GCP project A and Firebase project B (in a separate GCP project). I'm trying to use Cloud Build in A to build a web app and deploy it to Firebase Hosting in B.

In B's IAM page, I have granted A's <id>@cloudbuild.gserviceaccount.com service account the API Keys Admin, Firebase Admin, and Service Account User roles as described in e.g. screenshot from token generation page

The build process should only have access to Firebase project B, rather than "all my Firebase data and settings" and "my Google Cloud data".

  1. Is there any way to avoid needing to run firebase login here? It seems like the service account should already have sufficient access to deploy to Firebase Hosting.
  2. If I need to run firebase login, is there any way to create a token with a limited scope (assuming that my understanding of the default scope is correct)?

(I've also given B's service account the Cloud Functions Developer role in A and am able to successfully run gcloud --project=$_FIREBASE_PROJECT_ID functions deploy ... in a different build config. I'm also using a Cloud Build config similar to the one described above to deploy to Firebase Hosting in the same GCP project, so I suspect that firebase login isn't necessary in all cases.)

CodePudding user response:

I found an approach that lets project A's Cloud Build service account deploy to B without needing excessive permissions.

First, I created a service account named deploy under B and granted it the Firebase Hosting Admin, Firebase Rules Admin, and Cloud Datastore Index Admin roles. (I'm not sure whether the Datastore role is needed, but the console showed it as being used recently so I left it.)

Next, I generated a JSON key for the new service account, pasted it (including newlines and double-quotes) as a substitution variable named _DEPLOY_CREDENTIALS, and updated the build step to copy it to the environment:

 - id: firebase_deploy
    name: gcr.io/$PROJECT_ID/firebase
    entrypoint: bash
    args: ['-e', '--', 'build/deploy_hosting.sh']
    env:
      - DEPLOY_CREDENTIALS=$_DEPLOY_CREDENTIALS
      - FIREBASE_PROJECT_ID=$_FIREBASE_PROJECT_ID
      - FIREBASE_HOSTING_TARGET=$_FIREBASE_HOSTING_TARGET

In deploy_hosting.sh, I write the credentials to a temporary file and then pass them to the firebase command via the GOOGLE_APPLICATION_CREDENTIALS environment variable:

#!/bin/bash

set -e
    
CREDS=$(mktemp -t creds.json.XXXXXXXXXX)
printenv DEPLOY_CREDENTIALS >"$CREDS"
export GOOGLE_APPLICATION_CREDENTIALS=$CREDS
      
firebase --debug use "$FIREBASE_PROJECT_ID"
firebase target:apply hosting prod "$FIREBASE_HOSTING_TARGET"
firebase deploy --project="$FIREBASE_PROJECT_ID" --only=hosting,firestore:rules

I created a separate shell script for the step since I ran into problems with quotes being stripped from the credentials when writing them directly from the build step. It would likely be possible to store the credentials in Secret Manager instead, but that felt like overkill for my use case.

I'm still curious about whether there's a way to let A's service account deploy to B without using a service account in B while running the firebase executable.

  • Related