一个跑了三年以上的系统,权限表通常长成同一个形状:条目只增不减,审批记录齐全,但没人能回答"谁今天还能写生产库"。这不是审批环节坏了——入职授权、上线扩容都走过流程;坏的是从来没有一个环节把权限拿回来。
权限复审要解决的从来不是"有没有权限",而是"这个权限还有人需要吗"。这两句话的差别决定了复审表怎么设计:前者查的是事实,后者要的是判断。
1. 从"有没有"到"还需不需要"
| 提问方式 | 得到的结果 | 复审产出 |
|---|---|---|
| 这个账号有生产库写权限吗 | 有 | 无,只是确认了现状 |
| 还有谁需要这个写权限 | 两个人 | 收回清单 |
| 这个权限上次被用是什么时候 | 十一个月前 | 到期时间 |
| 谁能在今天证明自己还需要它 | 缺席的那个审批人 | 默认不续 |
四行里只有最后一行能让权限真的减少。前两行都是存在性检查,它天然导向批量确认——答案显而易见,审批人不会为它花时间。
一条权限记录要能被复审,至少要回答四件事:
// 权限条目:四要素缺一不可,缺哪个哪个就是盲区
grant_id: G-2023-0441
subject: svc-order-sync // 谁:人 / 服务账号 / 机器身份
resource: prod/mysql/order_db // 对什么:库、表、bucket、集群
action: write // 能做什么:读、写、管理、删除
expires_at: 2026-03-31 // 多久:为空则视为三个月后到期
source: ticket/OPS-8821 // 授予依据:工单、变更单、合同
常见的坏记录是 expires_at 为空、action 写成 admin、resource 写成 *。这三个字段只要有一个是空值或通配,复审就退化成"看账号名猜用途"。
2. 三种触发与各自的覆盖率
| 触发 | 覆盖范围 | 典型频率 | 稳定性 | 漏掉什么 |
|---|---|---|---|---|
| 定期复审 | 全量或抽检 | 季度 / 半年 | 高,可排期 | 两次复审之间发生的越权 |
| 离职、转岗 | 该主体的全部权限 | 事件驱动 | 依赖人事数据同步 | 外包、外部人员、服务账号 |
| 异常访问后 | 涉事资源的相关权限 | 不可预期 | 低,常被并进事故处理 | 同类资源上的同样问题 |
三者不是互相替代,而是互相补洞:定期复审保底,事件触发抓时效。判断一个团队是否真的在做复审,只要看"离职当天权限是否清零"——这一项的覆盖率最能暴露流程有没有接上人事数据。
3. 复审失效的三个机制
| 机制 | 表现 | 为什么发生 | 纠偏手段 |
|---|---|---|---|
| 审批人不懂 | 秒过 | 审批人离资源太远,看不懂用途 | 审批人改成资源负责人,而非直属上级 |
| 批量确认 | 一次勾几十条 | 单条决策缺依据,只能整批处置 | 每条必须附"最近一次使用时间" |
| 没人敢收回 | 全部保留 | 收回权限的后果无人负责 | 默认不续:不填保留理由即到期 |
后两条叠加时最危险:表格里全是"最近使用时间未知",审批人既不敢收也没法判断,于是批量通过——这就是"通过率 100% 的复审等于没做"的成因。这个指标可以反向使用:通过率接近 100%,说明复审表格没有提供决策依据,而不是说明权限都很合理。
// 复审表单最小列:没有 last_used 的表格等于走过场
subject resource action last_used owner keep_reason new_expiry
4. 复审的最小输出
一次复审只有同时产出下面三类东西才算完成:
─── 收回清单 ───
G-2023-0441 svc-order-sync prod/mysql/order_db:write 依据:近 12 个月零调用
─── 保留理由 ───
G-2024-0117 alice prod/mysql/order_db:read 依据:值班排障,近 90 天有 3 次调用
─── 到期时间 ───
G-2025-0002 bob prod/oss/backup:write 到期 2026-03-31,默认不续
三样缺一不可:只给收回清单,其余权限会慢慢长回来;只给保留理由,等于没做任何决定;只给到期时间,等于把问题推给下个季度。
5. 按持有者分类,节奏不同
| 持有者 | 典型风险 | 复审节奏 | 关键动作 |
|---|---|---|---|
| 人持有的 | 离职、转岗后残留 | 季度,另加事件触发 | 与人事数据对齐 |
| 服务持有的 | 权限过宽、长期不回收 | 半年级,随架构变更 | 核对服务的实际调用面 |
| 机器持有的 | 实例身份、证书被忽略 | 与密钥轮换合并 | 列入密钥清单统一登记 |
服务账号是最容易漏的一类:它不参加离职流程,也不会"忘记"自己有什么权限,因此永远不会主动暴露。核对方法不是问负责人,而是看调用记录——权限集合与实际调用面的差集,就是可收回部分。
─── 从调用侧反推:实际用到的动作通常远窄于授予范围 ───
mysql -e "SHOW GRANTS FOR 'svc-order-sync'@'%'" // 先看授予,再与调用日志比对
SELECT user, host, COUNT(*) FROM mysql.general_log GROUP BY 1,2 // 需先开启通用日志,按版本核对字段名
6. 粒度:按人审还是按资源审
| 粒度 | 好处 | 盲区 |
|---|---|---|
| 按人审 | 与离职、转岗流程天然对齐 | 看不到"一个资源上有多少人能碰" |
| 按资源审 | 能收敛高敏感资源的持有面 | 看不到"一个人身上攒了多少权限" |
| 混合:季度按资源、事件按人 | 两个盲区都覆盖 | 维护两套口径,需要去重 |
高敏感资源(生产库写、密钥读取、账单与结算)适合按资源审;一般资源按人审足够。只做一种粒度时,选"谁能动最贵的东西"的那一侧。
7. 临时权限必须自带到期时间
// 临时授权:默认不续,续期要重新给理由,而不是点一下按钮
temporary_grant:
subject: oncall-rotation
resource: prod/k8s/namespace-web
action: exec
expires_at: 2026-03-31T23:59:59+08:00
renewal: manual
renew_reason_required: true
expire_check: nightly
"默认不续"是这套机制的核心:如果续期和申请一样便宜,临时权限就会变成永久权限。到期前的提醒只发给持有者,不发给审批人——提醒审批人只会引发一次批量续期。
8. 复审与最小权限的关系
最小权限是设计问题,复审是纠偏问题。设计得好,复审只做减法;设计得差,复审永远在补旧账。
─── 两者的分工 ───
设计侧:新权限默认最小、默认带到期时间、按角色授予而非按人授予
复审侧:把已经偏离的记录收回,并把偏离原因反馈给设计侧
反馈通道:同一类权限每季度都要收回一次,说明角色定义有问题
判断复审是否被过度使用:如果每轮收回清单都是"同类权限、同类原因",要改的是角色设计,而不是提高复审频率。
9. 度量
| 指标 | 看什么 | 参考方向 |
|---|---|---|
| 权限总量趋势 | 条数与覆盖面是否单调上升 | 应趋于平稳并缓慢下降 |
| 权限存活期 | 从授予到收回的时长中位数 | 临时权限应落在授权期附近 |
| 收回率 | 每轮收回条数占复核条数之比 | 长期为 0 说明复审无效 |
| 异常访问数 | 使用了本不该有的权限的次数 | 复审质量的滞后指标 |
前三个是过程指标,最后一个是结果指标。只看结果指标要等事故发生,只看收回率会诱导无意义的收回——两者必须一起看。
10. 季度复审的操作形状
复审不应是一张巨大的 Excel,而是一条有固定终点的流水线:
| 步骤 | 产出 | 谁做 |
|---|---|---|
| 导出快照 | 权限全量 + 最近调用时间 | 系统自动 |
| 分桶 | 高敏感 / 一般 / 只读 | 系统按资源标签 |
| 判断 | 收回 / 保留 / 缩短到期 | 资源负责人 |
| 执行 | 收回清单落地到系统 | 平台侧 |
| 复核 | 抽样验证收回是否生效 | 非执行人 |
判断环节的平均耗时最能说明表格质量:一条要花两分钟以上才能决定,说明依据不够;一秒一条,说明在批量点确认。
─── 收回后必须验证生效,而不是发出通知就算完 ───
revoke --subject svc-order-sync --resource prod/mysql/order_db --action write
verify --subject svc-order-sync --expect DENY // 期望被拒,而不是期望无报错
11. 下个季度的输入从哪来
复审的长期有效依赖一个闭环:本轮的收回清单,要变成下一轮的检查项。
// 复审闭环登记:每一项都指向下一轮要比对的字段
review_cycle:
quarter: 2026-Q1
revoked: 12 // 本轮收回条数
top_reason: unused_90d
next_check:
- prod/mysql/*:write // 上一轮问题最集中的资源类型
- role: order-ops // 角色定义是否已收紧
没有这个登记,复审会年复一年处理同一批问题。
12. 排错:复审做不下去的常见原因
| 现象 | 原因 | 处理 |
|---|---|---|
| 表格填不完 | 复核对齐了全量,而非关键资源 | 先覆盖高风险资源,其余抽检 |
| 审批人不敢收 | 没有使用记录作依据 | 补最近调用时间,收回不再是判断题 |
| 服务账号反复被漏 | 它不在任何人员名单里 | 纳入密钥与配置清单统一登记 |
| 到期没有生效 | 自动过期没有明确执行者 | 过期由系统执行,不依赖人工清理 |
13. 边界:什么时候人工复审可以降级
| 条件 | 可降级到 | 理由 |
|---|---|---|
| 团队三人以下 | 不做定期复审,只保留事件触发 | 每个人手上的权限都在公开视野内 |
| 无生产数据、无付费资产 | 年度抽检 | 误授权的爆炸半径有限 |
| 已有强制的自动过期机制 | 季度抽查 | 默认不续已承担主要纠偏 |
三种条件同时成立时,人工复审的边际收益接近零。反过来,只要有一个条件不成立——有生产数据、有人数规模、或没有自动过期——人工复审就是必需项,不能靠"文化自律"代替。
14. 自测
- 复审表格里缺哪一列,会让审批人只能做批量确认?
- 为什么"离职当天权限是否清零"比"季度复审是否完成"更能反映流程质量?
- 服务账号为什么不参加离职流程,也不会主动暴露自己?
- 按资源审与按人审各自的盲区是什么?混合粒度要付出什么代价?
- 临时权限的续期为什么不设成和申请一样便宜?
- 如果每轮复审收回的都是同一类权限、同一个原因,该改的是哪一侧?