4. 用户、群组与服务账号管理

在 Google Cloud 的身份体系中,身份主体(Principal)是权限授予的接收方。理解用户、群组、服务账号这三类主体的差异,是设计可维护权限模型的基础。它们并非可以随意互换的选项,而是分别对应“人”“人的集合”“非人工作负载”三种截然不同的生命周期与安全边界。

三类身份主体的本质差异

用户账号(User Account)代表一个真实的人,通常由 Google Workspace 或 Cloud Identity 托管,形如 zhang@example.com。它的生命周期与员工在职状态绑定:入职创建、转岗调整、离职停用。用户账号的核心特征是“有交互式登录能力”,可以接受多因素认证,也正因如此,它是最容易被钓鱼攻击的目标。

群组(Google Group)是一个邮箱地址,形如 dev-team@example.com,本身不登录、不持有密钥,只作为一组用户的集合。它的价值在于把权限授予“群组”而非“个人”:当成员变动时,只需增删群组成员,无需触碰任何 IAM 策略。这是大规模权限治理中最重要的解耦手段。

服务账号(Service Account)是一种特殊的非人身份,形如 sa-worker@project-id.iam.gserviceaccount.com。它没有密码,通过密钥或短期凭证认证,供应用、虚拟机、CI/CD 流水线等程序化负载使用。服务账号默认属于创建它的项目,其生命周期应与它所支撑的工作负载一致。

三类身份主体:认证方式 · 生命周期 · 适用场景 用户 User zhang@example.com 认证方式 交互式登录 + MFA 生命周期 入职 → 转岗 → 离职 适用场景 人工操作控制台 日常开发与运维 风险点 钓鱼攻击 · 凭证泄露 离职未及时停用 群组 Group dev-team@example.com 认证方式 不登录 · 无密钥 生命周期 随项目/团队长期存在 适用场景 批量授权 · 权限解耦 团队级角色绑定 核心价值 成员变动不改策略 权限继承与嵌套 服务账号 Service Account SA sa-worker@proj.iam .gserviceaccount.com 认证方式 密钥 / 短期凭证 生命周期 随工作负载创建/销毁 适用场景 应用 · VM · CI/CD 程序化 API 调用 风险点 密钥泄露 · 权限过大 长期未轮换 推荐:用户 → 加入群组 → 群组绑定角色;服务账号独立授权,避免与个人账号混用

为什么优先用群组授权

假设一个项目有 30 名开发人员需要 roles/editor 权限。如果逐个给用户绑定角色,IAM 策略中会出现 30 条绑定记录;每当有人入职或离职,都要修改策略。而如果创建一个 dev-team@example.com 群组,只需一条绑定:group:dev-team@example.com → roles/editor。人员变动只发生在群组成员列表里,IAM 策略保持稳定。

这种做法的深层意义在于:权限策略描述的是“角色与资源的对应关系”,而不是“谁是谁”。把人的身份与权限解耦,才能让权限模型在组织变动中保持可审计、可预测。Google 官方也建议,除极少数个人专属权限外,几乎所有 IAM 绑定都应授予群组而非个人。

服务账号的正确使用姿势

服务账号最常见的误用,是把它当成“没有密码的用户账号”来用——比如给某个服务账号授予 roles/owner,然后到处下载它的 JSON 密钥。这实际上制造了一个永不过期、无法 MFA、泄露后极难察觉的超级凭证。

正确的做法遵循三条原则:

  • 最小权限:只授予工作负载真正需要的角色。例如一个只负责读取 Cloud Storage 的导出任务,应绑定 roles/storage.objectViewer,而不是 roles/storage.admin。
  • 优先短期凭证:在 GCE、GKE、Cloud Run 等环境中,使用附加的服务账号自动获取短期令牌,无需下载密钥文件。只有跨云或本地环境才考虑密钥,并应配合密钥轮换。
  • 一负载一账号:不同应用使用不同服务账号,避免一个账号被攻破后横向影响所有系统。服务账号的命名应体现用途,如 sa-log-export@proj.iam.gserviceaccount.com。

生命周期管理的关键节点

三类主体的生命周期管理重点不同。用户账号的关键节点是离职停用——应在 HR 系统触发后立即禁用账号并转移其拥有的资源(如 Drive 文件、项目所有权)。群组的关键节点是成员审计——定期检查是否有已离职人员仍留在群组中,这往往是权限泄漏的隐蔽通道。服务账号的关键节点是密钥轮换与闲置清理——Google 会在控制台标记长期未使用的服务账号,应定期审查并删除。

在组织层面,可以通过 Organization Policy 限制服务账号密钥的创建(constraints/iam.disableServiceAccountKeyCreation),从源头推动工作负载身份(Workload Identity)的使用,这是比事后审计更有效的治理手段。

实操示例:为一个应用创建最小权限服务账号

假设有一个运行在 GKE 上的日志导出应用,需要将日志写入 BigQuery。以下是使用 gcloud 创建并授权的示例:

# 1. 创建服务账号
gcloud iam service-accounts create sa-log-export \
  --display-name="Log Export to BigQuery" \
  --project=my-project

# 2. 授予最小权限:仅 BigQuery 数据编辑
gcloud projects add-iam-policy-binding my-project \
  --member="serviceAccount:sa-log-export@my-project.iam.gserviceaccount.com" \
  --role="roles/bigquery.dataEditor"

# 3. 在 GKE 中通过 Workload Identity 绑定 KSA 与 GSA
gcloud iam service-accounts add-iam-policy-binding \
  sa-log-export@my-project.iam.gserviceaccount.com \
  --role="roles/iam.workloadIdentityUser" \
  --member="serviceAccount:my-project.svc.id.goog[default/log-export-ksa]"

执行后,可通过以下命令验证绑定是否生效:

gcloud projects get-iam-policy my-project \
  --flatten="bindings[].members" \
  --filter="bindings.members:sa-log-export" \
  --format="table(bindings.role)"

预期输出应只显示 roles/bigquery.dataEditor,若出现其他角色,说明权限过大,需要回收。这个验证步骤应纳入 CI/CD 流水线,作为权限变更的自动检查点。

身份主体选择决策

面对一个具体的授权需求,可以按以下逻辑判断使用哪类主体:如果操作者是人且需要登录控制台,用用户账号;如果是一组人需要相同权限,用群组;如果是程序自动运行,用服务账号。需要特别注意的是,绝不要用个人用户账号的凭证去运行自动化脚本——这会让脚本的权限与个人绑定,人员离职时脚本失效,且审计日志无法区分人与机器行为。

把这三类主体放在一起看,它们构成了 Google Cloud 权限模型的输入侧。用户和群组解决“人如何获得权限”,服务账号解决“程序如何获得权限”。清晰地区分它们,并在授权时坚持“群组优先、服务账号最小化、密钥短期化”,就能在组织规模增长时保持权限体系的可控与可审计。