You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Workload Identity Federation调用Google Cloud Run服务遇401授权错误

使用AWS工作负载身份联盟调用Google Cloud Run服务时出现401未授权错误

问题背景

已通过AWS工作负载身份联盟成功 impersonate GCP服务账号,可正常调用GCS API列出存储桶,但调用开启了「require authentication」的Cloud Run服务时返回401未授权。使用服务账号密钥文件配合getIdTokenClient可正常访问,需排查工作负载身份联盟方式的问题。

正常工作的GCS调用代码

const {GoogleAuth} = require('google-auth-library');

async function main() {
    const auth = new GoogleAuth({
        scopes: 'https://www.googleapis.com/auth/cloud-platform'
      });
      const client = await auth.getClient();
      const projectId = await auth.getProjectId();
      console.log('projectId = ', projectId)
      // List all buckets in a project.
    const url = `https://storage.googleapis.com/storage/v1/b?project=${projectId}`;
    const res = await client.request({ url });
    console.log(res.data);
  }
  
main().catch(console.error);

报错的Cloud Run调用代码

const {GoogleAuth} = require('google-auth-library');

async function main() {
  const targetAudience = 'https://my-cloud-run-service.a.run.app/'
  const auth = new GoogleAuth({
      scopes: 'https://www.googleapis.com/auth/cloud-platform',
      targetAudience: targetAudience
    });
    const client = await auth.getClient();
    const projectId = await auth.getProjectId();
    console.log('projectId = ', projectId)
    
    const url = targetAudience;
    // 此处返回401 Unauthorized
    const response = await client.request({url});
    console.log(response);
  }
  
main().catch(console.error);

错误信息

GaxiosError: 
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>401 Unauthorized</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Unauthorized</h1>
<h2>Your client does not have permission to the requested URL <code>/</code>.</h2>
<h2></h2>
</body></html>

    at Gaxios._request (/home/ubuntu/trader2/node_modules/gaxios/build/src/gaxios.js:141:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async AwsClient.requestAsync (/home/ubuntu/trader2/node_modules/google-auth-library/build/src/auth/baseexternalclient.js:246:24)
    at async main (/home/ubuntu/trader2/testAuth.js:15:22)

解决方案与排查步骤

1. 修正目标受众URL格式

Cloud Run的目标受众URL必须不带末尾斜杠,Google ID令牌验证会严格匹配aud字段,末尾斜杠会导致令牌受众与服务期望不匹配,触发401。正确格式应为:

const targetAudience = 'https://my-cloud-run-service.a.run.app';

2. 显式获取ID令牌客户端

getClient()默认生成的是适用于GCP标准API的OAuth2客户端,而Cloud Run需要**ID令牌(ID Token)**而非访问令牌(Access Token)。需显式调用getIdTokenClient()获取专用客户端:

const {GoogleAuth} = require('google-auth-library');

async function main() {
  const targetAudience = 'https://my-cloud-run-service.a.run.app';
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/cloud-platform'
  });
  // 显式获取ID令牌客户端
  const client = await auth.getIdTokenClient(targetAudience);
  const projectId = await auth.getProjectId();
  console.log('projectId = ', projectId)
  
  const url = targetAudience;
  const response = await client.request({url});
  console.log(response);
}

main().catch(console.error);

3. 验证服务账号权限

确认被impersonate的GCP服务账号拥有roles/run.invoker权限,可通过gcloud命令验证:

gcloud projects get-iam-policy YOUR_PROJECT_ID --filter="bindings.members:serviceAccount:YOUR_SERVICE_ACCOUNT@YOUR_PROJECT_ID.iam.gserviceaccount.com" --format="value(bindings.role)"

确保输出包含roles/run.invoker。

4. 检查令牌有效性

临时解码ID令牌,验证aud字段是否与Cloud Run URL完全一致,同时确认权限字段:

const jwtDecode = require('jwt-decode');
// 在获取客户端后添加以下代码
const token = await client.idTokenProvider.fetchIdToken(targetAudience);
console.log(jwtDecode(token));

重点检查aud(受众)和permissions字段是否符合预期。

5. 确认身份池配置

检查工作负载身份池的属性映射是否正确,确保AWS角色的断言被正确映射到GCP身份属性,且身份池权限允许AWS角色impersonate目标服务账号。

内容的提问来源于stack exchange,提问作者BenTaylor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 20:07:23