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

如何用Python为Google服务账号正确分配Storage ObjectAdmin角色?

问题原因与解决方案

错误根源

你调用的projects().serviceAccounts().setIamPolicy接口是用来配置服务账号自身的IAM权限(比如控制哪些账号能修改这个服务账号),而非给服务账号分配云资源的访问权限。roles/storage.objectAdmin是Google Cloud Storage资源的专属角色,无法绑定到服务账号的IAM策略上,因此触发报错。

正确实现方式

要给服务账号分配存储桶的objectAdmin权限,需要将服务账号添加到目标存储桶的IAM策略中(如果需要项目级权限则绑定到项目IAM)。以下是修正后的代码:

修正后的完整代码

import os
from google.oauth2 import service_account
import googleapiclient.discovery

def create_service_account(project_id, account_id, display_name):
    """创建服务账号"""
    credentials = service_account.Credentials.from_service_account_file(
        filename=os.getenv('GOOGLE_APPLICATION_CREDENTIALS'),
        scopes=['https://www.googleapis.com/auth/cloud-platform'])

    service = googleapiclient.discovery.build(
        'iam', 'v1', credentials=credentials)

    my_service_account = service.projects().serviceAccounts().create(
        name=f'projects/{project_id}',
        body={
            'accountId': account_id,
            'serviceAccount': {
                'displayName': display_name
            }
        }).execute()
    return my_service_account

def assign_storage_bucket_role(project_id, bucket_name, service_account_email):
    """给服务账号分配指定存储桶的objectAdmin角色(带访问条件)"""
    credentials = service_account.Credentials.from_service_account_file(
        filename=os.getenv('GOOGLE_APPLICATION_CREDENTIALS'),
        scopes=['https://www.googleapis.com/auth/cloud-platform'])

    # 构建Storage服务客户端
    service = googleapiclient.discovery.build('storage', 'v1', credentials=credentials)

    # 获取存储桶现有IAM策略(避免覆盖已有权限)
    policy = service.buckets().getIamPolicy(
        bucket=bucket_name,
        options={'requestedPolicyVersion': 3}  # 版本3支持条件表达式
    ).execute()

    # 新增绑定规则:给目标服务账号添加带条件的objectAdmin权限
    new_binding = {
        "role": "roles/storage.objectAdmin",
        "members": [f"serviceAccount:{service_account_email}"],
        "condition": {
            "title": "TenantSpace",
            "expression": f'resource.type == "storage.googleapis.com/Object" && resource.name.startsWith("projects/{project_id}/buckets/{bucket_name}/")',
        }
    }

    # 将新绑定加入现有策略
    policy.setdefault('bindings', []).append(new_binding)

    # 更新存储桶IAM策略
    updated_policy = service.buckets().setIamPolicy(
        bucket=bucket_name,
        body={'policy': policy}
    ).execute()

    return updated_policy

# 执行流程
service_account = create_service_account(
        project_id='XXXX',
        account_id='test-name-sa',
        display_name='TestNameServiceAccount'
)
policy = assign_storage_bucket_role(
        project_id='XXXX',
        bucket_name='demo',
        service_account_email=service_account['email']
)

关键说明

  1. 资源IAM策略绑定:roles/storage.objectAdmin是针对存储资源的角色,必须绑定到存储桶或项目的IAM策略中,而非服务账号自身。
  2. 保留现有权限:先调用getIamPolicy获取现有策略,再添加新绑定,避免直接覆盖导致已有权限丢失。
  3. 条件表达式支持:指定策略版本为3才能使用条件表达式,确保服务账号仅能操作指定桶内的对象。
  4. 权限要求:执行代码的凭证账号需要拥有roles/storage.admin或roles/iam.securityAdmin权限,才能修改存储桶的IAM策略。

内容的提问来源于stack exchange,提问作者browser-bug

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:05:03