# 第十三章:访问控制模型 > "授权的本质是回答一个问题:主体 S 能否对客体 O 执行操作 A?" ```{mermaid} mindmap root((访问控制模型)) DAC 文件权限 ACL MAC Bell-LaPadula SELinux RBAC 角色 层次 约束 ABAC 属性 策略 XACML ReBAC Zanzibar 关系元组 图遍历 ``` ## 13.1 访问控制基本概念 访问控制的核心要素: ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 主体(S) │───▶│ 操作(A) │───▶│ 客体(O) │ │ Subject │ │ Action │ │ Object │ │ 用户/服务 │ │ 读/写/删 │ │ 文件/API │ └──────────┘ └──────────┘ └──────────┘ │ ▼ ┌──────────┐ │ 策略(P) │ │ Policy │ │ 允许/拒绝 │ └──────────┘ ``` ## 13.2 DAC — 自主访问控制 DAC(Discretionary Access Control)由资源拥有者决定谁可以访问。最典型的例子是 Unix 文件权限: ```bash # Unix 文件权限 -rwxr-xr-- 1 alice developers 4096 Jan 1 00:00 report.txt │├─┤├─┤├─┤ │ │ │ └── 其他用户:只读 │ │ └───── 组(developers):读+执行 │ └──────── 拥有者(alice):读+写+执行 └────────── 文件类型 # ACL(访问控制列表)— 更细粒度 setfacl -m u:bob:rw report.txt # 给 bob 读写权限 setfacl -m g:audit:r report.txt # 给 audit 组只读权限 getfacl report.txt # 查看 ACL ``` **优点**:简单直观、灵活 **缺点**:难以集中管理、容易权限蔓延 ## 13.3 MAC — 强制访问控制 MAC(Mandatory Access Control)由系统强制执行安全策略,用户无法更改。 ### Bell-LaPadula 模型(保密性) ``` 安全级别:绝密 > 机密 > 秘密 > 公开 规则: • No Read Up(简单安全属性):不能读高于自己级别的数据 • No Write Down(*属性):不能写低于自己级别的数据 ┌──────────┐ │ 绝密 │ ← 绝密用户可读写 │ │ ← 机密用户不能读(No Read Up) ├──────────┤ │ 机密 │ ← 机密用户可读写 │ │ ← 绝密用户不能写(No Write Down) ├──────────┤ │ 秘密 │ ├──────────┤ │ 公开 │ └──────────┘ ``` ### SELinux ```bash # 查看 SELinux 上下文 ls -Z /var/www/html/index.html # system_u:object_r:httpd_sys_content_t:s0 index.html # SELinux 策略:httpd 进程只能访问 httpd_sys_content_t 类型的文件 # 即使 httpd 被攻破,也无法访问其他类型的文件 ``` ## 13.4 RBAC — 基于角色的访问控制 RBAC(Role-Based Access Control)通过角色间接授权: ``` 用户 ──▶ 角色 ──▶ 权限 ┌──────┐ ┌──────────┐ ┌──────────────┐ │ Alice │───▶│ Admin │───▶│ user:read │ │ │ │ │ │ user:write │ └──────┘ └──────────┘ │ user:delete │ │ config:write │ ┌──────┐ ┌──────────┐ └──────────────┘ │ Bob │───▶│ Editor │───▶│ doc:read │ │ │ │ │ │ doc:write │ └──────┘ └──────────┘ └──────────────┘ ┌──────┐ ┌──────────┐ ┌──────────────┐ │Carol │───▶│ Viewer │───▶│ doc:read │ └──────┘ └──────────┘ └──────────────┘ ``` ### RBAC 层次 ```python from enum import Enum from dataclasses import dataclass, field class Permission(Enum): READ = "read" WRITE = "write" DELETE = "delete" ADMIN = "admin" @dataclass class Role: name: str permissions: set[Permission] parent: 'Role | None' = None # 层次 RBAC def has_permission(self, perm: Permission) -> bool: if perm in self.permissions: return True if self.parent: return self.parent.has_permission(perm) return False # 角色层次:Admin > Editor > Viewer viewer = Role("viewer", {Permission.READ}) editor = Role("editor", {Permission.WRITE}, parent=viewer) admin = Role("admin", {Permission.DELETE, Permission.ADMIN}, parent=editor) assert admin.has_permission(Permission.READ) # 继承自 viewer assert admin.has_permission(Permission.WRITE) # 继承自 editor assert admin.has_permission(Permission.DELETE) # 自身权限 assert not viewer.has_permission(Permission.WRITE) # 无此权限 ``` ### RBAC 的局限性 | 问题 | 描述 | |------|------| | 角色爆炸 | 细粒度需求导致角色数量指数增长 | | 缺乏上下文 | 无法表达"只在工作时间访问" | | 资源级控制弱 | 难以表达"只能访问自己的文档" | | 动态权限难 | 权限变更需要修改角色定义 | ## 13.5 ABAC — 基于属性的访问控制 ABAC 基于属性做出授权决策,更加灵活: ``` ABAC 决策过程: ┌──────────────────────────────────────────────┐ │ 主体属性 │ 角色=editor, 部门=engineering │ │ 资源属性 │ 类型=document, 密级=internal │ │ 操作属性 │ 动作=edit │ │ 环境属性 │ 时间=工作日, IP=内网 │ ├──────────────────┴──────────────────────────────┤ │ 策略: │ │ IF 主体.角色 == "editor" │ │ AND 资源.密级 <= "internal" │ │ AND 环境.时间 IN 工作时间 │ │ AND 环境.IP IN 内网范围 │ │ THEN 允许 edit │ └──────────────────────────────────────────────────┘ ``` ### RBAC vs ABAC 对比 | 维度 | RBAC | ABAC | |------|------|------| | 授权依据 | 角色 | 属性(多维度) | | 粒度 | 粗粒度 | 细粒度 | | 灵活性 | 低 | 高 | | 复杂度 | 低 | 高 | | 上下文感知 | ❌ | ✅ | | 动态策略 | 困难 | 容易 | | 审计 | 简单 | 复杂 | | 适用规模 | 中小型 | 大型 | ## 13.6 ReBAC — 基于关系的访问控制 ReBAC(Relationship-Based Access Control)基于实体之间的关系做出授权决策。Google 在 2019 年发表的 Zanzibar 论文奠定了 ReBAC 的基础。 ### Google Zanzibar Zanzibar 是 Google 内部的全球授权系统,服务于 Google Drive、YouTube、Cloud 等产品。 核心概念 — **关系元组(Relation Tuple)**: ``` 格式:object#relation@subject 示例: document:budget#reader@user:alice → alice 是 budget 文档的 reader document:budget#reader@group:finance#member → finance 组的所有 member 都是 budget 文档的 reader folder:engineering#viewer@folder:root#viewer → root 文件夹的 viewer 也是 engineering 文件夹的 viewer(继承) ``` ### 为什么 ReBAC 是未来趋势 ``` RBAC 的问题: "Alice 能编辑文档吗?" → 只能回答"能"或"不能" 无法区分"Alice 能编辑哪些文档" ReBAC 的优势: "Alice 能编辑文档 X 吗?" → 检查 Alice 与文档 X 的关系 "Alice 能编辑哪些文档?" → 遍历 Alice 的所有关系 关系图: user:alice ──reader──▶ document:budget user:alice ──member──▶ team:engineering team:engineering ──parent──▶ org:acme org:acme ──viewer──▶ folder:shared folder:shared ──parent──▶ document:roadmap → Alice 可以查看 roadmap(通过关系链推导) ``` ## 13.7 访问控制模型对比 | 模型 | 授权依据 | 粒度 | 复杂度 | 适用场景 | |------|---------|------|--------|---------| | DAC | 资源拥有者决定 | 中 | 低 | 文件系统 | | MAC | 安全标签 | 高 | 高 | 军事/政府 | | RBAC | 角色 | 粗 | 低 | 企业应用 | | ABAC | 属性 | 细 | 高 | 复杂策略 | | ReBAC | 关系 | 细 | 中 | 协作应用、SaaS | ### 选型决策树 ``` 你的授权需求是什么? │ ├── 简单的角色权限? │ └── ✅ RBAC(大多数应用的起点) │ ├── 需要上下文感知?(时间、位置、设备) │ └── ✅ ABAC(OPA/Cedar) │ ├── 需要资源级别的细粒度控制? │ ├── 资源之间有层次/继承关系? │ │ └── ✅ ReBAC(OpenFGA) │ └── 基于属性的条件? │ └── ✅ ABAC + ReBAC 组合 │ └── 以上都需要? └── ✅ ReBAC(OpenFGA)+ ABAC(OPA)组合 ``` ## 13.8 小结 - **DAC** 简单但难以集中管理,适合文件系统 - **MAC** 安全性最高但灵活性最低,适合军事/政府 - **RBAC** 是最普及的模型,但存在角色爆炸和粒度不足的问题 - **ABAC** 通过多维属性实现细粒度控制,但策略管理复杂 - **ReBAC** 基于 Google Zanzibar,通过关系图实现直观的细粒度授权 - 实际项目中,**RBAC + ReBAC** 或 **RBAC + ABAC** 的组合是最常见的选择