Firebase Functions Config: hide Secret in CLI itself - firebase

I need to set a secret in my functions config but I want to make sure, that this secret cannot be accessed by anyone, even if the person has access to the firebase project and thus the cli itself.
What I mean by that is, if I set the secret in my cli, I can then retrieve this secret firebase functions:config:get. There are people who might have access to the firebase cli of this project that should not be able to access this secret.
Is there a way to achieve this?

The functions configuration you're referring to is only saved on the local machine. It will not be checked into source control. Other developers who use the CLI in the same project, but on different machines, will not be able to see that configuration.
The configuration will be available in the deployed code, however. If each developer needs a fully isolated configuration at runtime, they should each have their own project to work with.

Related

Google Secret Manager Permissions For Local Emulating of Functions

I've given the service account for the functions the necessary permissions ('Secret Manager Secret Accessor') and when deployed, the firebase functions are able to access the secrets without any problems.
However, when using firebase serve or firebase emulators:start --only functions in local development, I'm getting the following error
Unhandled error Error: 7 PERMISSION_DENIED: Permission 'secretmanager.versions.access' denied for resource
I've found in the documentation that setting export GOOGLE_APPLICATION_CREDENTIALS=pathtoserviceaccount.json is needed to be entered in the terminal, though this did also not work for me.
I would be thankful for all pointers. Cheers.
I've found the answer myself:
When the functions are emulated locally, they do not get run by the App Engine default service account per default, this needs to be enabled as well.
So I had to follow this tutorial https://firebase.google.com/docs/functions/local-shell
The App Engine default service account needs a key which can be created in the Service Accounts settings in the Google Cloud, and then
I had to enter
export GOOGLE_APPLICATION_CREDENTIALS="path/to/key.json"
in the terminal. By running then firebase emulators:start they also got permission to access the Secret Manager.
So while I was on the right track, I was exporting the wrong Service Account key, and not the one that was allowed to run access the Secret Manager.
In order to access Secret Manager from your Firebase application running with local emulator you need to add role of:
"Secret Manager Secret Accessor" to YOUR account used to authenticate with Firebase
You can verify it by running: firebase login in local CLI.
If you're already logged in, it should respond with Already logged in as [email address].
This email address is the Principal account you need to add the role to.
As you've mentioned in your question the "firebase-adminsdk" service account permissions are used on the production deployment, but not on local, unless you specify it with: export GOOGLE_APPLICATION_CREDENTIALS="path/to/key.json"
"[...] you can override secrets values by setting up a .secret.local file. This makes it easy for you to test your functions locally, especially if you don't have access to the secret value."
https://firebase.google.com/docs/functions/config-env#secrets_and_credentials_in_the_emulator
Step by step:
make sure you have the latest version of firebase-tools installed, as this feature is relatively new.
Create a file named secret.local in the root of your firebase project (along side the .firebaserc and firebase.json
add your secrets to the file, formatted the same as way as a regular .env file. e.g.
MY_SECRET_1=foo
MY_SECRET_2=bar
run the emulator firebase emulators:start
within your firebase functions, access the secrets on the process object. e.g. process.env.MY_SECRET_1
note, as far as I can tell, the secrets are only available inside the block scope of a function handler. you can't access them in the root scope of your functions JS code (if somebody finds a way to do that, please comment here as I'd love to know too)
I had the same problem and tried the solution from pureth's answer to adding local overrides, but it didn't work. What did work for me was to create the .secret.local file in the functions directory, not in the project root.
My project structure is as follows:
/
|- .firebaserc
|- firebase.json
|- package.json
|- /* ... */
|- functions/
|- .secret.local
|- package.json
|- /* ... */
So the .secret.local file needs to be placed in the directory where your functions reside and not where the .firebaserc file is.
Also, please note that the file name starts with a dot.

When configuring CI for a Firebase project, should I use a Firebase token or a GCP service account key?

When configuring CI for a Firebase project, I often see references to either a FIREBASE_TOKEN generated with firebase login:ci or a service account key that (I think) is generated by default for each project.
For my particular use case, I want to do the following:
run online tests (with Firestore) against my test project when running npm run test during my CI build
deploy that code to a different prod project if tests pass
Which one should I use?
I would recommend you to use the FIREBASE_TOKEN. As usually, tokens are better to use, as you can quickly cancel or renew in any issue that you might have it, as well it's easier to manage them a service account and to insert them in the code.
Besides that, the official Firebase documentation - Use the CLI with CI systems - indicates and teaches how to use it with the token, so it seems that indeed, using the token is the best and easier option for you to implement.

Firebase Remote Config - copy to another project

I have two projects for dev and prod. I want to be able to run a script to copy dev config to prod.
Firebase Remote Config has an API for programatically updating Remote Config. But as far as I can tell, you need to init admin with a project-specific service account. It seems like I would need two admin instances, but I'm not sure that's possible?
I'm wondering if someone has done this before and has an example script. Thanks!
See docs:
https://firebase.google.com/docs/remote-config/automate-rc
There is no Firebase Admin SDK for Flutter, so you'll have to implement this on a different platform that is supported. For a list of these platforms and instructions on setting it up, see the documentation on adding Firebase to a server.
For these platforms that the Firebase Admin SDK targets, you can create multiple instances of the FirebaseApp class, and initialize each of them with different credentials and project configuration. For examples of how to do this, see the documentation on initializing multiple apps.

Can you give blanket public access to users in a Firebase project?

I have an open-source project that uses two separate Firebase projects for a test environment and the production one.
Ultimately, I want to have other developers be able to pull down the project and actually be able to run it WITHOUT me needing to give each individual developer access.
I see a number of solutions in this question: How to add collaborators to a Firebase app?. Those all seem to require each person's email.
I understand why it maybe isn't a thing, but I am wondering if there is a way to just give access to everyone for only the test project so that contributing is super low-friction. Something similar to Firestore database rules that allow read/write in a public fashion to get started for testing.
I've tried making a new IAM account in the Google Cloud Console, and I think that partially worked for the Firebase Cloud Functions access to Admin SDK, but my collaborators get hung up trying to run firebase use <test-firebase-project> saying that they don't have access.
I see a lot of other config options for IAM, but nothing sticking out to me for this public access scenario.
Can anyone confirm this either is or isn't a thing?
Thanks!
EDIT
To add some more detail to my project...
I am using Authentication, Firestore, and Cloud Functions. The only js package I will use is the Auth one, which will be loaded from a CDN (so I believe that doesn't apply to my question).
I want to give access to people to run the Cloud Functions locally. There is a pre-build step that I have made in vanilla Node that calls a Cloud Function (running locally), which uses the Firebase Admin SDK to call my Firestore database. I then write that response to a JSON file that my front end uses.
When my collaborators pull down the project, and install the Firebase CLI, when they try to serve the Cloud Functions locally, they get hit with a "no access" type of error. I was trying to resolve this by adding a service account into the /functions directory, but apparently that didn't help.
My collaborators don't need access to the console at all. I basically just need them to be able to run the Cloud Function locally (and make sure they can't access my production Firebase project).
I am happy to add more detail, but I kind of feel like I am just rambling. Thanks again.
There is no way to grant everyone contributor access to your Firebase console. You will either have add each individual user, or create your own dashboard that uses the API to show the relevant data.

Deploy via firebase-tools API without previous login

I'm currently building an open-source microservice that makes use of Firebase Database, Hosting & Functions. The plan is to pack everything in a single binary and distribute this. So users will have a hazzle-free, "bring your own Firebase project"-solution. They'll just have to download the binary and their Firebase secret key and can then create a user and deploy the service via CLI.
The problem is, that firebase-tools require a $FIREBASE_TOKEN when deploying via its API. So users would have to install firebase-tools in order to be able to generate that token and they would also have to store it (or re-generate it frequently).
Since I would like to provide a hazzle-free experience, I'd rather generate that token myself with the help of the secret key.
The question is: is this even possible? And if yes: how??
My workaround for this is to reflect the login- and logout-commands of the Firebase-CLI on my own binary's CLI. So the user won't have to install another tool.
To get the refresh_token I then read the data from the firebase-tools-configstore, that is located in the user folder. This feels a little dirty, like accessing a private API. But I couldn't come up with a better solution. And it works.

Resources