第三章 主体(Principal)配置:用户、角色与服务主体的那些事

权限策略里有个核心概念——主体。说白了,就是「谁」在请求访问。

我刚开始接触云权限时,总觉得主体配置不就是填个用户名吗?后来踩过几次坑才明白,用户、角色、服务主体、匿名主体,这四类东西虽然都叫主体,但使用场景天差地别。选错了,轻则权限失效,重则安全漏洞。

这一章,咱们就把它们掰开揉碎讲清楚。

3.1 用户(User)与角色(Role)的本质区别

很多新手会问:用户和角色不都是「一个人」吗?

嗯,还真不是。

核心区别一句话:用户是「你是谁」,角色是「你能干什么」。

用户代表一个真实的人或一个服务账号。它有固定的身份标识,长期存在。你登录控制台,用的就是用户身份。

角色则是一组权限的集合。它不绑定具体的人,而是被「赋予」给某个主体。角色可以被多个用户同时使用,也可以随时切换。

我举个例子你就明白了:

  • 用户 = 公司工牌。上面印着你的名字和照片,证明你是张三。
  • 角色 = 门禁卡。谁拿着这张卡,谁就能进机房。今天张三拿,明天李四拿,卡本身不变。

在实际项目中,我见过有人把每个员工都配成独立用户,然后给每个用户单独绑定权限。结果呢?员工离职时,要一个个解绑,漏一个就是安全隐患。

我的建议:用户只负责身份认证,权限尽量通过角色来管理。这样人员变动时,你只需要调整角色归属,不用改策略本身。

3.2 什么时候该用用户,什么时候该用角色?

这里我总结了一个决策表,帮你快速判断:

场景 推荐主体类型 原因
员工登录控制台操作资源 用户 + 角色 用户负责登录,角色赋予操作权限
应用程序调用 API 服务主体(或角色) 程序不需要「人」的身份,只需要权限
临时授权给外部合作方 角色(跨账号信任) 不用创建用户,用完撤销信任关系即可
自动化脚本执行运维任务 服务主体 长期运行,密钥管理比用户密码更安全
匿名访问公开资源 匿名主体 不需要身份验证,但必须限制权限范围

你看,大部分场景下,角色比用户更灵活。我自己的习惯是:能用角色解决的问题,绝不创建新用户。

3.3 服务主体(Service Principal)—— 程序的「身份证」

服务主体,说白了就是给程序用的身份。

你想想看,你的代码跑在服务器上,它需要调用云 API 创建虚拟机、读写数据库。但代码不是人,没法输密码登录。这时候就需要服务主体。

服务主体有几个特点:

  • 没有密码,使用密钥对或证书进行认证
  • 不依赖具体用户,即使创建它的管理员离职了,服务主体依然有效
  • 可以绑定角色,获得相应的操作权限

我在项目中遇到过这样一个坑:有个同事把云服务器的访问密钥直接写死在代码里,用的是他自己的用户密钥。后来他离职了,密钥被轮转,整个生产环境直接瘫痪。

我曾经踩过的坑:永远不要用个人用户的密钥给程序用。应该创建专用的服务主体,分配最小权限。这样即使密钥泄露,影响范围也有限。

配置服务主体时,通常需要指定:

{
  "Principal": {
    "Service": ["ecs.aliyuncs.com"]
  },
  "Action": "sts:AssumeRole",
  "Effect": "Allow"
}

这段策略的意思是:允许 ECS 服务(作为服务主体)扮演某个角色。这样,运行在 ECS 上的程序就能临时获取角色的权限。

3.4 匿名主体(Anonymous)—— 公开访问的守门员

匿名主体,就是「不需要登录就能访问」的主体。

什么场景下会用?

  • 公开的静态网站托管(比如 OSS 上的图片、HTML 文件)
  • 开放的 API 接口(比如天气查询、公共数据)
  • 资源分享链接(比如网盘分享,不需要对方登录)

但这里有个大坑——匿名主体一旦配置不当,就等于把家门钥匙挂在门外。

我记得有一次帮客户做安全审计,发现他们的 OSS Bucket 策略里写着:

{
  "Principal": "*",
  "Action": "oss:GetObject",
  "Effect": "Allow",
  "Resource": "acs:oss:*:*:my-bucket/*"
}

看起来只是允许匿名读取文件,对吧?但问题在于,这个策略没有限制文件路径。结果就是,任何人都可以遍历整个 Bucket,把所有的文件都下载下来——包括数据库备份文件。

匿名主体配置铁律:

  • 必须指定具体的 Resource,不要用通配符
  • 只开放必要的 Action(比如只读,不开放写操作)
  • 加上条件限制(比如 IP 范围、Referer 来源)
  • 定期审计匿名策略,确认是否仍然需要

3.5 四种主体的关系与选择逻辑

说了这么多,咱们用一张图来总结四种主体的关系:

四种主体关系与选择逻辑 主体(Principal) 用户(User) 角色(Role) 服务主体 匿名主体 选择逻辑: 1. 需要长期身份 → 用户 2. 需要临时权限 → 角色 3. 程序调用 API → 服务主体 4. 公开资源访问 → 匿名主体(务必限制范围)

3.6 实战:一个典型的多主体配置案例

最后,咱们看一个完整的例子。假设你要搭建一个文件分享系统:

  1. 管理员(用户)登录后台,管理文件列表
  2. 后端服务(服务主体)处理文件上传下载
  3. 分享链接(匿名主体)允许外部用户下载指定文件
  4. 临时运维(角色)在故障时获得服务器访问权限

对应的策略配置思路:

// 1. 管理员用户策略
{
  "Principal": { "User": "admin@company.com" },
  "Action": "oss:ListObjects",
  "Effect": "Allow",
  "Resource": "acs:oss:*:*:share-bucket/*"
}

// 2. 服务主体策略
{
  "Principal": { "Service": "ecs.aliyuncs.com" },
  "Action": ["oss:PutObject", "oss:GetObject"],
  "Effect": "Allow",
  "Resource": "acs:oss:*:*:share-bucket/uploads/*"
}

// 3. 匿名主体策略(严格限制路径)
{
  "Principal": "*",
  "Action": "oss:GetObject",
  "Effect": "Allow",
  "Resource": "acs:oss:*:*:share-bucket/public/*",
  "Condition": {
    "IpAddress": { "acs:SourceIp": "0.0.0.0/0" }
  }
}

// 4. 临时运维角色
{
  "Principal": { "Role": "ops-role" },
  "Action": "ecs:DescribeInstances",
  "Effect": "Allow",
  "Resource": "*"
}

小技巧:配置完成后,用「最小权限原则」反向检查一遍——把每个主体的权限降到「刚好够用」的程度。多一个 Action 都不要给。

嗯,这一章的内容就到这儿。主体配置是权限策略的基石,选对了,后面的策略编写就顺风顺水。选错了,后面全是补丁。