Cloud Run服务A调用需认证服务B的配置步骤及多服务账号问题
Cloud Run服务A调用需认证的服务B问题解答
1. Cloud Run能否配置多个服务账号?
不能,每个Cloud Run修订版本只能绑定一个默认服务账号(就是控制台「SECURITY」标签里设置的那个)。但这完全不影响你实现服务A调用服务B的需求——不需要额外添加服务账号,只要在服务A的代码里用指定的服务身份生成认证令牌即可,和服务A当前绑定的、用于Firestore的服务账号互不冲突。
2. 实现服务A调用服务B的具体步骤
先修正权限配置(你之前的步骤有冗余)
- 只需要给服务A用来调用服务B的身份(可以是服务A的默认服务账号,也可以是你创建的Service Account A)授予服务B的
roles/run.invoker权限:- 打开Cloud Run控制台,找到服务B,进入「权限」标签
- 点击「添加成员」,输入目标服务账号的邮箱(比如Service Account A的邮箱,或者服务A默认账号的邮箱)
- 选择角色「Cloud Run > Cloud Run Invoker」,保存即可
你之前给Service Account A添加Cloud Run Service Agent权限是多余的,这个权限是Cloud Run内部服务使用的,不需要手动配置。
在服务A的代码中生成认证令牌并调用服务B
Cloud Run运行时会自动为绑定的服务账号提供身份凭证,你可以用两种方式获取认证令牌:
方式一:用官方SDK(推荐,以Python为例)
import google.auth from google.auth.transport.requests import Request import requests def invoke_service_b(): # 获取当前服务账号的凭证(自动使用服务A绑定的账号,或代码指定的ServiceAccount A) credentials, _ = google.auth.default() # 刷新凭证以获取针对服务B的ID令牌 credentials.refresh(Request()) # 替换成你的服务B的完整API地址 service_b_api_url = "https://service-b-xxxxxx.run.app/your-api-path" # 带上认证头发起请求 headers = {"Authorization": f"Bearer {credentials.id_token}"} response = requests.get(service_b_api_url, headers=headers) response.raise_for_status() return response.json()
方式二:直接调用元数据服务器(适合无SDK场景)
如果你的代码环境无法使用Google SDK,可以直接调用元数据服务器获取令牌:
# 在服务A的容器内执行,替换成服务B的根URL(不带路径) TOKEN=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://service-b-xxxxxx.run.app") # 调用服务B的API curl -H "Authorization: Bearer $TOKEN" https://service-b-xxxxxx.run.app/your-api-path
注意:
audience必须填服务B的根域名URL,不能带具体路径,否则令牌会被服务B拒绝。
最后验证
部署服务A的新版本(包含上述调用逻辑),触发服务A的公共接口,检查是否能成功调用服务B的API即可。
内容的提问来源于stack exchange,提问作者iKK
相关产品推荐
相关产品推荐

