1. RBAC基本概念与模型介绍

咱们直接开门见山。RBAC,全称 Role-Based Access Control,也就是基于角色的访问控制。说白了,它就是一套规则,用来决定“谁可以干什么,在什么条件下干”。

你想想看,在一个稍大点的系统里,用户那么多,权限又细碎。如果直接给人绑权限,那简直是灾难。我早期在部署一个内部密钥管理系统(KMS)时,就踩过这个坑——所有工程师共享一个超级 ,结果谁改了 Secret 版本根本查不到,后来排查了整整三天才定位到问题。从那以后,我成了 RBAC 的坚定信徒。

1.1 为什么我们需要 RBAC?

先看几个核心痛点,你肯定遇过:

  • 权限爆炸:100 个用户,每人 50 个权限,维护起来就是 5000 条记录。改一次权限,全盘都得调。
  • 审计困难:"谁删除了这个 Secret?" 答案永远是 "不知道,可能是张三?"
  • 安全漏洞:开发人员拿着管理员权限去读生产环境的数据库密码。这合理吗?

RBAC 的解决思路其实很简单——引入“角色”这个中间层。用户不直接跟权限打交道,他们只跟角色绑定。权限全部挂在角色下面。这样一来,哪怕系统里有 1000 个用户,我只要管好“管理员”、“开发者”、“审计员”这10来个角色就行。

一句话总结:RBAC 的核心是“用户 → 角色 → 权限”的三层映射。角色是权力的容器,用户是权力的执行者。

1.2 核心术语,必须搞懂

这些术语在后续章节会反复出现,建议你先建立肌肉记忆。

术语 定义 在 Secrets 中的例子
用户 (User) 系统中的一个实体,可以是一个人、一个服务账号或一个应用程序。 你的 Jenkins CI 服务账号需要读取数据库密码。
角色 (Role) 一组权限的集合。它是绑定的最小单元。 “只读角色”只能查询 Secret 版本,不能创建或删除。
权限 (Permission) 对某个资源执行特定操作的许可。 对路径 secret/production/db 执行 read 操作。
会话 (Session) 用户激活角色后的临时上下文。用户可以在一次会话里切换不同的角色。 运维人员在日常维护时激活“只读”角色,只在故障恢复时临时激活“管理员”角色。
约束 (Constraint) 对角色或权限的额外限制条件,比如时间、IP 范围、设备指纹。 “管理员角色”只能在公司 VPN 内部使用,且不能从非工作时间登录。
我的习惯:我在做系统设计时,会先把所有权限写成 Action + Resource 的形式。比如 read:secrets/*。这样后期转换成权限策略时,几乎不用改代码。

1.3 三张表帮你理清“谁、角色、权限”的关系

数据库层面,RBAC 落地其实就是几张关系表。我直接给你最精简的模型,你在项目里可以直接复用。

表1:用户表 (users)

user_id | user_name  | email
------- | ---------- | -------------------
1       | zhangsan   | zhangsan@corp.com
2       | lisi       | lisi@corp.com

表2:角色表 (roles)

role_id | role_name      | description
------- | -------------- | ---------------------
1       | secret_admin   | 管理所有 Secret 的生命周期
2       | secret_reader  | 仅可读取已存在的 Secret
3       | secret_rotator | 可读取并轮换密钥

表3:权限表 (permissions)

perm_id | resource_path          | action  | role_id
------- | ---------------------- | ------- | -------
1       | secret/production/*    | read    | 2
2       | secret/production/*    | write   | 1
3       | secret/development/*   | read    | 2
4       | secret/development/*   | write   | 1

你注意看,用户张三在用户表里只存了 ID,权限全是通过角色 ID 去查。改一次角色,所有绑定这个角色的人权限都变了。

我曾经踩过的坑:别把“角色”当“用户”用。团队里有人偷懒,直接给 Jenkins 建了 10 个角色,每个角色只对应一个服务账号。最后角色表膨胀到 200 个,维护成本比直接绑权限还高。角色一定要做抽象——比如“只读”、“读写”、“管理”这三类就够了。

1.4 RBAC 模型的四个级别

官方标准把 RBAC 分成了 4 个等级,从基础到复杂。你至少需要掌握 RBAC0 和 RBAC1。

模型等级 核心特性 是否常用于 Secrets 管理? 我的评价
RBAC0 基本模型:用户 ↔ 角色 ↔ 权限 是,绝大多数场景适用 够用、安全。推荐所有新项目起步就用。
RBAC1 支持角色继承。子角色拥有父角色的权限。 有时需要 如果你有严格组织结构(如大部门套小部门),这个很香。
RBAC2 引入约束:互斥角色、先决条件角色、数量限制等。 部分场景 用于合规场景,比如“不能同时拥有创建和审计权限”。
RBAC3 RBAC1 + RBAC2 的完整组合。 很少 要不是做金融或国防系统,RBAC0 就够了。

我个人最常用 RBAC0 + 少量约束。比如在 Vault 中,我给“开发者”角色添加一个约束:valid_ip: 10.0.0.0/8。这样就相当于自带了一层网络隔离。嗯,这点要注意——约束不一定需要数据库字段支持,有时候在 API 层做拦截也够用。

关于角色继承的一个例子: 假设有“超级管理员”角色(权限:所有操作),和“项目管理员”角色(权限:仅对项目 A)。如果项目管理员继承了超级管理员,那么他也能对项目 B 操作。这在某些场景下是漏洞,一定要明确继承关系才启用 RBAC1。

1.5 一张图看懂本章的核心模型

RBAC 核心组件关系图 🔑 用户 (User) zhangsan, jenkins 📝 会话 (Session) 临时上下文 🎭 角色 (Role) secret_reader ✅ 权限 (Permission) read:secrets/* ⚠️ 约束 (Constraint) IP, 时间, 设备 📌 关系说明 用户 → 会话 → 角色 → 权限 约束可以施加在角色或权限上
怎么用这张图?当你在设计你的 Secrets 管理系统(无论是 HashiCorp Vault、AWS Secrets Manager 还是自研系统)时,你可以把每个用户登录的行为看作创建了一个“会话”。在这个会话里,用户激活某个“角色”,从而获得一组“权限”。图上红色的“约束”框是容易被忽略的——我见过太多系统因为没加 IP 白名单,导致外网可以访问内部接口。

1.6 RBAC 在 Secrets 管理中的初步落地

咱们拿一个实际场景来收尾。假设你是一个 100 人团队的 SRE,需要管理三个环境:dev、staging、production。

你可能会这样设计角色和权限:

  1. 角色:dev-admin、staging-admin、prod-readonly、prod-admin
  2. 权限:
    • dev-admin 可以读写 secret/dev/*
    • staging-admin 可以读写 secret/staging/*
    • prod-readonly 只能读 secret/prod/*
    • prod-admin 可以读写 secret/prod/*
  3. 用户分配:
    • 全栈工程师:所有 dev 角色 + staging 角色
    • 运维主管:所有环境所有角色
    • QA 工程师:仅 dev-readonly 角色

代码层面,你可能会写出这样的策略配置(以 JSON 格式举例):

{
  "role": "prod-readonly",
  "policies": [
    {
      "path": "secret/prod/*",
      "capabilities": ["read", "list"]
    }
  ],
  "constraints": {
    "allowed_ip": ["10.0.0.0/8", "172.16.0.0/12"],
    "valid_time": "09:00-18:00"
  }
}
记住这个原则:在 Secrets 管理中,权限应该尽量窄。你宁可一开始给少了,后续再加,也别一开始给多了,后面改起来一堆人受影响。我有个习惯,叫做“最小权限 + 动态提升”——默认只给只读角色,需要做变更时,通过审批流程临时提升到写权限。

好了,这一节的概念就到这里。内容比较多,但你只要记住“用户 → 角色 → 权限”这个三层模型,以及角色是权限的容器这个核心思想,后面的理解就会轻松很多。