15

I'm trying to call a Google Cloud function from within Python using the following:

import requests
url = "MY_CLOUD_FUNCTON_URL"
data = {'name': 'example'}
response = requests.post(url, data = data)

but I get back the error: Your client does not have permission to get URL MY_CLOUD_FUNCTON from this server

Does anyone know how I can avoid this error? I am assuming I should be passing credentials as part of the request somehow?

Also note that if I instead try to call the function via gcloud from the command line like the below then it works, but i want to do this from within python

gcloud functions call MY_CLOUD_FUNCTON --data '{"name": "example"}' 

Any help would be really appreciated!

0

3 Answers 3

13

Given a working Cloud Function in HTTP mode which requires authentication in order to be triggered.

You need to generate an authentication token and insert it in the header as shown below:

import os
import json
import requests
import google.oauth2.id_token
import google.auth.transport.requests

os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = './my-service-account.json'
request = google.auth.transport.requests.Request()
audience = 'https://mylocation-myprojectname.cloudfunctions.net/MyFunctionName'
TOKEN = google.oauth2.id_token.fetch_id_token(request, audience)

r = requests.post(
    audience, 
    headers={'Authorization': f"Bearer {TOKEN}", "Content-Type": "application/json"},
    data=json.dumps({"key": "value"})  # possible request parameters
)
r.status_code, r.reason
Sign up to request clarification or add additional context in comments.

Comments

4

You have a few options here. Either open the function to the public so that anyone can call it or take the more secure route, albeit necessitating a bit more steps. I will cover the 2nd option since it's the one I would suggest for security reasons, but should you be satisfied with simply opening the function to the public ( which is especially useful if you are trying to create a public endpoint after all ), see this documentation.

If you want to limit who can invoke your GCF however, you would have to perform a few more steps.

  1. Create a service account and give it the Cloud Functions Invoker role ( if you simply want to restrict it's permissions to only invoke the GCF )
  2. After you assign the Service Account a role(s), the next page will give you the option to create a key
  3. After creating the Service Account Key and downloading it as credentials.json, the next step is straightforward. You would simply populate the environment variable GOOGLE_APPLICATION_CREDENTIALS with the path to the credentials.json file.

Once these steps are done, you can simply invoke the GCF as you did before, only this time, it will invoke it as the service account that you created, which contained all the permissions necessary to invoke a GCF.

1 Comment

Google doesn't recommend doing it this way, though, because then you have your key lying around. "Service account keys could pose a security risk if compromised. We recommend you avoid downloading service account keys and instead use the Workload Identity Federation."
0

This may be obvious to many, but to add to Marco's answer (I can't comment yet):

Make sure to install the google-auth package, not the google package. More details in the documentation and the requirements.txt for the code on GitHub.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.