Agent 时代,RBAC 为什么只完成了一半
RBAC 没有过时。它仍然适合回答“这类人通常能做什么”,但 Agent 执行还要回答:哪个 Agent,为了哪次任务,在什么条件下,可以对哪些具体对象执行多少次什么动作。
企业给 Agent 接入 CRM、ERP、HR 或财务系统时,最常见的一句话是:
不用再做权限,沿用现有 RBAC 就行。
这句话有一半是对的。
现有 RBAC 不应该被绕过。员工原本不能查看的客户、不能审批的付款、不能修改的合同,Agent 也不能因为接入了 MCP 就突然获得权限。
但如果方案到这里结束,另一半问题会被漏掉:
这个用户有权限
≠
这个 Agent 在这次任务中已获得同样范围的自动执行授权
传统 RBAC 主要围绕用户、角色和权限展开。Agent 场景又增加了执行主体、资源关系、任务意图、时间窗口、调用次数、批量规模和运行时风险。
所以标题不是“RBAC 已死”,而是“RBAC 只完成了一半”。
RBAC 仍然是底座,只是不再是完整答案。
RBAC 解决了什么
RBAC 的价值首先是降低权限管理成本。
如果没有角色,管理员可能要给每名员工逐项配置权限:
张三 → 查看客户
张三 → 修改商机
李四 → 查看客户
李四 → 修改商机
……
使用 RBAC 后,可以先把权限赋给角色,再把人员分配到角色:
角色:销售经理
权限:查看客户、修改商机、提交折扣申请
张三 → 销售经理
李四 → 销售经理
NIST 已归档的 RBAC 项目页对这一经典模型的介绍很清楚:RBAC 让安全管理贴近组织结构,用户被分配一个或多个角色,角色拥有相应权限;角色层级和互斥角色等复杂关系也可以由 RBAC 软件处理。这里引用它作为历史模型依据,不把该归档页面当成当前产品实施指南。
这几个能力在 Agent 时代仍然重要:
- 大规模人员授权;
- 岗位与基础权限映射;
- 角色层级;
- 静态或动态职责分离;
- 入职、调岗和离职治理;
- 权限申请与周期复核。
假设财务专员没有付款审批角色,代表他的 Agent 同样不能审批付款。
用户 RBAC Deny
→ Agent 必须 Deny
Agent 平台不能通过 MCP、Ontology、PDP 或共享服务账号把这条 Deny 改成 Allow。
RBAC 没有回答什么
RBAC 擅长表达:
销售经理可以修改商机
但一次 Agent 执行需要更具体的问题:
哪个销售经理?
哪个 Agent 和版本?
代表用户还是自主运行?
为了哪次任务?
修改哪个区域、项目或客户的商机?
允许改哪些字段?
当前业务状态是否允许修改?
最多处理多少条?
权限何时过期?
失败后能否重试?
累计影响是否超出预算?
这些问题并非都适合继续堆进角色名称。
如果强行使用 RBAC,角色会迅速膨胀:
华东区销售经理
华东区大客户销售经理
华东区项目 A 大客户销售经理
华东区项目 A 临时代理销售经理
华东区项目 A 可批量修改但不可删除销售经理
……
角色开始同时承载组织、区域、项目、时间、数据关系和任务范围,最终形成 Role Explosion。
这不是 RBAC 实现得不够好,而是把不同维度的问题都塞进了角色。
ABAC 补上运行时条件
NIST SP 800-162 将 ABAC 定义为一种逻辑访问控制方法:通过评估 Subject、Object、Requested Operation 以及某些情况下的 Environment 属性,并将其与策略、规则或关系比较,决定是否允许操作。
放到 Agent 场景中,可以得到:
Subject 属性
- 用户部门
- 用户职级
- 用户所属法人
- Agent 身份
- Agent 风险等级
- Agent 版本
Object 属性
- 客户所属区域
- 合同密级
- 发票金额
- 数据所属法人
- 记录当前状态
Action 属性
- read
- update
- approve
- refund
- export
Environment 属性
- 当前时间
- 来源网络
- 设备可信度
- 风险评分
- 是否完成 Step-up
策略可以写成:
用户具有“财务审批人”角色
且发票所属法人等于用户所属法人
且金额不超过用户审批上限
且 Agent 风险等级允许执行写操作
且当前会话已完成 Step-up
→ 可以进入审批动作
ABAC 解决的是“同一个角色,在不同对象和环境下,决策可能不同”。
它比继续增加组合角色更适合表达金额、时间、地域、敏感度和运行时风险。
ABAC 也不能包办所有关系
理论上,很多关系都可以转成属性:
user.project_ids = [A, B, C]
resource.project_id = A
然后判断两者是否匹配。
小规模系统这样做完全可行。
但在大型企业中,关系往往不是单层属性:
张三是项目 A 成员
项目 A 属于事业群 B
事业群 B 管理供应商 C
合同 D 属于供应商 C
还可能出现:
- 文件由某个团队拥有;
- 用户是团队成员;
- Agent 被分配给某项任务;
- 任务获得某个项目的写权限;
- 项目下的工单继承项目权限;
- 临时代理只对一个客户生效。
如果把这些关系全部展开为用户属性,缓存失效、关系更新和列表膨胀会变得困难。
这正是关系授权模型擅长的部分。
ReBAC 补上人与资源之间的关系
ReBAC 通常根据主体与对象之间的关系决定权限。
Google Zanzibar 展示了一种大规模关系授权系统:通过统一数据模型和配置语言表达访问控制列表,并为多个 Google 服务提供授权判断。OpenFGA 则以 Authorization Model 和 Relationship Tuple 表达用户、关系与对象之间的连接。
典型关系元组可以写成:
user:zhangsan
relation: member
object: project:east-2026
或者:
task:purchase-001
relation: write
object: project:east-2026
授权系统再根据模型计算:
项目成员可以读取项目
项目所有者可以编辑项目
项目管理员可以删除项目
工单继承所属项目的读取权限
ReBAC 对以下场景很自然:
- 一人多岗;
- 矩阵组织;
- 项目成员关系;
- 临时代理;
- 资源所有者;
- 上下级组织继承;
- 文档共享;
- 任务与 Agent 的绑定;
- 项目到子资源的权限继承。
但 ReBAC 也不是新的万能权限中台。
它能证明张三与项目 A 有关系,却不会自动知道:
- 当前金额是否超过限额;
- 数据是否处于冻结状态;
- 是否完成二次认证;
- 这次任务最多可以执行几次;
- 下游系统当前是否最终允许写入。
关系是授权输入,不是完整业务状态机。
Agent 场景还缺一个任务维度
到这里,我们已经有:
RBAC:用户长期拥有哪类基础权限
ABAC:当前主体、对象、动作和环境满足哪些条件
ReBAC:主体与具体资源之间存在什么关系
它们仍然没有完整表达用户这次究竟把什么交给了 Agent。
例如,客服人员长期拥有 5000 元以内的退款权限。
RBAC 可以判断他属于退款专员角色。
ABAC 可以判断退款金额不超过 5000 元,订单状态也允许退款。
ReBAC 可以判断该订单属于他的处理队列。
但用户说的可能只是:
给订单 A 退 300 元,原因是物流超时。
这次任务并没有授权 Agent 对处理队列中的其他订单退款,也没有授权它连续重试十次。
因此,还需要一个短生命周期的任务授权对象。
任务授权不是换一个角色名称
可以把任务建模为显式对象:
{
"task_id": "refund-task-20260823-001",
"subject_user": "user:customer-service-a",
"actor_agent": "agent:after-sales-v12",
"action": "refund_order",
"resource": "order:20260823001",
"constraints": {
"max_amount": 300,
"max_calls": 1,
"expires_at": "2026-08-23T16:00:00+08:00"
},
"purpose": "物流超时补偿",
"delegation_depth": 0
}
任务不是“临时退款专员”角色。
它是一份有来源、对象、动作、时间和预算边界的 Delegation Grant。
OpenFGA 当前的 Agent 授权指南给出了一种具体建模方式:Agent 默认没有权限,任务开始时才获得所需权限;任务可以绑定到具体工具资源,并增加有效期、最大调用次数、Session 范围和 Agent 绑定。任务结束后,删除相关关系元组以撤销权限。
这个实现证明任务可以成为授权关系中的一等对象。
不过,关系条件能表达“当前调用次数小于上限”,不代表授权系统会自动、原子地增加计数。高风险动作还需要 Action Service 或事务型计数器负责占用预算、避免并发穿透;任务结束后的关系清理也必须成为可靠的生命周期操作,不能只靠约定。
但要注意术语边界:
“任务级授权”是一种架构模式,并非所有产品都遵循同一个统一标准,也不意味着 OpenFGA 是唯一实现。
企业可以用关系授权、PDP、Capability Token、短期 Grant、工作流系统或业务 Action Service 实现同类约束。
四层模型不是四套互相打架的权限系统
很多团队听到 RBAC、ABAC、ReBAC 和任务授权,会担心再造四套权限真相。
如果四层都复制一份完整 ACL,担心是对的。
更合理的做法是分工:
RBAC
→ 管理长期、稳定、可审查的基础职责
ABAC
→ 评估主体、对象、动作和环境条件
ReBAC
→ 查询人与组织、项目、资源、Agent、任务之间的关系
Task Grant
→ 表达用户此次委托的对象、动作、时间、次数和预算
Source System
→ 执行最终记录权限、字段权限、状态机和业务规则
它们不是并列投票,而是逐层收窄。
最终允许
=
用户基础角色权限
∩ 用户与资源关系
∩ Agent 身份允许范围
∩ 当前任务委托
∩ 对象与环境条件
∩ Action 前置条件
∩ 源系统最终校验
任何一层拒绝,操作都不能继续。
一个采购场景
用户提出:
帮华东项目向供应商 A 提交 3 台测试服务器的采购申请,
总金额不超过 10 万元。
RBAC 判断
用户是否具有采购申请人角色?
Agent 是否允许进入采购数据域?
ReBAC 判断
用户是否是华东项目成员?
用户是否可以代表该项目申请采购?
供应商 A 是否属于该项目允许的供应商范围?
Agent 是否绑定到这次任务?
ABAC 判断
采购金额是否低于上限?
设备类别是否允许?
供应商状态是否有效?
当前是否处于预算冻结期?
操作环境风险是否可接受?
Task Grant 判断
只允许华东项目
只允许供应商 A
只允许 3 台测试服务器
累计金额不超过 10 万元
只允许创建草稿和提交审批
有效期 30 分钟
最多提交一次
源系统判断
预算余额是否仍然充足?
采购申请状态机是否允许提交?
必填字段是否完整?
供应商是否刚被停用?
是否命中业务系统的最终 Deny?
如果只使用 RBAC,“采购申请人”这个角色无法独立表达后面所有限制。
如果只使用 ABAC,又可能需要把项目、供应商和任务关系全部展平为动态属性。
如果只使用 ReBAC,金额、时间、库存和风险条件仍然需要其他策略。
组合才是答案。
PDP 应该怎样接收这些信息
一次授权请求可以包含:
{
"subject": {
"user_id": "user:zhangsan",
"roles": ["purchase-requester"],
"org_unit": "org:east-projects"
},
"actor": {
"agent_id": "agent:procurement-assistant",
"agent_version": "7.3.1",
"risk_tier": "MEDIUM"
},
"task": {
"task_id": "task:purchase-001",
"purpose": "采购测试服务器",
"max_amount": 100000,
"max_calls": 1,
"expires_at": "2026-08-23T16:30:00+08:00"
},
"action": "purchase_order.submit",
"resource": {
"project_id": "project:east-2026",
"supplier_id": "supplier:a",
"amount": 96000
},
"environment": {
"current_time": "2026-08-23T16:10:00+08:00",
"risk_score": 18,
"step_up_completed": true
}
}
PDP 可以查询:
- IAM/IGA 提供的角色和身份状态;
- 本体或关系授权系统提供的组织、项目和资源关系;
- Delegation Service 提供的任务 Grant;
- 风险引擎提供的环境属性;
- 业务系统提供的当前对象状态。
决策输出不应只有一个裸 true:
{
"decision": "ALLOW_WITH_OBLIGATIONS",
"policy_version": "policy-2026-08-23.4",
"obligations": {
"max_calls_remaining": 1,
"require_idempotency_key": true,
"require_expected_version": true,
"require_post_action_readback": true
},
"evidence": {
"matched_role": "purchase-requester",
"matched_relation": "member of project:east-2026",
"delegation_grant": "task:purchase-001"
}
}
Action Service 还要执行这些 Obligation,并把下游结果读回。
PDP 的 Allow 不能覆盖源系统的最终 Deny。
不要把组织本体当成权限计算器的唯一数据源
企业本体很适合表达:
Person
Position
Assignment
OrganizationUnit
Project
Responsibility
DataDomain
Agent
Task
BusinessAction
这些数据可以支持 ABAC 和 ReBAC。
但本体中的关系必须有来源、版本和生效时间。尤其不能把自然语言职责直接变成生产权限:
“负责华东销售”
≠
“允许读取华东全部客户明细”
职责可以产生角色候选、关系候选或策略属性,最终权限仍需经过显式政策、委托和源系统校验。
如果本体只是外部业务系统的投影,它更不能复制 ACL 后覆盖原系统 Deny。
权限缓存为什么会成为新风险
组合授权会查询角色、属性、关系和任务状态,性能压力随之增加。
最简单的优化是缓存,但权限缓存可能让已撤销权限继续生效。
Agent 又会高频、并发调用,这会放大缓存陈旧窗口。
需要分别定义:
角色缓存 TTL
关系缓存 TTL
任务 Grant TTL
高风险 Deny 缓存策略
离职和禁用事件的主动失效
PDP 故障时的降级规则
高风险写操作不能只依赖数小时前的组织快照。
离职、Agent 禁用、任务取消和高风险策略变更,应触发主动失效,而不是等待 TTL 自然过期。
子 Agent 不能自动继承父 Agent 的全部权限
多 Agent 系统经常出现这样的调用链:
主 Agent
→ 采购子 Agent
→ 合同审查子 Agent
→ 通知 Agent
如果子 Agent 自动继承父 Agent 的全部权限,委托链会不断扩大攻击面。
任务级授权应遵守不可扩权:
子任务权限
⊆ 父任务权限
OpenFGA 的任务授权指南给出两种模式:共享同一任务,或者创建权限更窄的新任务。
生产环境更稳妥的默认值是:
- 子 Agent 默认无权限;
- 创建显式子任务;
- 仅分配必要动作和资源;
- 限制委托深度;
- 父任务撤销时级联撤销;
- 审计保留完整委托链。
模型决定使用哪个子 Agent,不等于模型有权扩大发放权限。
常见反对意见
“RBAC 加几个条件就够了”
在关系简单、资源规模小、任务不需要细粒度委托的系统中,这完全可能成立。
文章主张的不是必须部署四个独立产品,而是不要遗漏四类语义。它们可以由一个策略引擎实现,也可以由现有 IAM、源系统和 Action Service 分担。
“ABAC 可以表达关系,所以不需要 ReBAC”
理论上可以。关系可以被编码成属性,ReBAC 也可以表达部分角色语义。
选择取决于数据形态和更新方式。如果授权核心是大量、多跳、频繁变化的主体—对象关系,关系模型通常更自然;如果主要是金额、密级、时间和环境条件,ABAC 更直接。
没有必要为了模型纯洁性,把所有问题压进同一种表示。
“任务授权会制造大量临时记录”
是的,所以任务权限必须短生命周期、可批量清理、可按任务索引,并与业务任务状态机绑定。
但不记录任务权限的代价,是让 Agent 在整个用户会话甚至长期服务账号权限范围内持续运行。对于高风险写操作,前者更容易治理。
“源系统已经做最终权限检查,中间层没必要再判断”
低风险、单系统、只读场景可能只需要源系统权限和薄 MCP。
但源系统通常不知道 Agent 版本、任务目的、最大调用次数、跨系统累计金额和用户本次委托范围。高风险 Agent 动作仍需在执行前收窄,源系统再做最终校验。
“任务来自自然语言,无法生成可靠权限”
这正是必须保留人工门和结构化确认的原因。
模型可以把用户意图转换为 Action Proposal,但不能自行批准新增权限。无法确定对象、金额或影响范围时,应请求确认或拒绝,而不是猜测一个更宽的 Grant。
按风险分层落地
不是所有 Agent 都需要完整组合。
低风险只读
RBAC + 源系统 ACL + 短期用户委托
适合读取用户本来可见的数据,且源系统每次都会再次校验。
项目型协作
RBAC + ReBAC + 源系统 ACL
适合文件共享、项目成员、工单继承和资源所有权场景。
条件复杂的业务动作
RBAC + ABAC + Action Predicate + 源系统状态机
适合金额、地域、密级、时间和风险条件明显的操作。
高风险 Agent 写操作
RBAC
+ ABAC
+ ReBAC
+ Task Grant
+ 审批/SoD
+ Action Service
+ 源系统最终 Deny
适合付款、退款、删除、合同审批、批量修改和跨系统副作用。
架构强度应随风险增加,不应让低风险场景的便利路径自动扩展到高风险写入。
建议的落地顺序
第一步:保留现有 RBAC
不要先推翻角色体系。先把它定义为用户和 Agent 的长期权限上限。
第二步:找出角色爆炸的来源
识别哪些角色只是为了表达区域、项目、金额、时间或临时代理。这些维度可能更适合属性或关系。
第三步:把 Agent 和任务变成显式主体
授权请求必须携带 Agent Identity、版本、任务 ID 和委托证据。
第四步:先覆盖高风险动作
为付款、退款、删除、批量修改等动作增加资源范围、TTL、次数、金额和审批约束。
第五步:统一决策证据
每次决策记录角色、属性、关系、Grant、策略版本和源系统结果,避免只留下 allowed=true。
第六步:测试负面路径
至少验证:
- 用户调岗后旧角色失效;
- 项目成员移除后关系失效;
- 任务取消后 Agent 不能继续调用;
- Grant 过期后旧会话不能复用;
- 子 Agent 不能扩大权限;
- 缓存陈旧时高风险动作拒绝;
- 源系统 Deny 不会被 PDP Allow 覆盖。
结论
RBAC 在 Agent 时代仍然不可替代。
它适合管理长期职责、基础权限、角色层级和职责分离,也能继续作为用户权限的稳定上限。
但它通常只回答:
这类主体通常可以做什么?
Agent 生产执行还要回答:
主体与这个资源有什么关系?
当前对象和环境满足什么条件?
哪个 Agent 正在执行?
用户这次到底委托了什么?
允许执行几次,何时失效?
下游业务系统当前是否仍然允许?
因此,长期方案不是 RBAC 与 ABAC、ReBAC 之间选一个赢家,而是让它们承担各自擅长的部分:
RBAC 管长期职责
ABAC 管动态条件
ReBAC 管资源关系
Task Grant 管本次委托
源系统保留最终 Deny
RBAC 没有死亡。
只是当执行者从人变成可以规划、循环和委托子任务的 Agent 时,角色不再足以独自描述完整授权边界。
参考资料
- NIST:Role Based Access Control
- NIST SP 800-162:Guide to Attribute Based Access Control
- Google Research:Zanzibar, Google’s Consistent, Global Authorization System
- OpenFGA:Authorization Concepts
- OpenFGA:Modeling Task-Based Authorization for Agents
- OAuth 2.0 Token Exchange(RFC 8693)
发布摘要
RBAC 没有过时,但它主要解决“这类人通常能做什么”。当 Agent 代表用户自主规划、循环调用工具并委托子任务时,企业还要表达资源关系、运行时条件和本次任务边界。本文用一个采购案例拆解 RBAC、ABAC、ReBAC 与 Task Grant 的分工,并给出逐层收窄、源系统保留最终 Deny 的落地模型。
标签
AI Agent MCP RBAC ABAC ReBAC IAM OpenFGA 权限系统 企业架构 零信任