使用不同服务账号时Cloud Function调用另一个Cloud Function失败
问题:第二代Cloud Function通过Pub/Sub触发时认证失败
架构配置
- Cloud Scheduler触发HTTP类型的Function A(第二代,需身份认证,使用独立服务账号)
- Function A执行完成后,通过已创建的Pub/Sub主题
db-topic触发Function B(第二代,需身份认证,使用另一独立服务账号)
错误现象
Function A可成功发布Pub/Sub消息,但Function B日志持续报错:
The request was not authenticated. Either allow unauthenticated invocations or set the proper Authorization header
已执行的部署命令
部署Function A(HTTP触发)
gcloud functions deploy db-func-pubsub-test \ --runtime=python310 \ --trigger-http \ --entry-point=start_script \ --region=europe-west3 \ --max-instances=1 \ --timeout=3500s \ --memory=1GiB \ --service-account=cloud-function-a@propane-nomad-396712.iam.gserviceaccount.com \ --ingress-settings=all \ --no-allow-unauthenticated \ --gen2 \ --source=./cloud_functions/code/6/publisher/
部署Function B(Pub/Sub触发)
gcloud functions deploy func-pubsub-subscriber-test \ --runtime=python310 \ --trigger-topic=db-topic \ --entry-point=pubsub_handler \ --region=europe-west3 \ --max-instances=1 \ --timeout=60s \ --memory=256MiB \ --service-account=cloud-function-b@propane-nomad-396712.iam.gserviceaccount.com \ --ingress-settings=all \ --no-allow-unauthenticated \ --gen2 \ --source=./cloud_functions/code/6/subscriber/
已执行的授权操作
- 尝试授权Function A调用Function B:
gcloud functions add-invoker-policy-binding func-pubsub-subscriber-test \ --member="serviceAccount:cloud-function-a@propane-nomad-396712.iam.gserviceaccount.com" \ --region='europe-west3'
- 修复Function A的Pub/Sub发布权限:
gcloud projects add-iam-policy-binding propane-nomad-396712 --member=serviceAccount:cloud-function-a@propane-nomad-396712.iam.gserviceaccount.com --role=roles/pubsub.publisher
- 尝试授权Function B的Pub/Sub订阅权限:
gcloud projects add-iam-policy-binding propane-nomad-396712 --member=serviceAccount:cloud-function-b@propane-nomad-396712.iam.gserviceaccount.com --role=roles/pubsub.subscriber
已知有效场景
- 两个函数使用同一服务账号时,整个流程正常运行
- Cloud Scheduler通过授权可正常调用Function A
代码参考
Function A发布消息片段
# Publish a message to the Pub/Sub topic publisher = pubsub_v1.PublisherClient() topic_path = f'projects/{project_id}/topics/{topic_name}' data = {"project_id": project_id, "bucket_name": bucket_name, "prefix_path": prefix_path} data_str = json.dumps(data).encode('utf-8') # Convert dictionary to JSON-encoded bytestring publisher.publish(topic_path, data=data_str) print(f"Printing json message being published: {data}")
Function B处理消息片段
def pubsub_handler(event, context): # Retrieve the JSON payload from the Pub/Sub message pubsub_message = event['data'] decoded_message = base64.b64decode(pubsub_message).decode('utf-8') # Decode and convert to string print(f"Printing pubsub message received: {decoded_message}") data_dict = json.loads(decoded_message)
问题根源与解决方法
核心误区
之前给Function A添加Function B的调用权限完全无效,因为Pub/Sub触发第二代Function的流程是:Function A → Pub/Sub主题 → Google Pub/Sub服务账号 → Function B的HTTP端点。实际发起Function B调用请求的是Pub/Sub的服务账号,而非Function A的服务账号。
正确授权步骤
- 获取当前项目编号:
gcloud projects describe propane-nomad-396712 --format='value(projectNumber)'
- 构造Pub/Sub服务账号(格式为
service-<项目编号>@gcp-sa-pubsub.iam.gserviceaccount.com),为其添加Function B的调用权限:
gcloud functions add-invoker-policy-binding func-pubsub-subscriber-test \ --member="serviceAccount:service-<你的项目编号>@gcp-sa-pubsub.iam.gserviceaccount.com" \ --region=europe-west3
验证
重新触发Function A发布消息,查看Function B日志是否正常执行。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

