GCP Cloud Run中Nginx反向代理跨服务转发的IAM鉴权问题
问题原因与修复方案
核心错误点
你遇到的问题由配置错误叠加Cloud Run IAM鉴权特性共同导致:
- Host头配置非法:HTTP规范中
Host头只允许填写域名:端口格式,不能带https://协议前缀,你之前配置的https://my-cloud-run-backend.run.app是无效值,后端服务收到后直接返回400错误。 - 路径重写规则冲突:你同时配置了带尾斜杠的
proxy_pass和自定义rewrite规则,两者都会修改转发路径,容易出现路径拼接异常,甚至导致请求匹配不到正确的location块,落到前端静态资源规则上。 - 无效配置冗余:根路径
location /用于提供静态文件服务,没有配置反向代理,你在这个块里写的所有proxy_set_header相关配置都不会生效,反而可能干扰Nginx的location匹配逻辑。 - IAM令牌受众校验不匹配:受IAM保护的Cloud Run服务会校验请求头中OIDC令牌的
aud(受众)字段,必须匹配当前服务的URL才会放行。如果你透传的用户令牌是仅申请给前端服务使用的,后端服务校验时会直接判定令牌无效返回401。
修复步骤
1. 前置权限配置
先给前端Cloud Run的运行时服务账号授予后端服务的roles/run.invoker(Cloud Run调用者)权限,保证前端服务本身有权限访问后端。
2. 替换为正确的Nginx配置
把你的配置文件替换为以下内容,已经移除错误配置、修正头信息、处理了路径匹配问题:
server { access_log /dev/stdout; listen 8080; # 根路径提供前端静态资源,移除无用的proxy配置 location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; } # 处理无尾斜杠的/api路径,避免匹配到根路径规则 location = /api { return 301 /api/; } location /api/ { # proxy_pass末尾带斜杠,会自动剥离/api/前缀,不需要额外rewrite proxy_pass https://my-cloud-run-backend.run.app/; # 需要透传终端用户身份就保留这行,否则替换为服务账号生成的令牌 proxy_set_header Authorization $http_authorization; # 修正Host头,只保留域名 proxy_set_header Host my-cloud-run-backend.run.app; # 传递标准代理头 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # HTTPS代理必要配置,防止SNI校验失败 proxy_ssl_server_name on; proxy_ssl_name my-cloud-run-backend.run.app; # 可选:使用GCP元数据服务器做DNS解析,走内网访问后端降低延迟 resolver 169.254.169.254 valid=300s; resolver_timeout 5s; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
额外说明
如果配置后访问/api路径还是返回后端的401,说明你透传的用户令牌受众不包含后端服务地址,这种场景下不要透传用户原始令牌:
你可以通过GCP元数据接口http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://my-cloud-run-backend.run.app(请求时需要带Metadata-Flavor: Google头)动态获取前端服务账号对应后端受众的ID令牌,放到Authorization头中发给后端即可,这种方式不需要依赖用户令牌,适合后端不需要感知终端用户身份的场景。
内容的提问来源于stack exchange,提问作者istrupin
相关产品推荐
相关产品推荐

