第十三章:访问控制模型
“授权的本质是回答一个问题:主体 S 能否对客体 O 执行操作 A?”
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 文件权限:
# 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
# 查看 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 层次
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 的组合是最常见的选择