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

使用服务账号 impersonation 生成Google Cloud Storage签名URL时遭遇权限错误及凭证获取失败问题

使用服务账号 impersonation 生成Google Cloud Storage签名URL时遭遇权限错误及凭证获取失败问题

看起来你在通过服务账号 impersonation 生成GCS签名URL时遇到了典型的权限配置偏差问题,我来帮你梳理核心问题和解决步骤。

先拆解你的两个错误

你遇到的两个403错误指向了不同的权限需求:

  1. iam.serviceAccounts.signBlob:这是生成GCS签名URL时,服务账号需要的核心签名权限
  2. iam.serviceAccounts.getAccessToken:这是你本地登录的个人账号在尝试扮演(impersonate)目标服务账号时必须的权限

你已经完成了不少正确的前置操作,但可能在角色绑定的资源范围上出了问题,下面是具体的修正方案:


核心权限逻辑梳理

当你执行 gcloud auth application-default login --impersonate-service-account=xxx 时,整个权限链路是:

本地登录的个人账号 → 获得扮演目标服务账号的权限 → 以目标服务账号身份执行GCS操作

所以需要配置两层权限:

1. 目标服务账号的基础权限(已做对)

这部分你配置的没问题:给目标服务账号绑定Storage Object User角色,确保它能访问GCS桶和对象。

2. 本地个人账号的扮演权限(关键修正点)

你之前把Service Account Token Creator角色绑定给了目标服务账号本身,这是错误的!这个角色应该绑定给你本地登录的个人账号,并且要绑定到目标服务账号这个资源上(而不是整个项目)。

具体操作步骤:

  • 打开GCP控制台的IAM页面
  • 找到你本地登录的个人Google账号(就是你执行gcloud auth application-default login时用的账号)
  • 点击"添加权限",选择Service Account Token Creator角色
  • 重点:在"资源"下拉框中,选择你的目标服务账号(而非项目),完成绑定

这个配置的作用是:允许你的个人账号扮演该目标服务账号,获取它的凭证并执行签名操作。


快速验证权限是否生效

调整完权限后,先通过命令行验证扮演权限是否正常:

gcloud auth print-access-token --impersonate-service-account=virtu-backend@hip-apricot-446418-f2.iam.gserviceaccount.com

如果这个命令能成功返回一个access token,说明你的扮演权限已经配置正确;如果还是返回403,那大概率是角色绑定的资源范围不对,再检查一遍。


代码层面的优化(可选)

如果你的默认凭证没有自动识别到impersonation配置,可以在代码中显式指定使用扮演的服务账号凭证,确保身份正确:

import datetime
from google.cloud import storage
from google.auth import impersonated_credentials
import google.auth

def get_impersonated_sa_creds():
    # 获取本地应用默认凭证
    default_creds, project = google.auth.default()
    # 目标服务账号邮箱
    target_sa = "virtu-backend@hip-apricot-446418-f2.iam.gserviceaccount.com"
    # 定义需要的权限范围
    scopes = [
        "https://www.googleapis.com/auth/devstorage.read_only",
        "https://www.googleapis.com/auth/iam"
    ]
    # 创建扮演凭证
    return impersonated_credentials.Credentials(
        source_credentials=default_creds,
        target_principal=target_sa,
        target_scopes=scopes,
        lifetime=3600
    )

# 使用扮演凭证初始化GCS客户端
storage_client = storage.Client(credentials=get_impersonated_sa_creds())
bucket = storage_client.bucket('virtu_users_uploaded_pictures')
blob = bucket.blob('test1')

url = blob.generate_signed_url(
    version="v4",
    expiration=datetime.timedelta(minutes=15),
    method="GET",
)

print("Generated GET signed URL:")
print(url)
print("You can use this URL with any user agent, for example:")
print(f"curl '{url}'")

额外注意事项

  • 确保Service Account Credentials API启用后等待2-3分钟,API生效需要一点同步时间
  • 检查是否有拼写错误:服务账号邮箱、桶名必须完全一致
  • 如果你的个人账号有组织级别的权限限制,可能需要联系管理员确认是否允许你扮演服务账号

备注:内容来源于stack exchange,提问作者André Kuljis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:04:51