关于GCP默认IAM权限过宽的原因、存储桶访问管控最佳实践及Terraform迁移时收紧权限的技术咨询
GCP默认IAM权限过宽的原因、存储桶访问管控最佳实践及Terraform迁移时收紧权限的技术咨询
老哥,你的问题戳中了GCP默认配置的核心痛点——为了让用户开箱即用、快速上手,GCP给这些内置服务代理账号开了项目级的宽泛权限,但在生产环境里,这种过度授权的风险确实很高,尤其是涉及存储桶这类敏感资源时,必须精准收紧。我给你一步步拆解清楚:
为什么默认服务账号会有项目级权限?
GCP这么设计本质是降低初期使用门槛:
- 像Compute Engine Service Agent这类账号,是GCP内部服务运行的「系统账号」——比如VM需要拉取存储桶里的镜像、上传日志,Cloud Run需要访问存储里的容器镜像或静态资源。默认项目级权限是为了避免用户在部署初期遇到一堆权限报错,减少配置复杂度。
- 但这确实是过度授权:这些服务代理根本不需要访问项目内所有存储桶,只需要访问它们实际依赖的那些资源。
收紧权限的核心思路:从项目级→资源级的最小授权
这里结合Terraform给你一套可落地的操作步骤,重点针对存储桶场景:
1. 先确认依赖,再移除项目级角色绑定
⚠️ 注意:别直接删项目级权限!先排查现有资源(VM、Cloud Run服务)有没有依赖这些项目级权限的场景——比如之前的VM用默认服务账号访问任意存储桶。建议先在测试环境验证,或者先配置好资源级权限,再移除项目级权限。
在Terraform里,你可以用google_project_iam_member来移除项目级角色绑定:
# 移除Compute Engine Service Agent的项目级roles/compute.serviceAgent权限 resource "google_project_iam_member" "remove_compute_service_agent_project" { project = var.gcp_project_id role = "roles/compute.serviceAgent" member = "serviceAccount:service-${var.gcp_project_number}@compute-system.iam.gserviceaccount.com" # 执行terraform apply时,这个资源会移除对应的项目级绑定 } # 移除Cloud Run Service Agent的项目级roles/run.serviceAgent权限 resource "google_project_iam_member" "remove_cloud_run_service_agent_project" { project = var.gcp_project_id role = "roles/run.serviceAgent" member = "serviceAccount:service-${var.gcp_project_number}@serverless-robot-prod.iam.gserviceaccount.com" }
2. 给服务代理配置存储桶级的最小权限
针对不同服务的需求,精准绑定到特定存储桶:
- Compute Engine场景:如果你的VM只需要读写某个特定存储桶,就给Compute Engine Service Agent绑定该桶的对应权限:
# 授予Compute Engine Service Agent在目标桶的对象创建/更新权限 resource "google_storage_bucket_iam_member" "compute_bucket_creator" { bucket = var.target_compute_bucket role = "roles/storage.objectCreator" member = "serviceAccount:service-${var.gcp_project_number}@compute-system.iam.gserviceaccount.com" } # 授予该账号在目标桶的对象读取/列表权限 resource "google_storage_bucket_iam_member" "compute_bucket_viewer" { bucket = var.target_compute_bucket role = "roles/storage.objectViewer" member = "serviceAccount:service-${var.gcp_project_number}@compute-system.iam.gserviceaccount.com" } - Cloud Run场景:同理,只给Cloud Run Service Agent绑定它实际需要访问的存储桶权限:
# 授予Cloud Run Service Agent在目标桶的对象读取/列表权限 resource "google_storage_bucket_iam_member" "cloud_run_bucket_viewer" { bucket = var.target_cloud_run_bucket role = "roles/storage.objectViewer" member = "serviceAccount:service-${var.gcp_project_number}@serverless-robot-prod.iam.gserviceaccount.com" } # 如果需要访问托管文件夹,绑定对应的查看权限 resource "google_storage_bucket_iam_member" "cloud_run_managed_folder_viewer" { bucket = var.target_cloud_run_bucket role = "roles/storage.managedFolderViewer" member = "serviceAccount:service-${var.gcp_project_number}@serverless-robot-prod.iam.gserviceaccount.com" }
3. 自定义IAM角色(如果现有角色不符合最小授权)
如果现有预制角色权限还是太宽(比如你只需要storage.objects.create和storage.objects.get,不需要list),可以创建自定义角色:
resource "google_project_iam_custom_role" "compute_bucket_custom_access" { project = var.gcp_project_id role_id = "computeBucketCustomAccess" title = "Compute Bucket Custom Access" description = "Precise permissions for Compute Engine Service Agent to access specific buckets" permissions = [ "storage.objects.create", "storage.objects.get", ] } # 把自定义角色绑定到目标存储桶 resource "google_storage_bucket_iam_member" "compute_custom_binding" { bucket = var.target_compute_bucket role = google_project_iam_custom_role.compute_bucket_custom_access.name member = "serviceAccount:service-${var.gcp_project_number}@compute-system.iam.gserviceaccount.com" }
存储桶访问管控的最佳实践
- 严格遵循最小权限原则:只给需要访问的主体(用户/服务账号)授予刚好够用的权限,避免使用
roles/storage.admin这类宽泛角色。 - 权限绑定到资源层级:优先用存储桶级甚至对象级的IAM绑定,而不是项目级的存储权限,把权限范围缩到最小。
- 启用存储桶审计日志:开启存储桶的访问日志,跟踪所有读写请求,既能验证权限配置是否正确,也能及时发现异常访问。
- 资源分类隔离:把敏感数据存储桶和普通日志/镜像存储桶分开,给不同主体配置不同的权限策略。
Terraform迁移时的注意事项
- 先测试再推生产:在测试环境完整模拟迁移流程,验证所有服务(VM、Cloud Run)都能正常访问所需资源后,再应用到生产环境。
- 用Terraform统一管理权限:把所有IAM绑定都纳入Terraform状态管理,避免手动修改导致配置漂移。如果有现有手动配置的权限,可以用
terraform import导入到Terraform中。 - 不要删除默认服务账号:这些内置服务代理账号是GCP服务运行必需的,只能调整它们的权限,不能删除。
备注:内容来源于stack exchange,提问作者Dolf Andringa
相关产品推荐
相关产品推荐

