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.
The build process should only have access to Firebase project B
, rather than "all my Firebase data and settings" and "my Google Cloud data".
- 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. - 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.