Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

firebase CLI 10.3.1 does not issue calls to make callable functions public #4327

Closed
taeold opened this issue Mar 18, 2022 · 12 comments
Closed

Comments

@taeold
Copy link
Contributor

taeold commented Mar 18, 2022

I'm also having this issue Using firebase CLI 10.3.1 and on deploying a new function, it is always deployed in a way that causes it to return 403 when triggered using the firebase SDK firebaseFunctions().httpsCallable(). My fix so far has been to edit it in the console to 'Allow Unauthenticated', but it would like to avoid that if it's supposed to work differently.

I'm running firebase deploy locally, logged in as the account owner, so I doubt it is a permissions issue. The debug log has these lines early on:

[debug] [2022-03-18T10:20:59.704Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[debug] [2022-03-18T10:20:59.705Z] > authorizing via signed-in user ([REMOVED])
[debug] [2022-03-18T10:20:59.705Z] [iam] checking project [REMOVED] for permissions ["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","datastore.indexes.create","datastore.indexes.delete","datastore.indexes.list","datastore.indexes.update","firebase.projects.get","firebaserules.releases.create","firebaserules.releases.update","firebaserules.rulesets.create"]
[debug] [2022-03-18T10:20:59.708Z] >>> [apiv2][query] POST https://cloudresourcemanager.googleapis.com/v1/projects/[REMOVED]:testIamPermissions [none]
[debug] [2022-03-18T10:20:59.708Z] >>> [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/[REMOVED]:testIamPermissions {"permissions":["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","datastore.indexes.create","datastore.indexes.delete","datastore.indexes.list","datastore.indexes.update","firebase.projects.get","firebaserules.releases.create","firebaserules.releases.update","firebaserules.rulesets.create"]}
[debug] [2022-03-18T10:21:00.373Z] <<< [apiv2][status] POST https://cloudresourcemanager.googleapis.com/v1/projects/[REMOVED]:testIamPermissions 200
[debug] [2022-03-18T10:21:00.374Z] <<< [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/[REMOVED]:testIamPermissions {"permissions":["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","datastore.indexes.create","datastore.indexes.delete","datastore.indexes.list","datastore.indexes.update","firebase.projects.get","firebaserules.releases.create","firebaserules.releases.update","firebaserules.rulesets.create"]}
[debug] [2022-03-18T10:21:00.375Z] >>> [apiv2][query] POST https://iam.googleapis.com/v1/projects/[REMOVED]/serviceAccounts/[REMOVED]@appspot.gserviceaccount.com:testIamPermissions [none]
[debug] [2022-03-18T10:21:00.375Z] >>> [apiv2][body] POST https://iam.googleapis.com/v1/projects/[REMOVED]/serviceAccounts/[REMOVED]@appspot.gserviceaccount.com:testIamPermissions {"permissions":["iam.serviceAccounts.actAs"]}
[debug] [2022-03-18T10:21:00.591Z] <<< [apiv2][status] POST https://iam.googleapis.com/v1/projects/[REMOVED]/serviceAccounts/[REMOVED]@appspot.gserviceaccount.com:testIamPermissions 200
[debug] [2022-03-18T10:21:00.591Z] <<< [apiv2][body] POST https://iam.googleapis.com/v1/projects/[REMOVED]/serviceAccounts/[REMOVED]@appspot.gserviceaccount.com:testIamPermissions {"permissions":["iam.serviceAccounts.actAs"]}

What should I be looking for in the (copious) logs that show the allUsers permission being granted or at least attempted? I can't find that string anywhere, so assume it's not a literal.

Originally posted by @dsl101 in firebase/firebase-functions#1015 (comment)

@taeold taeold transferred this issue from firebase/firebase-functions Mar 18, 2022
@brianmhunt
Copy link

brianmhunt commented Mar 18, 2022

Just confirming we're experiencing this with firebase-tools: "^10" (i.e. the latest). The breakage is spontaneous in our CI (i.e. not a code change on our end), just noticed today.

Noting that when we deployed the region of the function changed from us-central to northamerica-northeast.

@chrisbrown-io
Copy link
Contributor

I'm having the same problem. Seems like rolling back to 10.2.2 temporarily fixes the problem.

@dsl101
Copy link

dsl101 commented Mar 18, 2022

Seems 10.3 might not have quite been baked :) Fingers crossed the fix is as quick as for #4307

@chrisbrown-io
Copy link
Contributor

After a bit of digging, I think I've come to the conclusion that this is due to the implementation of handling callable functions seperately to https functions, as introduced in #4310.

In 10.2.2 (which works as expected) callable functions would have the httpsTrigger attribute set, which in v10.3.1 was changed to handle callable functions seperately and set a callableTrigger attribute instead.

As a result, this means that within calls to both the createV1Function and updateV1Function methods, the backend.isHttpsTriggered(endpoint) condition will always return false, as the httpsTrigger attribute is missing on the endpoint. This means the invoker won't be copied (or set to "public" by default).

Could a fix be as simple as adding an or condition, with a call to isCallableTriggered in addition to the isHttpsTriggered?

if (backend.isHttpsTriggered(endpoint) || backend.isCallableTriggered(endpoint)) {
      const invoker = endpoint.httpsTrigger.invoker || ["public"];
      ...
}

I heavily caveat that this is based on my naive knowledge of this being the first time I've looked through the source for firebase-tools, so this conclusion may very well be incorrect.

Happy to make this change if the opinion is this is a valid fix 👍

@taeold
Copy link
Contributor Author

taeold commented Mar 18, 2022

@chrisbrown-io Nice! I've been working on a fix, but if you are interested in contributing, I'd be happy to help.

Your suggested fix is exactly what I was doing. Only thing I'd add is to add test cases to fabricator.spec.ts to avoid this kind of regression in the future.

Let me know if this is something you can do soon. I don't want to have you "work" over the weekend, but I'd love to get a fix out asap, so if you think you won't have time today/this weekend, then I might just take it.

@chrisbrown-io
Copy link
Contributor

chrisbrown-io commented Mar 18, 2022

@taeold - sure, it would be good to contribute. I don't mind taking a look at all and I have time to look at this now. However, If you're close to having a fix implemented then feel free to finish it – I don't want to hinder things!

Quick questions I would have about a fix implementation (now I've given it a bit more thought):

  1. It seems a though adding an additional else if is probably more sensible than adding an additional condition, following on the patterns in the rest of the file?
  2. Following the above point – currently, the invoker is either specified within the httpsTrigger.invoker attribute, or defaults to "public". As a callable function will never have this set, is it safe to just default to "public" in all cases for callable functions? This would go against the documentation perhaps ? Misread docs, my bad. I guess this is suggesting everything >= 7.7.0 will be public?
  3. I presume the same logic applies to both the create and update methods?
  4. In what instances are the V2 method(s) called? In my testing, it seems as though in my case, the V1 methods are only every called, although both would need updating.

@taeold
Copy link
Contributor Author

taeold commented Mar 18, 2022

  1. Yes, else if is should work
  2. Yes, callables should always be made public w/o option to configure it otherwise.
  3. No changes to on update - we don't try to change settings on update to respect changes you've made outside the Firebase CLI.
  4. V2 methods are used in not-so-secret CF3v2 functions. I'd suggest adding the change anyway even if you can't trigger the code path :p

taeold added a commit that referenced this issue Mar 18, 2022
@chrisbrown-io
Copy link
Contributor

Great - thanks for the feedback! On it now. Will have a PR up shortly and will add yourself to review 👍

@taeold
Copy link
Contributor Author

taeold commented Mar 18, 2022

BTW - I added the test cases for the change here:

68bb952

There is one more bug that this test catches - I'll leave it as an exercise for you to find out haha!

Again, thank you so much for your help!

taeold pushed a commit that referenced this issue Mar 19, 2022
Implemented fix for issue introduced in `v10.3.0` where callable functions were not having their `invoker` property correctly set to `"public"` that would in turn cause access issues with the deployed functions (as detailed in #4327).

Will also fix issues such as #3965, that are presumably cause by version mismatches/upgrades introducing this issue.

Fixes issue by adding specific handling for callable functions and always setting the `invoker` to `"public"`.

Also fixed issue with `taskQueueTrigger` endpoints calling wrong method/passing wrong args when trying to set invoker.
@taeold
Copy link
Contributor Author

taeold commented Mar 21, 2022

Fix released in 10.4.1! Thank you @chrisbrown-io !

@taeold taeold closed this as completed Mar 21, 2022
tohhsinpei pushed a commit that referenced this issue Mar 23, 2022
Implemented fix for issue introduced in `v10.3.0` where callable functions were not having their `invoker` property correctly set to `"public"` that would in turn cause access issues with the deployed functions (as detailed in #4327).

Will also fix issues such as #3965, that are presumably cause by version mismatches/upgrades introducing this issue.

Fixes issue by adding specific handling for callable functions and always setting the `invoker` to `"public"`.

Also fixed issue with `taskQueueTrigger` endpoints calling wrong method/passing wrong args when trying to set invoker.
@dsl101
Copy link

dsl101 commented Jun 24, 2022

No need (I think) to reopen, but I've just had this happen again on CLI 11.0.1. I just deployed a set of functions to a different project, and all the new ones were deployed without public invoker.

I upgraded the CLI to 11.1.0, deleted the functions, and redeployed, and all seems OK. But I don't see any mention of this in the changelog or comparing those 2 versions...

Anyway, just wanted to log it here, in case anyone was on 11.0.1 still.

@kitfit-dave
Copy link

Sorry to again resurrect this, but I am seeing a similar issue with 11.25.1

Deploying an https.onCall function "sometimes" does not end up with allUsers granted Cloud Functions Invoker. Deleting the function and re-deploying "sometimes" fixes it. I have not seen it get changed once it is right (or wrong), but it seems to be a toss-up whether it will get set public or private on first deploy. No error message in the function logs that I have seen.

Note: I am deploying to 'australia-southeast1' but that may or may not be pertinent information.
(If it's preferable for me to open a new ticket I will do that, though having finally found this ticket I thought it seemed like I should just comment here.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants