Deploying to firebase without --token, using Service account on a pipeline - firebase

I am trying to switch from the firebase deploy whatever --token ... to use the new service account
I generated the service account json, but i don't know which command am I supposed to run now instead of the one with --token
Any ideas? Thanks

Related

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

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. this question.
The final step in the Cloud Build config used by A is the following:
- id: firebase_deploy
name: gcr.io/$PROJECT_ID/firebase
entrypoint: sh
args:
- '-c'
- |
firebase use $_FIREBASE_PROJECT_ID
firebase target:apply hosting prod $_FIREBASE_HOSTING_TARGET
firebase deploy --project=$_FIREBASE_PROJECT_ID --only=hosting,firestore:rules
I set the _FIREBASE_PROJECT_ID substitution variable to B and the _FIREBASE_HOSTING_TARGET variable to a Hosting alias that I use for the site.
When I trigger a build, it fails with the following error:
...
Step #3 - "firebase_deploy": Error: Invalid project selection, please verify project B exists and you have access.
Step #3 - "firebase_deploy":
Step #3 - "firebase_deploy": Error: Must have an active project to set deploy targets. Try firebase use --add
Step #3 - "firebase_deploy":
Step #3 - "firebase_deploy": Error: Failed to get Firebase project B. Please make sure the project exists and your account has permission to access it.
Finished Step #3 - "firebase_deploy"
I suspect that the problem may be that I'm not running the Firebase CLI's extra login step first. To do that, it seems that I would need to run firebase login:ci locally to generate a token and then pass it via the FIREBASE_TOKEN environment variable as described in the docs, but the permissions associated with the token appear to be much broader than needed:
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.)
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.

gcloud run & Firebase Admin SDK

I have deployed a JVM application to Google cloud run that uses the Firebase Admin SDK to send notifications on Firebase Cloud Messaging.
Everything works fine locally using GOOGLE_APPLICATION_CREDENTIALS. The deployed app, however, throws errors as follows:
java.lang.IllegalArgumentException: Project ID is required to access messaging service. Use a service account credential or set the project ID explicitly via FirebaseOptions. Alternatively you can also set the project ID via the GOOGLE_CLOUD_PROJECT environment variable.
I create the FirebaseMessaging instance as:
FirebaseMessaging.getInstance(
FirebaseApp.initializeApp(
FirebaseOptions.Builder().setCredentials(
GoogleCredentials.getApplicationDefault()
).build()
I have deployed the Cloud Run instance with a service account which has admin permissions for Cloud Run.
My understanding is that an application deployed to any GCP service acquires application credentials automatically. Is there a difference for the combination of Cloud Run and Firebase Admin SDK?
Any help would be much appreciated.
You have two options:
Query the cloud metadata service to find the project ID where your Cloud Run instance is deployed to. This can only be done within Cloud Run - it won't work if you're testing locally.
Make the project ID available to Cloud Run in some way during deployment.
An easy way to implement #2 is to put the project ID in the environment for the Admin SDK to automatically pick up. For example, a shell script:
service_id="your-service-id"
project_id="your-project-id"
gcloud run deploy "$service_id" \
--project "$project_id" \
--image "..." \
--platform managed \
--update-env-vars "GOOGLE_CLOUD_PROJECT=$project_id"
Note the --update-env-vars which populates GOOGLE_CLOUD_PROJECT.

Login to firebase using gcloud service account

I have functions deployed to gcloud functions and i want to configure CI/CD for deploying this functions from gitlab.
To do any operations from gitlab i need to get firebase auth token with
firebase login:ci
command.
The problem is that i need to get this token using gcloud service account, which is not displayed in browser, when i run
firebase login:ci
I have this service account data (project_id, private_key, private_key_id, etc.)
How should i authorize using this acc?
If you set an environment variable called GOOGLE_APPLICATION_CREDENTIALS as a path pointing to your service account JSON file, the Firebase CLI will automatically pick that up and use it to authorize commands. You don't need to be logged in or provide a --token argument when this is the case.
If anyone finds this and is wondering how to do it on CircleCI, this worked for me.
Generate a json file key for you service account in the GCP Console
Set the json to a CircleCI environment variable at the org level or the project level
We use one at the org level called GSA_KEY
In your workflow config, before you run the firebase command, run this command:
echo echo $GSA_KEY > "$HOME"/gcloud.json
Then run your firebase deploy command, first setting the path to GOOGLE_APPLICATION_CREDENTIALS
The deployment run looks like:
steps:
- checkout
- run:
name: Create SA key JSON
command: echo $GSA_KEY > "$HOME"/gcloud.json
- run:
name: Deploy to Firebase
command:
GOOGLE_APPLICATION_CREDENTIALS="$HOME"/gcloud.json firebase deploy [project specific stuff]
Use command:
gcloud auth activate-service-account xyz#project-id.iam.gserviceaccount.com --key-file=/path/to/file.json --project=project-id
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/file.json"
in Bash
run the following commands 1 and 2 in order
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/file.json"
"/path/to/file.json" -- the location of the file where the service account json file is saved.
npx firebase-tools deploy --json
Do not forget to use the right project when deploying like
firebase use dev or
firebase use qa
This is what worked for me:
Added the environment variable GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
firebase deploy --non-interactive # needed to bypass any prompts that might stall out a CI script.
You can also set the value of the Environment variable to be the JSON in the key file.

Firebase deploy without login

I'm trying deploy my firebase app. But when I try run 'firebase deploy', I got:
Is any way to deploy the app automatically ( without human login to dashboard) ? I care only to send on firebase security rules.
You can use firebase login:ci to work with continuous integration systems.
The command firebase login:ci will create a token, then you can use this token for deploying with:
firebase deploy --token
See the Github repo section on CI Systems for more information.

How can I get firebase deploy --email or --token parameters to work?

I'm having trouble deploying travis CI with firebase using these firebase commands:
firebase deploy --email ${FIREBASE_USERNAME} --password ${FIREBASE_PASSWORD}
firebase deploy --token ${FIREBASE_TOKEN}
It does not like --email option and it does seem that it takes --token but does not work with my firebase auth token I can get from my firebase app. What am I doing wrong?
The email option was removed in the 2.0 release of the CLI.
Use firebase login:ci to generate a token.
On a machine with a browser, install the Firebase CLI.
Run firebase
login:ci to log in and print out a new access token (the current CLI
session will not be affected).
Store the output token in a secure but accessible way in your CI system.
Another firebase deployment option in travis-ci is to use dpl (https://github.com/travis-ci/dpl) which is a deployment provider
OPTIONS
token: Your Firebase CI Access Token (generated from firebase login:ci)
project: Deloy to a different Firebase Project than specified in firebase.json
public: Specifies which directory to upload to Firebase Hosting.
ignore: Specifies the files to ignore on deploy. (similar to .gitignore)
EXAMPLE
dpl --provider=firebase --token=<token> --project=<project>
What is really cool about using this deployment provider utility is that you can deploy to one or more firebase hosted applications from a single project commit...
after_script:
- dpl --provider=firebase --token=${FIREBASE_TOKEN} --project=${PROJECT_ONE}
- dpl --provider=firebase --token=${FIREBASE_TOKEN} --project=${PROJECT_TWO}
References:
(firebase.json) https://www.firebase.com/docs/hosting/guide/full-config.html
(dpl --provider=firebase) https://github.com/travis-ci/dpl#firebase
Note: One thing you will need to consider is how you set FIREBASE_URL as a constant in each hosted application if they need to use the same code base but a separate Firebase for storing data.

Resources