从 Cloud Function 到 App Engine 的请求 returns 错误 401
Requests from Cloud Function to App Engine returns error 401
我正在尝试从 Cloud Function 向部署在默认 GAE 服务上的几个 App Engine 端点发送请求。我的代码很简单:
云函数
main.py
import logging
import requests
def main(event, context):
bucketname = event['bucket']
filename = event['name']
endpoint = # Some logic extracting the endpoint to be used
url = 'https://myproject.ew.r.appspot.com/{}'.format(endpoint)
data = {
'bucketname': bucketname,
'filename': filename
}
r = requests.post(url, json=data)
logging.info(r)
return str(r)
Cloud Functions 部署为:
gcloud functions deploy storage_to_gae --runtime python37 --trigger-resource $BUCKETNAME --trigger-event google.storage.object.finalize --region $REGION --source gcf/ --entry-point main --service-account cf-sa@myproject.iam.gserviceaccount.com
Fuction 使用的服务帐户已授予服务帐户用户 (roles/iam.serviceAccountUser
) 角色。
应用引擎
app.yml
runtime: python37
service: default
但是,请求没有到达 App Engine,因为 GAE 服务上没有日志。请求返回 <Response [401]>
错误代码,因此 CF 似乎无法访问 App Engine 服务。
我需要什么额外的角色来提供我的 cf-sa@myproject.iam.gserviceaccount.com
服务帐户?我正在客户端环境中部署,所以我的权限有限,我必须询问所需的确切角色。
在询问我客户的 GCP 团队后,他们使用 IAP 来管理访问。
我按照 this 文档中的说明进行操作,并且能够向 GAE 端点发送请求。
这是我的最终代码:
import requests
from google.oauth2 import id_token
from google.auth.transport.requests import Request
def make_iap_request(url, client_id, method='POST', **kwargs):
"""Makes a request to an application protected by Identity-Aware Proxy.
Args:
url: The Identity-Aware Proxy-protected URL to fetch.
client_id: The client ID used by Identity-Aware Proxy.
method: The request method to use
('GET', 'OPTIONS', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE')
**kwargs: Any of the parameters defined for the request function:
https://github.com/requests/requests/blob/master/requests/api.py
If no timeout is provided, it is set to 90 by default.
Returns:
The page body, or raises an exception if the page couldn't be retrieved.
"""
# Set the default timeout, if missing
if 'timeout' not in kwargs:
kwargs['timeout'] = 90
# Obtain an OpenID Connect (OIDC) token from metadata server or using service
# account.
open_id_connect_token = id_token.fetch_id_token(Request(), client_id)
# Fetch the Identity-Aware Proxy-protected URL, including an
# Authorization header containing "Bearer " followed by a
# Google-issued OpenID Connect token for the service account.
resp = requests.request(
method, url,
headers={'Authorization': 'Bearer {}'.format(
open_id_connect_token)}, **kwargs)
return resp.text
def main(event, context):
bucketname = event['bucket']
filename = event['name']
endpoint = # Some logic extracting the endpoint to be used
url = 'https://myproject.ew.r.appspot.com/{}'.format(endpoint)
data = {
'bucketname': bucketname,
'filename': filename
}
client_id = 'myclientid'
r = make_iap_request(url, client_id, 'POST', json=data)
logging.info(r)
return str(r)
我正在尝试从 Cloud Function 向部署在默认 GAE 服务上的几个 App Engine 端点发送请求。我的代码很简单:
云函数
main.py
import logging
import requests
def main(event, context):
bucketname = event['bucket']
filename = event['name']
endpoint = # Some logic extracting the endpoint to be used
url = 'https://myproject.ew.r.appspot.com/{}'.format(endpoint)
data = {
'bucketname': bucketname,
'filename': filename
}
r = requests.post(url, json=data)
logging.info(r)
return str(r)
Cloud Functions 部署为:
gcloud functions deploy storage_to_gae --runtime python37 --trigger-resource $BUCKETNAME --trigger-event google.storage.object.finalize --region $REGION --source gcf/ --entry-point main --service-account cf-sa@myproject.iam.gserviceaccount.com
Fuction 使用的服务帐户已授予服务帐户用户 (roles/iam.serviceAccountUser
) 角色。
应用引擎
app.yml
runtime: python37
service: default
但是,请求没有到达 App Engine,因为 GAE 服务上没有日志。请求返回 <Response [401]>
错误代码,因此 CF 似乎无法访问 App Engine 服务。
我需要什么额外的角色来提供我的 cf-sa@myproject.iam.gserviceaccount.com
服务帐户?我正在客户端环境中部署,所以我的权限有限,我必须询问所需的确切角色。
在询问我客户的 GCP 团队后,他们使用 IAP 来管理访问。
我按照 this 文档中的说明进行操作,并且能够向 GAE 端点发送请求。
这是我的最终代码:
import requests
from google.oauth2 import id_token
from google.auth.transport.requests import Request
def make_iap_request(url, client_id, method='POST', **kwargs):
"""Makes a request to an application protected by Identity-Aware Proxy.
Args:
url: The Identity-Aware Proxy-protected URL to fetch.
client_id: The client ID used by Identity-Aware Proxy.
method: The request method to use
('GET', 'OPTIONS', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE')
**kwargs: Any of the parameters defined for the request function:
https://github.com/requests/requests/blob/master/requests/api.py
If no timeout is provided, it is set to 90 by default.
Returns:
The page body, or raises an exception if the page couldn't be retrieved.
"""
# Set the default timeout, if missing
if 'timeout' not in kwargs:
kwargs['timeout'] = 90
# Obtain an OpenID Connect (OIDC) token from metadata server or using service
# account.
open_id_connect_token = id_token.fetch_id_token(Request(), client_id)
# Fetch the Identity-Aware Proxy-protected URL, including an
# Authorization header containing "Bearer " followed by a
# Google-issued OpenID Connect token for the service account.
resp = requests.request(
method, url,
headers={'Authorization': 'Bearer {}'.format(
open_id_connect_token)}, **kwargs)
return resp.text
def main(event, context):
bucketname = event['bucket']
filename = event['name']
endpoint = # Some logic extracting the endpoint to be used
url = 'https://myproject.ew.r.appspot.com/{}'.format(endpoint)
data = {
'bucketname': bucketname,
'filename': filename
}
client_id = 'myclientid'
r = make_iap_request(url, client_id, 'POST', json=data)
logging.info(r)
return str(r)