user3472360
user3472360

Reputation: 2065

Calling a Google Cloud Function from within Python

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!

Upvotes: 15

Views: 12524

Answers (3)

Marco Cerliani
Marco Cerliani

Reputation: 22031

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

Upvotes: 12

Einfelspinsel
Einfelspinsel

Reputation: 31

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.

Upvotes: 0

JKleinne
JKleinne

Reputation: 1310

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.

Upvotes: 4

Related Questions