如何用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'] )
关键说明
- 资源IAM策略绑定:
roles/storage.objectAdmin是针对存储资源的角色,必须绑定到存储桶或项目的IAM策略中,而非服务账号自身。 - 保留现有权限:先调用
getIamPolicy获取现有策略,再添加新绑定,避免直接覆盖导致已有权限丢失。 - 条件表达式支持:指定策略版本为3才能使用条件表达式,确保服务账号仅能操作指定桶内的对象。
- 权限要求:执行代码的凭证账号需要拥有
roles/storage.admin或roles/iam.securityAdmin权限,才能修改存储桶的IAM策略。
内容的提问来源于stack exchange,提问作者browser-bug
相关产品推荐
相关产品推荐

