Google App Engine与Google Cloud Run服务间私有通信配置问题
问题核心原因
你之前的配置不生效的根本原因是:测试阶段你是前端代码直接在用户浏览器侧发起Cloud Run请求,请求的发起方是终端用户的浏览器,不是GAE的服务端实例,自然不会携带GAE服务账号的身份凭证,所以即使给GAE服务账号加了Cloud Run Invoker权限也不会生效,直接返回403。
可行解决方案
方案1:GAE服务端反向代理(推荐,适配免费额度、配置最简单)
这是成本最低、符合你现有免费额度使用需求的方案,步骤如下:
- 在你的GAE部署的React服务的配套服务端逻辑(如果是纯静态React部署在GAE的话,给GAE加一个轻量后端路由层,用Node.js/Flask均可)新增所有
/api/*前缀的路由 - GAE服务端收到
/api/xxx请求时,内部转发到你的Cloud Run服务对应接口,转发时附带GAE服务账号的身份令牌 - 前端代码把所有原来直接调用Cloud Run的域名替换成GAE自己的域名,比如原来
https://xxx.run.app/getData改成https://你的GAE域名.appspot.com/api/getData - 确认Cloud Run的身份验证配置:关闭公开访问权限,只保留
Cloud Run Invoker权限给GAE的默认服务账号(格式为你的项目ID@appspot.gserviceaccount.com)
转发时获取身份令牌的代码示例(GAE用Node.js做服务端场景)
const {GoogleAuth} = require('google-auth-library'); const auth = new GoogleAuth(); async function getCloudRunToken() { // 注意audience必须是Cloud Run的完整根URL,不能带接口路径 const targetAudience = '你的Cloud Run服务的完整根URL'; const client = await auth.getIdTokenClient(targetAudience); const idToken = await client.idTokenProvider.fetchIdToken(targetAudience); return idToken; }
转发请求时把生成的令牌放到请求头的Authorization: Bearer 令牌内容里即可。
方案2:前端直接调用Cloud Run,下发签名身份令牌
如果不想改动现有请求路径架构,可以用这个方案:
- GAE服务端新增一个接口,专门给合法用户签发Cloud Run访问用的ID令牌,令牌有效期最长1小时
- 前端调用Cloud Run接口前,先从GAE拿到有效令牌,放到请求头
Authorization字段中 - 做好令牌过期刷新逻辑,避免用户使用过程中接口报错
配置验证步骤
配置完成后可以先在本地用gcloud命令模拟调用验证权限是否正确:
# 先获取Cloud Run的服务地址 gcloud run services describe 你的Cloud Run服务名 --region 对应区域 --format 'value(status.url)' # 用GAE服务账号模拟调用,验证权限是否配置正确 gcloud auth print-identity-token --audiences="你的Cloud Run根URL" --impersonate-service-account="你的项目ID@appspot.gserviceaccount.com" | xargs curl -H "Authorization: Bearer {}" 你的Cloud Run测试接口地址
如果上述调用返回正常结果,说明权限配置没有问题,剩下的只需调试服务端转发逻辑即可。
内容的提问来源于stack exchange,提问作者Suhas
相关产品推荐
相关产品推荐

