如何在Google Cloud Build中认证调用需鉴权的Cloud Run服务?
在Cloud Build中为单元测试的Cloud Run请求完成认证的解决方案
核心问题分析
你看到client.idTokenProvider.email为default是正常现象——Cloud Build容器中通过元数据服务器获取的临时凭证,不会直接返回服务账号邮箱,但只要服务账号权限配置正确,生成的ID令牌依然有效。问题的核心是确保Cloud Build使用的服务账号拥有正确权限,同时代码能正确生成可通过Cloud Run鉴权的令牌。
步骤1:确认Cloud Build服务账号的权限
确保Cloud Build触发器关联的服务账号(默认是[PROJECT_ID]@cloudbuild.gserviceaccount.com,自定义服务账号则是你指定的那个)拥有Cloud Run Invoker(roles/run.invoker)角色:
- 打开目标Cloud Run服务的权限设置页面
- 添加对应服务账号,分配
Cloud Run Invoker角色
步骤2:优化令牌获取代码(更可靠的实现)
你的现有代码逻辑没问题,可调整为贴合Google Auth库最佳实践的方式,避免手动提取令牌的潜在问题:
const { GoogleAuth } = require('google-auth-library'); async function getAuthenticatedHeaders(url) { const auth = new GoogleAuth({ // 明确指定获取ID令牌,适配Cloud Run这类需受众验证的服务 scopes: ['openid'], }); const targetAudience = url; // 直接传入完整Cloud Run服务根URL即可 const client = await auth.getIdTokenClient(targetAudience); return await client.getRequestHeaders(); } // 使用示例 const headers = await getAuthenticatedHeaders(process.env.URL); const response = await fetch(process.env.URL, { headers });
注意:Cloud Run的目标受众必须是服务的完整根URL(如
https://my-service-abcdef-uc.a.run.app),不能包含具体路径。
步骤3:验证Cloud Build步骤配置
你的cloudbuild.yaml基本合规,只需确认两点:
URL环境变量是Cloud Run服务的完整根URL,无额外路径- Cloud Build容器默认可访问元数据服务器,无需额外配置
若测试仍失败,可在测试步骤中添加调试命令,验证当前使用的服务账号:
- id: npm-test name: node:16 entrypoint: sh args: - '-c' - '(/workspace/cloud_sql_proxy -dir=/cloudsql -instances=[INSTANCE-NAME] & sleep 2) && (curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email && npm test)' env: - 'NODE_ENV=production' - 'URL=[CLOUD_RUN_SERVICE_URL]' waitFor: ['npm-install']
该curl命令会打印当前服务账号邮箱,确认是否是你配置了权限的账号。
关键注意事项
- 无需在Cloud Build中上传服务账号JSON文件,元数据服务器会自动提供临时凭证,符合最佳实践
- 若使用自定义Cloud Build服务账号,需确保触发器配置中已选择该账号,而非默认服务账号
- 目标Cloud Run服务的"允许未认证调用"必须关闭,否则鉴权逻辑不会生效
内容的提问来源于stack exchange,提问作者Sven
相关产品推荐
相关产品推荐

