What service account roles to deploy a scheduled Cloud Function? - firebase

To deploy my Firebase project, I have setup a service account with the roles:
Cloud Functions Admin
Firebase Admin
Service Account User
It works fine with Hosting and Cloud Functions triggered by Firestore or HTTPS, but it fails with a function on schedule.
What additional role do I need?
Edit: the only related ouput messages are:
i functions: updating Node.js 14 function schedule-statistics(europe-west3)...
...
✔ functions[schedule-statistics(europe-west3)]: Successful update operation.
...
Functions deploy had errors with the following functions:
schedule-statistics(europe-west3)
Edit: additional test: when deploying using my logged-in CLI on my machine, I see this additional message, which is missing when deploying with the service account:
✔ functions[schedule-statistics(europe-west3)]: Successful upsert schedule operation.
Edit: by adding logs as suggested by #Dharmaraj, I can see the missing permissions:
The principal (user or service account) lacks IAM permission \"cloudscheduler.jobs.get\"
...
The principal (user or service account) lacks IAM permission \"cloudscheduler.jobs.update\"
So when adding the "Cloud Scheduler Admin", it works!
I was misled because I already set this role to the service account but within another project, and it does not propagate! Lesson learned at the expense of a nice afternoon.

The answer is: add role "Cloud Scheduler Admin".
The gotcha is: roles set to a service account in one project do not propagate to the same service account in other project.
The nice lesson is: add --debug to see additional logs, including missing permissions, thanks #Dharmaraj

Related

If I already have Cloud Functions Admin role, why do I need Cloud Functions Invoker role to run cloud functions?

I have been assigned Cloud Functions Admin role in the IAM permissions settings. I have created a cloud function callable by HTTP. When I make the request it throws
Error: Forbidden
Your client does not have permission to get URL /<function name> from this server.
Apparently I have to add the Cloud Functions Invoker role to be able to call cloud functions, but this seems unnecessary since I'm already a Cloud Functions Admin, whose permissions surely encompass any held within Cloud Functions Invoker.
Is this strange behavior correct or have I taken a wrong turn?
I have now added Owner role aswell as Cloud Functions Admin and it still throws the same 403.
I have updated my CLI using npm install -g firebase-tools - now on v11.8.0.
I have added allUsers principal to have Cloud Functions Invoker.
I have checked any errors logged in the console and gcf-artifacts has failed as the Artifact Registry API is not active. Please enable the API and try again. - however when I check if the Artifact Registry API is enabled, it is.
I am now attempting to enable unauthenticated HTTP function invocation using this article however I can't find the Configuration panel within the google cloud console.
If you are experiencing the same issue and have already completed all of my troubleshooting above, delete your cloud function and redeploy it.
It's that simple.

Previous GCP service account being used when deploying Firebase Functions despite passing updated service account info to admin.initializeApp

I am switching my Firebase functions from one Firebase account to another.
I have rerun firebase init.
I have added the new service account configs to the project and am passing it to admin.initializeApp. I have logged into GCP via my CLI and have run firebase login:ci as well.
Despite all this, whenever I try to run firebase deploy, I am met with the error:
Missing permissions required for functions deploy. You must have permission iam.serviceAccounts.ActAs on service account #appspot.gserviceaccount.com.
Any idea what's going on here?
This doesn't have anything to do with the service account you use to initialize the Firebase Admin SDK. The error has to do with the lack of permission of the Google Account that you used to sign in with the Firebase CLI. It doesn't have permission to deploy to Cloud Functions. You should either sign out then sign back in with an account that has permission (typically "editor" role), or add the appropriate permission to the account that you want to use.
If you're migrating to a new Firebase project / account, you must delete the project's existing .firebaserc and firebase.json files before running firebase init - this will ensure that you're using the updated project configs.

Firebase hosting deploy with serviceaccount fails with 403

I'm trying to deploy a Firebase hosted project with a Service Account (that I created myself, not one provided by Google/Firebase as default) via a pipeline (Gitlab, but that shouldn't matter for this issue).
When I run the following command locally (same happens in the pipeline):
GOOGLE_APPLICATION_CREDENTIALS="/path/to/serviceaccount.json" firebase deploy --only hosting
I'm getting the following error:
=== Deploying to 'my-firebase-project'...
i deploying hosting
Error: HTTP Error: 403, The caller does not have permission
The --debug does not provide any more details, other than the 403. I've set the following roles to the serviceaccount:
Firebase Hosting Admin
Firebase Rules Admin
API keys viewer
Deploying the rules (using --only firestore) works without issues. I've read the documentation about the roles of Firebase hosting, but assigning these don't work either.
Does anyone know which roles I'm missing?
Note: a service account is used here to do a deployment, so any firebase login / firebase logout actions won't have any effect. See Login to firebase using gcloud service account for details.
With the help of Firebase support, I was pointed to the Deploying to Firebase page, which provides an enumeration of all required roles. To sum it up here:
Cloud Build Service Account
Firebase Admin
API Keys Admin
I was missing the first one, which resulted in this error. Hope that this'll help others as well!
You have to add the role at the cluster level using oadm policy add-cluster-role-to-user cluster-reader system:serviceaccount:myproject:default

Proper permission for Cloud Build to deploy to Firebase?

Permissions recommended for the Cloud Build service account in the official Google documentation and the Firebase CLI community builder docs are insufficient:
In the permissions table, locate the email ending with #cloudbuild.gserviceaccount.com, and click on the pencil icon.
Add Cloud Build Service Account, Firebase Admin and API Keys Admin roles.
I still get the following error in Cloud Build when I do firebase deploy:
Error: HTTP Error: 403, The caller does not have permission
What I've tried is different Firebase IAM roles, Editor, and Owner. So far only the Owner role works. That is way too much privilege for a Cloud Build service account, and violates the least-privilege model.
Everything is in the same Google Cloud project.
Anyone know how to troubleshoot this? Or know which role/permission is missing?
For our project (which uses Firestore, Functions, Hosting, and Storage extensively) here is the list we came up with. Critically I wanted to avoid "Firebase Admin" because I did not want this service account to have access to read/write my Firestore data:
Artifact Registry Administrator
Cloud Build Service Account
Cloud Datastore Index Admin
Cloud Functions Admin
Cloud RuntimeConfig Admin
Cloud Scheduler Admin
Firebase Hosting Admin
Firebase Rules Admin
Pub/Sub Admin
Service Account User
tl;dr seems like it was "an accidental permission expansion" that has been corrected.
I am able restrict the roles to:
Cloud Build Service Account
Firebase Admin
API Keys Admin

Can't run Firebase Test Lab tests using gcloud and service account: 403, does not have storage.objects.create

I am trying to run instrumented tests using the glcoud CLI as a service account in CircleCi. When I run:
gcloud config set project project-name-12345
gcloud auth activate-service-account firebase-testlab-serviceuser#project-name-12345.iam.gserviceaccount.com --key-file ${HOME}/client-secret.json
gcloud firebase test android run --type instrumentation --app debug-app.apk --test debug-test.apk --device model=Nexus6P,version=27,locale=en,orientation=portrait --environment-variables coverage=true,coverageFile=/sdcard/tmp/code-coverage/connected/coverage.ec --directories-to-pull=/sdcard/tmp --timeout 20m
I get:
ERROR: (gcloud.firebase.test.android.run) Could not copy [debug-app.apk] to [gs://test-lab-xxxxxxxx-yyyyyyyy/2018-01-18_17:14:09.964449_zPAw/] ResponseError 403: firebase-testlab-serviceuser#project-name-12345.iam.gserviceaccount.com does not have storage.objects.create access to bucket test-lab-xxxxxxxx-yyyyyyyy..
Using the API Console (https://console.cloud.google.com/iam-admin/iam/project) I've given my service user all the permission I can think would be relevant:
Firebase Crash Symbol Uploader
Firebase Test Lab Admin
Storage Admin
Storage Object Admin
Storage Object Creator
Storage Object Viewer
Firebase Rules System
Any help would be greatly appreciate. Thanks.
You should be able to use a service account created in the Google Cloud Console. Did your service account have the required project Editor role? (as noted in this doc: https://firebase.google.com/docs/test-lab/continuous)
After lots of clicking through the Firebase console and the Google Cloud Console, reading SO, asking for help on Slack, and more trial and error than I care to admit, I discovered that the Firebase console has a service account page:
https://console.firebase.google.com/u/0/project/project-name-12345/settings/serviceaccounts/adminsdk
That is different from the service accounts page in the Google Cloud Console
https://console.cloud.google.com/iam-admin/serviceaccounts/project?project-name-12345
It turns out you want the Firebase service account, you can not create one via the cloud console. Super, super annoying.
The steps I took to create the key is as follow:
1. Firebase Console https://console.firebase.google.com/
2. Project Settings
3. "Service Accounts" tab
4. Inside "Service Accounts" panel, Firebase Admin SDK
5. At the bottom of "Firebase Admin SDK" panel, "Generate new private key"
This is what Etherton answered
https://stackoverflow.com/a/48327579/2353939
Even after that, I still had some errors. So, I added a bunch of roles as follows.
Firebase Test Lab Admin
Firebase Service Management Service Agent
Firebase Admin SDK Administrator Service Agent
Service Account Token Creator
Storage Object Creator
That also didn't fix. So, finally, I applied P. Davis answer by adding Editor role to the service account.
https://stackoverflow.com/a/48331465/2353939
Steps to add Editor role is as follows
1. Go to google cloud console https://console.cloud.google.com/iam-admin/iam
2. Go into "IAM"
3. Use "client_email" from the json file downloaded from firebase console to find the service account you need to edit
4. Click the "Edit" icon on the right
5. Scroll down and "Add Another Role"
6. Click the input field and type in "Editor" to search
7. Choose the one with subtitle "Edit access to all resource"
8. Save
9. Now you should be able to use it
This is the list of the roles that I put in to my service account :
Firebase - Firebase admin ( I think this is overkill. I might update it later )
Project - Editor
Storage - Storage Object Creator
It does not matter whether you create the service account from Firebase or google cloud console. As long as you have these roles in your service account then you should be able run the Firebase test lab.
For people who stumble upon this and don't want to use the all powerful Project Editor role, here are the roles I'm using for my service account:
Firebase Test Lab Roles
I think the Firebase Analytics Viewer role is not necessary, because it mostly just execute the tests. To view the result we use the developer accounts instead but haven't tried removing it.
We ran into the same permissions issue with storage.objects.create. We have added all the roles that were mentioned here, except for the Editor role which we wanted to avoid, but it still failed. We were using a Service Account and it definitely had the proper permissions.
In the end our workaround was to setup a cloud storage bucket manually and then use it in the --results-bucket argument for gcloud. See the documentation here. That finally fixed it for us.

Resources