Skip to content

How to deploy public function on GCF? #205

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

Open
Micka33 opened this issue Mar 30, 2020 · 20 comments
Open

How to deploy public function on GCF? #205

Micka33 opened this issue Mar 30, 2020 · 20 comments
Assignees
Labels

Comments

@Micka33
Copy link

Micka33 commented Mar 30, 2020

I can't find the answer anywhere in the documentation. Feel free to point it to me.

$> serverless
  Your Environment Information ---------------------------
     Operating System:          darwin
     Node Version:              12.13.1
     Framework Version:         1.67.0 (standalone)
     Plugin Version:            3.5.0
     SDK Version:               2.3.0
     Components Version:        2.22.3
# serverless.yml
service: my-name

provider:
  name: google
  runtime: nodejs8
  region: europe-west1
  project: project-123456
  credentials: ~/path/to/secret.json

plugins:
  - serverless-google-cloudfunctions
package:
  excludeDevDependencies: true
  exclude:
    - node_modules/**
    - .gitignore
    - .git/**

functions:
  my_name:
    handler: my_name_http
    memorySize: 128
    timeout: 60s
    events:
      - http: path
    labels:
      application: my-name
    environment:
      PROJECT_ID: ${self:provider.project}

Since the last serverless upgrade, my functions are deployed without the "Cloud function invoker" role set to "allUsers".
Screenshot 2020-03-30 at 16 55 47

By the way, I can't find anywhere in the documentation how to set it in serverless.yml.
Can you help me?

N.B.: Of course, I did set it in the Google Cloud Console UI and the function works perfectly. But then, I can no longer do serverless deploy. It displays the following error:

$> serverless deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Compiling function "my-name"...
Serverless: Uploading artifacts...
Serverless: Artifacts successfully uploaded...
Serverless: Updating deployment...
Serverless: Checking deployment update progress...
....
  Error --------------------------------------------------

  Error: Deployment failed: RESOURCE_ERROR

       {"ResourceType":"gcp-types/cloudfunctions-v1:projects.locations.functions","ResourceErrorCode":"400","ResourceErrorMessage":{"code":400,"message":"Invalid JSON payload received. Unknown name \"location\" at 'function': Cannot find field.","status":"INVALID_ARGUMENT","details":[{"@type":"type.googleapis.com/google.rpc.BadRequest","fieldViolations":[{"field":"function","description":"Invalid JSON payload received. Unknown name \"location\" at 'function': Cannot find field."}]}],"statusMessage":"Bad Request","requestPath":"https://cloudfunctions.googleapis.com/v1/projects/project-123456/locations/europe-west1/functions/my-name-dev-my-name","httpMethod":"PATCH"}}
      at throwErrorIfDeploymentFails (/Users/username/Documents/remotal/remotal-my-name/node_modules/serverless-google-cloudfunctions/shared/monitorDeployment.js:71:11)
      at /Users/username/Documents/remotal/remotal-my-name/node_modules/serverless-google-cloudfunctions/shared/monitorDeployment.js:42:17
      at processTicksAndRejections (internal/process/task_queues.js:93:5)

     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com

  Your Environment Information ---------------------------
     Operating System:          darwin
     Node Version:              12.13.1
     Framework Version:         1.67.0 (standalone)
     Plugin Version:            3.5.0
     SDK Version:               2.3.0
     Components Version:        2.22.3
@medikoo medikoo transferred this issue from serverless/serverless Mar 30, 2020
@bao1018
Copy link
Contributor

bao1018 commented Apr 1, 2020

@Micka33 it is caused by the location field not supported anymore, please update to latest version and try again

@Micka33
Copy link
Author

Micka33 commented Apr 2, 2020

I don't understand what you mean by update to latest version and try again. I already upgraded to the last version of serverless. I did so before running serverless create --......

  • What should I update to the latest version?
  • This error only occurs when I manually add a role to a google cloud function through the GCC UI and run serverless deploy.
  • I would like to understand how I can specify that I want the role Cloud function invoker set with allUsers when running serverless deploy.

@Micka33
Copy link
Author

Micka33 commented Apr 8, 2020

Up

@iSynthetica
Copy link

Have the same issue, after updated serverless and serverless-google-cloudfunctions have an error:

Error: Forbidden
Your client does not have permission to get URL /function from this server

@Micka33
Copy link
Author

Micka33 commented Apr 16, 2020

Does anyone know a way to setup Cloud function invoker to allUsers while deploying with serverless ?

@Trowsing
Copy link

Same here, only happens if you upgrade to version 3.0.0, tried downgrading to 2.4.3 and everything was working again with the correct invoker.

@mwawrusch
Copy link

It would be nice to have a fix for this. Downgrading to 2.4.3 does not work anymore as Google ended support for the previous API, so we are stuck with 3.0.0.

So what is the correct way to make a function publicly accessible with serverless?

@curtismenmuir
Copy link

I am using private cloud functions with Serverless v3.
I have setup a google cloud project which has a Gateway API (App Engine) to sit in front of the private cloud functions. To allow communication between gateway and cloud functions, I have created a Service Account with the Cloud Function Invoker permissions. The gateway will then use a JSON keyfile for that service account to generate an ID Token to be sent as bearer token in request to Cloud Functions.

@pramendra
Copy link

The issue is not able setIamPolicy after deployment.

We should be able to configure IAM policy via serverless.yml; similar to AWS.

@zenati
Copy link

zenati commented May 14, 2020

Up.

@andrx
Copy link

andrx commented May 20, 2020

+1

@nover
Copy link

nover commented May 26, 2020

Also having this problem now after upgrading to google provider 3 here - any fix in the pipeline?

edit

My fix is the following for allowing public access to my cloud function:

Create a policy.json file with the content:

{
  "bindings": [
    {
      "role": "roles/cloudfunctions.invoker",
      "members": [
        "allUsers"
      ]
    }
  ]
}

Ensure that you have the gcloud sdk installed and logged in (gcloud auth login) and then:

$ gcloud functions set-iam-policy --region={YOUR_REGION} {FUNCTION_NAME} policy.json

Updated IAM policy for function [FUNCTION_NAME].
bindings:
- members:
  - allUsers
  role: roles/cloudfunctions.invoker
etag: blah-blah
version: 1

Replacing {YOUR_REGION} and {FUNCTION_NAME} with your own appropriate values.

@frandiox
Copy link

Docs and commands to change this policy using gcloud are here: https://cloud.google.com/functions/docs/securing/managing-access-iam#allowing_unauthenticated_function_invocation

gcloud functions add-iam-policy-binding FUNCTION_NAME \
 --member="allUsers" \
 --role="roles/cloudfunctions.invoker" \
 --project=YOUR_PROJECT_ID

The previous command needs to be run once per function. New deployments work after making functions public with this command.

Apparently, an equivalent to the --allow-unauthenticated flag is missing in SLS deploy.

@kevboutin
Copy link

This was very helpful @frandiox

Here is what worked for me:

gcloud functions add-iam-policy-binding SERVICENAME-STAGE-FUNCTIONNAME \
    --member="allUsers" \
    --role="roles/cloudfunctions.invoker" \
    --project="PROJECT_ID" \
    --region="us-east1"

@buffolander
Copy link

When will this be available from the npm package? I see the latest version (3.1.0) was deployed 2 months ago

@edaniszewski
Copy link
Contributor

The changes made in the above linked PR appear to not fully work (see #222). I'm working through a solution for it, but it does seem like more work needs to be done to get the feature stable enough for a new release. I'll post an update once I make some progress.

@edaniszewski
Copy link
Contributor

I've opened a PR for an alternative approach for IAM that I've tested locally and seems to work. See: #223

@deemetree-at-satelligence
Copy link

deemetree-at-satelligence commented Jul 15, 2020

Wanted to add my two-pence based on suggestions of @frandiox @kevboutin, I managed to set it up using sls hooks using this plugin: https://www.npmjs.com/package/serverless-plugin-scripts, works pretty nice for me (I have just one function at this point) but I can imagine it might not work in all cases. Here is the snippet:

service: YOUR-SERVICE-NAME

custom:
  ...
 # this comes from https://www.npmjs.com/package/serverless-plugin-scripts
  scripts:
    commands:
      make-public: gcloud functions add-iam-policy-binding ${self:service}-${self:provider.stage}-${opt:function, "YOUR-DEFAULT-FUNCTION-NAME"} --member="allUsers" --role="roles/cloudfunctions.invoker" --project=${self:provider.project} --region=${self:provider.region} | xargs echo 
    hooks:
      'after:deploy:deploy': npx sls make-public --function=YOUR-FUNCTION-NAME
...

And then it automatically makes the specified functions public after deploy and otherwise I can run sls make-public --function=<function-name> at any time.

Cheers, maybe that helps.

cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

One this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

One this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

One this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 20, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
@cgossain
Copy link

Thanks @frandiox @kevboutin @deemetree-at-satelligence for the suggestions!

I put together a little script that combines the above by running through all the functions defined in serverless.yml and updates their IAM policy.

The script looks for a parameter allowUnauthenticated: true within each function definition to determine if the function should be made public (otherwise it's private). This is of course an "unofficial" parameter that was suggested in #223, so until the PR is merged this seems like an unobtrusive workaround.

#!/bin/bash

# Get a list of functions in the serverless.yml file and format as args
functions=$(sls print --path functions --transform keys --format text | xargs)

# Sort functions as public and private
pub=()
prv=()
for fn in ${functions[@]}; do
    # if the `allowUnauthenticated: true` flag is defined for the function flag it to be made public
    if [[ "$(sls print --path functions."$fn" --format yaml | xargs)" == *"allowUnauthenticated: true"* ]]; then
        pub+=($fn)
    else
        prv+=($fn)
    fi
done

# Run the mkfunc-pub command for each public function
for fn in ${pub[@]}; do
    echo "Making function \""$fn"\" public..."
    npx sls mkfunc-pub --function="$fn"
done

# Run the mkfunc-pvt command for each private function
for fn in ${prv[@]}; do
    echo "Making function \""$fn"\" private..."
    npx sls mkfunc-pvt --function="$fn"
done

I've also put together a Serverless Google Functions Starter Project for Golang that includes all this.

Hopefully it helps someone!

cgossain added a commit to cgossain/serverless-template-golang-google-cloud-functions that referenced this issue Nov 21, 2020
Shout out to this post for pointing out this workaround:
serverless/serverless-google-cloudfunctions#205 (comment)

Once this is natively supported in the serverless-google-cloudfunctions plugin, the serverless.yml file should be updated accordingly.
@J-Rojas
Copy link

J-Rojas commented May 12, 2021

@deemetree-at-satelligence Great workaround! For anyone trying this with a service account, make sure that your service account has the 'Security Admin' Role set, otherwise you'll get a 403 error on the scripted IAM policy update command.

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

No branches or pull requests