Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How I can get access to GCP cloud function from python code using service account?

I've deployed a simple GCP Cloud Function which returns "Hello World!". I need this function to be under authorization. I unmarked "Allow unauthenticated invocations" checkbox, so only authenticated invocations can call this code. I also created Service Account and give next roles: - Cloud Functions Invoker - Cloud Functions Service Agent

my code:

from google.oauth2 import service_account
from google.auth.transport.urllib3 import AuthorizedHttp

if __name__ == '__main__':
    credentials = service_account.Credentials.from_service_account_file('service-account.json',
        scopes=['https://www.googleapis.com/auth/cloud-platform'],
        subject='service-acc@<project_id>.iam.gserviceaccount.com')
    authed_session = AuthorizedHttp(credentials)
    response = authed_session.urlopen('POST', 'https://us-central1-<project_id>.cloudfunctions.net/main')
    print(response.data)

and I've got response:

b'\n<html><head>\n<meta http-equiv="content-type" content="text/html;charset=utf-8">\n<title>401 Unauthorized</title>\n</head>\n<body text=#000000 bgcolor=#ffffff>\n<h1>Error: Unauthorized</h1>\n<h2>Your client does not have permission to the requested URL <code>/main</code>.</h2>\n<h2></h2>\n</body></html>\n'

How to become authorized?

like image 621
Voldemort93 Avatar asked Sep 23 '26 21:09

Voldemort93


1 Answers

Your example code is generating an access token. Below is a real example that generates an identity token and uses that token to call a Cloud Functions endpoint. The Function needs to have the Cloud Function Invoker role for the service account being used for authorization.

import json
import base64
import requests

import google.auth.transport.requests
from google.oauth2.service_account import IDTokenCredentials

# The service account JSON key file to use to create the Identity Token
sa_filename = 'service-account.json'

# Endpoint to call
endpoint = 'https://us-east1-replace_with_project_id.cloudfunctions.net/main'

# The audience that this ID token is intended for (example Google Cloud Functions service URL)
aud = 'https://us-east1-replace_with_project_id.cloudfunctions.net/main'

def invoke_endpoint(url, id_token):
    headers = {'Authorization': 'Bearer ' + id_token}

    r = requests.get(url, headers=headers)

    if r.status_code != 200:
        print('Calling endpoint failed')
        print('HTTP Status Code:', r.status_code)
        print(r.content)
        return None

    return r.content.decode('utf-8')

if __name__ == '__main__':
    credentials = IDTokenCredentials.from_service_account_file(
            sa_filename,
            target_audience=aud)

    request = google.auth.transport.requests.Request()

    credentials.refresh(request)

    # This is debug code to show how to decode Identity Token
    # print('Decoded Identity Token:')
    # print_jwt(credentials.token.encode())

    response = invoke_endpoint(endpoint, credentials.token)

    if response is not None:
        print(response)
like image 50
John Hanley Avatar answered Sep 26 '26 18:09

John Hanley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!