Google cloud platform 如何使用服务帐户从python代码访问GCP云函数?

Google cloud platform 如何使用服务帐户从python代码访问GCP云函数?,google-cloud-platform,google-cloud-functions,service-accounts,google-iam,google-cloud-iam,Google Cloud Platform,Google Cloud Functions,Service Accounts,Google Iam,Google Cloud Iam,我部署了一个简单的GCP云函数,它返回“Hello World!”。 我需要这个功能得到授权。我取消标记了“允许未经身份验证的调用”复选框,因此只有经过身份验证的调用才能调用此代码。 我还创建了服务帐户并指定了下一个角色: -云函数调用程序 -云功能服务代理 我的代码: from google.oauth2 import service_account from google.auth.transport.urllib3 import AuthorizedHttp if __name__ ==

我部署了一个简单的GCP云函数,它返回“Hello World!”。 我需要这个功能得到授权。我取消标记了“允许未经身份验证的调用”复选框,因此只有经过身份验证的调用才能调用此代码。 我还创建了服务帐户并指定了下一个角色: -云函数调用程序 -云功能服务代理

我的代码:

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)

如何获得授权

该错误是由于未对调用进行身份验证

由于这些调用现在来自本地主机,因此应该适合您

curl https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME \
  -H "Authorization: bearer $(gcloud auth print-identity-token)"
这将从本地主机使用您在gcloud上的活动帐户进行呼叫

进行调用的帐户必须具有角色云函数调用者


以后只需确保调用此函数的服务具有上述角色。

错误是因为调用未经过身份验证

由于这些调用现在来自本地主机,因此应该适合您

curl https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME \
  -H "Authorization: bearer $(gcloud auth print-identity-token)"
这将从本地主机使用您在gcloud上的活动帐户进行呼叫

进行调用的帐户必须具有角色云函数调用者


以后只需确保调用此函数的服务具有上述角色。

您的示例代码正在生成访问令牌。下面是一个生成标识令牌并使用该令牌调用云函数端点的真实示例。对于用于授权的服务帐户,该函数需要具有云函数调用器角色

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)

您的示例代码正在生成访问令牌。下面是一个生成标识令牌并使用该令牌调用云函数端点的真实示例。对于用于授权的服务帐户,该函数需要具有云函数调用器角色

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)

您试图从何处调用函数?有许多选项取决于您的答案:您的代码正在生成和发送OAuth访问令牌。您需要生成并发送一个标识令牌。错误是因为调用方未经过身份验证,而且我看到您正在部署的代码是生成访问令牌。通常在生成访问令牌的地方都有公共访问权,您想做什么?谢谢@DustinIngram。我正试图从本地实例调用它。将来,它将被其他服务调用。@JohnHanley是的,我想使用OAuth令牌。因为若我并没有弄错的话,我需要在每次调用函数时生成标识令牌,因为它被更改了。我希望OAuth能自动完成。你想从哪里调用这个函数?有许多选项取决于您的答案:您的代码正在生成和发送OAuth访问令牌。您需要生成并发送一个标识令牌。错误是因为调用方未经过身份验证,而且我看到您正在部署的代码是生成访问令牌。通常在生成访问令牌的地方都有公共访问权,您想做什么?谢谢@DustinIngram。我正试图从本地实例调用它。将来,它将被其他服务调用。@JohnHanley是的,我想使用OAuth令牌。因为若我并没有弄错的话,我需要在每次调用函数时生成标识令牌,因为它被更改了。我希望OAuth能自动完成。