如何使用服务帐户从 python 代码访问 GCP 云功能?
How I can get access to GCP cloud function from python code using service account?
我已经部署了一个简单的 GCP Cloud Function returns "Hello World!"。
我需要这个功能得到授权。我取消标记 "Allow unauthenticated invocations" 复选框,因此只有经过身份验证的调用才能调用此代码。
我还创建了服务帐户并赋予了下一个角色:
- 云函数调用器
- 云功能服务代理
我的代码:
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)
我收到了回复:
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'
如何获得授权?
错误是因为调用未经过身份验证。
因为现在的呼叫来自您的本地主机 this 应该适合您。
curl https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME \
-H "Authorization: bearer $(gcloud auth print-identity-token)"
这将从本地主机使用您在 gcloud 上激活的帐户进行调用。
进行调用的帐户必须具有角色 Cloud Functions Invoker
以后只要确保调用此函数的服务具有上述作用即可。
您的示例代码正在生成访问令牌。下面是一个生成身份令牌并使用该令牌调用 Cloud Functions 端点的真实示例。该函数需要具有用于授权的服务帐户的 Cloud Function Invoker 角色。
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)
您需要获得身份令牌才能 (http) 触发您的云功能并且
您的服务帐户至少需要具有 Cloud Functions Invoker 角色。
(为了尽可能保证它的安全,请创建一个只能调用云功能的服务帐户,不能调用其他任何东西 -> 以避免在您的服务帐户密钥文件落入坏人之手时出现问题。)
然后您可以运行以下内容:
import os
import google.oauth2.id_token
import google.auth.transport.requests
import requests
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'service_account_key_file.json'
google_auth_request = google.auth.transport.requests.Request()
cloud_functions_url = 'https://europe-west1-your_project_id.cloudfunctions.net/your_function_name'
id_token = google.oauth2.id_token.fetch_id_token(
google_auth_request, cloud_functions_url)
headers = {'Authorization': f'Bearer {id_token}'}
response = requests.get(cloud_functions_url, headers=headers)
print(response.content)
这个问题+答案也对我有帮助:
How can I retrieve an id_token to access a Google Cloud Function?
如果您需要通过 python 的访问令牌(而不是身份令牌),请在此处查看:
我已经部署了一个简单的 GCP Cloud Function returns "Hello World!"。 我需要这个功能得到授权。我取消标记 "Allow unauthenticated invocations" 复选框,因此只有经过身份验证的调用才能调用此代码。 我还创建了服务帐户并赋予了下一个角色: - 云函数调用器 - 云功能服务代理
我的代码:
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)
我收到了回复:
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'
如何获得授权?
错误是因为调用未经过身份验证。
因为现在的呼叫来自您的本地主机 this 应该适合您。
curl https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME \
-H "Authorization: bearer $(gcloud auth print-identity-token)"
这将从本地主机使用您在 gcloud 上激活的帐户进行调用。
进行调用的帐户必须具有角色 Cloud Functions Invoker
以后只要确保调用此函数的服务具有上述作用即可。
您的示例代码正在生成访问令牌。下面是一个生成身份令牌并使用该令牌调用 Cloud Functions 端点的真实示例。该函数需要具有用于授权的服务帐户的 Cloud Function Invoker 角色。
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)
您需要获得身份令牌才能 (http) 触发您的云功能并且
您的服务帐户至少需要具有 Cloud Functions Invoker 角色。
(为了尽可能保证它的安全,请创建一个只能调用云功能的服务帐户,不能调用其他任何东西 -> 以避免在您的服务帐户密钥文件落入坏人之手时出现问题。)
然后您可以运行以下内容:
import os
import google.oauth2.id_token
import google.auth.transport.requests
import requests
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'service_account_key_file.json'
google_auth_request = google.auth.transport.requests.Request()
cloud_functions_url = 'https://europe-west1-your_project_id.cloudfunctions.net/your_function_name'
id_token = google.oauth2.id_token.fetch_id_token(
google_auth_request, cloud_functions_url)
headers = {'Authorization': f'Bearer {id_token}'}
response = requests.get(cloud_functions_url, headers=headers)
print(response.content)
这个问题+答案也对我有帮助:
How can I retrieve an id_token to access a Google Cloud Function?
如果您需要通过 python 的访问令牌(而不是身份令牌),请在此处查看: