serverless-google-cloudfunctions
serverless-google-cloudfunctions copied to clipboard
How to deploy public function on GCF?
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".
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
@Micka33 it is caused by the location field not supported anymore, please update to latest version and try again
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 withallUsers
when runningserverless deploy
.
Up
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
Does anyone know a way to setup Cloud function invoker
to allUsers
while deploying with serverless ?
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.
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?
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.
The issue is not able setIamPolicy
after deployment.
We should be able to configure IAM policy via serverless.yml; similar to AWS.
Up.
+1
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.
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.
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"
When will this be available from the npm package? I see the latest version (3.1.0) was deployed 2 months ago
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.
I've opened a PR for an alternative approach for IAM that I've tested locally and seems to work. See: https://github.com/serverless/serverless-google-cloudfunctions/pull/223
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.
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!
@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.