第2章 权限模型与ABAC/RBAC

权限模型,说白了就是一套“谁能在什么条件下对什么资源做什么事”的规则框架。你想想看,没有清晰的模型,IAM审计根本无从下手——你连权限是怎么分配的都不清楚,又怎么去发现滥用?我这些年做过的审计项目里,但凡权限混乱的,几乎都是模型没选好或者混用出了问题。这一章我们就从RBAC和ABAC这两个最主流的模型入手,把它们的原理、评估逻辑和实际坑点聊透。

2.1 基于角色的访问控制(RBAC)

RBAC应该是大家最熟悉的了。它的核心思想很简单:把权限打包成角色,再把角色分配给用户。用户通过角色获得权限,而不是直接拥有权限。这样做的好处是管理方便,角色一变,下面所有人的权限跟着变。

RBAC有三大要素:用户、角色、权限。用户和角色是多对多关系,角色和权限也是多对多关系。实际落地时还会加一层会话控制——用户激活哪些角色,用哪些权限。

  • 用户:账号主体,可以是一个人、一个服务或一个流水线。
  • 角色:权限的集合,比如“管理员”、“审计员”、“开发者”。
  • 权限:对特定资源的读写执行操作,比如“ec2:DescribeInstances”。
  • 会话:用户登录后的临时上下文,决定哪些角色被激活。
我个人习惯:给角色命名时一定要遵循规范。比如“只读-生产-EC2”,而不是“viewer_prod”。名字一乱,审计时你根本分不清这个角色到底该给谁用。

我在项目里遇到过典型的“角色爆炸”问题。一个中型企业,业务线有20个,每个业务线都设了“运维-生产”、“运维-测试”、“开发-生产”……结果角色数量一下冲到上百个。更离谱的是,有些角色权限一模一样,只是名字不同。这就是RBAC粒度太粗的反噬——你不得不用大量角色去覆盖不同的权限组合。

避坑指南:我曾经见过一个团队,角色A继承了角色B,角色B又继承了角色A,结果造成权限递归。云平台虽然大部分会检测循环继承,但有些自研系统不会。写策略时务必检查角色继承图,避免死循环。

2.2 基于属性的访问控制(ABAC)

ABAC呢,就更灵活了。它不再依赖硬编码的角色,而是根据一组属性来做决策。属性通常分为四类:用户属性(部门、职级、地理位置)、资源属性(标签、创建时间、敏感级别)、环境属性(时间、IP、设备状态)、动作属性(读、写、删除)。

策略嘛,就是一堆条件表达式的组合。举个例子,一条ABAC策略可能是这样的:

{
  "Effect": "Allow",
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::prod-*",
  "Condition": {
    "StringEquals": {
      "aws:PrincipalTag/department": "engineering"
    },
    "IpAddress": {
      "aws:SourceIp": "10.0.0.0/8"
    }
  }
}

这条策略的意思是:只有部门标签为“engineering”的用户,且从内网IP段访问时,才能读取prod前缀的S3桶对象。你看,角色在这里根本不需要——属性直接决定了权限。

但ABAC也有它的麻烦。我记得有一次帮客户审计,他们的ABAC策略里用了十几个自定义属性,有的属性值有几百种。策略评估器每个请求都要计算这些条件,延迟上去了不说,排查权限问题快把人搞疯掉。我那时跟客户说:属性不是越多越好,关键属性控制在5个以内比较健康。

关键点:ABAC的威力在于条件组合的“高倍率”。但每增加一个复杂条件,理解和调试难度成倍增长。滥用条件逻辑是ABAC最大的坑。

2.3 策略评估逻辑

不管你是RBAC还是ABAC,最终都要落到策略评估上。主流云平台(AWS、Azure、GCP)的评估逻辑大同小异,核心规则就三点:

  1. 显式拒绝优先:只要有一条策略明确说“Deny”,结果就是拒绝,不管后面有多少条Allow。
  2. 显式允许:如果没有拒绝,任何一条策略允许了,结果就是允许。
  3. 默认拒绝:如果既没有拒绝也没有允许,那就拒绝。

为什么会这样设计?你可以理解为“安全优先”。拒绝就像一票否决权,确保哪怕管理员手抖写错策略,也不会意外开放危险权限。

实际评估流程里,还有个决策缓存的问题。我见过一个系统,策略评估器把用户的所有策略缓存起来,每次请求都重新遍历。结果是并发一高,CPU打满。后来改成按部门分组缓存,命中率从40%提到85%。

注意:我曾经踩过一个坑:在AWS IAM里写了一条Deny策略,但忘了加条件层级,结果Deny覆盖了所有资源,把管理员自己都锁在门外。还好有root用户救急。所以,拒绝策略一定要做最小范围限定,最好加个“NotResource”或条件限制。

2.4 RBAC与ABAC对比

两者不是非此即彼的关系。我建议你根据场景选择。下面这张表基本能说清差异:

维度 RBAC ABAC
核心概念 角色 属性
粒度 粗粒度(角色级) 细粒度(条件级)
管理复杂度 中等,角色数量容易膨胀 高,属性定义和条件组合需严谨
灵活性 低,新增权限组合需建新角色 高,调整条件即可,无需新建角色
性能开销 低,角色映射简单 中等,条件运算可能有延迟
审计可读性 高,角色即权限分组 中等,条件复杂时审计日志难查
适用场景 部门边界清晰、权限相对固定的场景 多维度条件、临时授权、大规模组织

2.5 实际应用中的选择

你想想看,大部分企业其实既用RBAC也用ABAC。比如,用RBAC做基础角色划分(管理员、普通员工),然后通过ABAC在细粒度上做条件约束——时间限制、IP限制、资源标签限制。AWS IAM里就是典型的这种混合模型:角色负责分配权限集合,策略里的Condition负责做ABAC。

我个人更推荐这种混合方式:RBAC做骨架,ABAC做血肉。角色不超过20个,每个角色下的属性条件控制在3~5个。这样既好管理,又保留灵活性。审计的时候,你一眼就能看出某个角色的边界在哪里。

最后,无论你选哪种模型,权限策略必须可自动化审计。手动翻策略那是上个时代的事。现在至少要做到定期扫描未使用的角色、无效属性和不一致的条件。

一句话总结:RBAC让你管得住,ABAC让你管得细。两个搭配好,IAM审计才能稳。
权限决策流程(RBAC + ABAC 混合模型) 用户 / 服务主体 身份验证 & 会话 RBAC 角色解析 用户 → 角色 → 权限集合 (检查角色继承、会话激活) ABAC 属性匹配 用户属性 + 资源属性 + 环境属性 + 动作属性 策略评估引擎 拒绝优先 → 允许 → 默认拒绝 允许 / 拒绝(响应) 混合模型:RBAC骨架 + ABAC血肉