场景

权限越给越多、无人回收、默认角色里夹带了不该有的权限——这是 IAM 系统最常见的退化路径。本指南聚焦如何在日常运维中落地最小权限原则,不重复概念定义,只讲可操作的步骤和反模式。

适用:正在设计或治理企业 IAM 权限体系、需要等保合规(三级要求强制最小权限)、Keycloak 权限爆炸的管理员和架构师。

不适用:概念阶段还没开始配权限的团队(先读 IAM RBAC/ABAC/ReBAC 授权模型)。

常见反模式

在讨论怎么做之前,先识别当前权限设计中的「最小权限杀手」:

反模式表现后果
admin 扩散每个新应用都创建 admin 角色,开发时为了方便先给所有人 admin审计时发现 30% 用户有管理员权限
角色继承失控为了省事让「员工」继承「经理」的角色权限,再让「实习生」也继承实习生能审批报销单
权限永不过期临时项目组的权限在项目结束后无人回收离职人员通过项目组权限仍然能访问资产
默认允许Keycloak Authorization Services 没配 Policy,默认返回 Permit所有认证用户都能访问所有资源
粗粒度角色一个 power-user 角色包含 200 个权限,无法拆分权限审计无法回答「谁能删除生产数据」
权限复制粘贴给新同事「跟老王一样的权限就行」老王五年前的临时权限也被继承了

识别出反模式后,下面的模式帮你逐一收敛。

落地模式

模式一:角色粒度分层

不创建「全能角色」,而是按业务职能拆分为原子角色,用 Composite Roles 组合:

[订单查看]  [订单编辑]  [订单删除]  [报表导出]  [用户管理]
     │           │           │           │           │
     └───────────┴─────┬─────┴───────────┘           │
                       │                             │
                  [订单管理员]                   [系统管理员]
              (Composite Role)               (Composite Role)

Keycloak 操作:在 Realm Roles 中创建原子角色,再用 Composite Roles 把原子角色组合成业务角色。用户→Group→Composite Role,不直接给用户赋原子角色。

为什么这么做:一年后需要「只能查看不能删除」的新角色时,从原子角色池里重新组合,而不是新建一个 订单查看员 角色然后又忘了删旧的。

模式二:Just-in-Time (JIT) 权限提升

运维人员日常只用普通账号,需要操作生产环境时临时提权,操作完成后自动降级。

正常状态: user → viewer (只读)
提权申请: user → operator (5 分钟,需审批)
自动降级: 5 分钟后 operator → viewer

Keycloak 实现方式

  1. 创建 operator 角色(Realm Role),不要直接分配给用户
  2. 创建一个临时 Group(如 temp-operator-20260711),将 operator 角色赋予该 Group
  3. 审批通过后,将用户加入该 Group,同时设置一个定时任务(如 Keycloak Admin REST API 调用 + CronJob)在到期后移除
  4. 所有角色变更事件通过 Admin Events 审计

Keycloak 原生不支持 Time-based Role,需要外部编排。对于简单场景,可以用一个脚本:kcadm.sh add-roles --uusername alice --rolename operator → sleep 300 → kcadm.sh remove-roles --uusername alice --rolename operator,配合审批工单系统触发。

模式三:默认拒绝 + 显式允许

Keycloak Authorization Services 的决策策略默认是「UNANIMOUS」(所有策略都通过才允许),但很多团队在配置时因为不熟悉而切换为「AFFIRMATIVE」甚至留空默认的 Permit 策略。

底线配置检查

# 检查某 Client 的 Authorization Settings
# 确保 Default Policy 不是 Permit All
kcadm.sh get clients/CLIENT_ID/authz/resource-server/settings -r REALM

# 确认 decisionStrategy = "UNANIMOUS"
# 确认 defaultResourceType 的 scope 策略没有通配符

每个 Client 的 Authorization 上线前 checklist

  • 至少有一个 Deny Policy 作为兜底
  • 新 Resource 的默认策略不是 Permit
  • Policy Evaluation 验证过:无权限用户返回 Deny
  • 管理员角色不受 Authorization Services 限制(避免把自己锁在外面)

模式四:定期权限审计

IAM 权限不是「配置一次就完了」的东西。以下审计节奏是生产环境的底线:

频率检查项工具/方式
每周是否有超过 7 天未使用的 admin 角色分配Keycloak Admin REST API → GET /admin/realms/{realm}/roles/{role}/users + 最后登录时间对比
每月角色-权限矩阵与实际授权是否一致导出 Realm JSON,用脚本对比预期 vs 实际
每季度完整权限回收:离职员工账号禁用、临时项目组清理、过期角色归档结合 HR 系统离职名单交叉比对
每半年渗透测试:用一个 viewer 账号尝试访问 admin 接口安全团队专项测试

Keycloak 权限审计脚本示例(获取某角色的所有用户):

# 获取 admin 角色的所有直接用户
kcadm.sh get-roles -r REALM --uusername admin --effective --role-role admin_user

# 导出所有用户的角色分配
kcadm.sh get users -r REALM --max 500 | jq '.[] | {username: .username, roles: .realmRoles}'

与等保 2.0 的对应关系

等保三级明确要求「最小权限」和「强制访问控制」。对照本指南:

等保要求对应模式证据
账户-权限绑定模式一 角色粒度分层角色-权限矩阵表
最小权限模式三 默认拒绝Policy Evaluation 记录
授权粒度到用户级模式一 + 模式二逐用户角色分配记录
定期审计模式四 权限审计季度审计报告

详细等保落地 Checklist 参见 IAM 安全合规与等保 2.0

验证

完成以上配置后,用以下测试用例验证最小权限是否生效:

# 1. 用 viewer 账号获取 token
TOKEN=$(curl -s -X POST "https://keycloak.example.com/realms/REALM/protocol/openid-connect/token" \
  -d "client_id=CLIENT_ID" -d "username=viewer" -d "password=PASS" \
  -d "grant_type=password" | jq -r '.access_token')

# 2. 尝试访问 admin 接口 → 期望返回 403
curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: Bearer $TOKEN" \
  "https://api.example.com/admin/users"

# 3. 检查 Token 中的角色是否不包含 admin
echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null | jq '.resource_access'

常见错误

症状原因解决
所有认证用户都能调 admin APIAuthorization Services 的默认策略是 Permit 或未启用启用 Authorization,将默认策略改为 Deny
给用户去掉了 admin 角色但仍然能访问用户通过 Group 间接持有 admin 角色(Effective Roles 包含 Group 传递的角色)--effective 参数检查实际生效的角色
Policy Evaluation 显示 Permit 但实际 DenyAuthorization Scopes 配置了但 Resource 没有关联 Scope检查 Resource → Scopes 关联
复合角色中的子角色权限丢失Composite Roles 中的子角色被误删或改名用 Realm JSON 导出做 diff
JIT 提权到期后权限未回收定时任务失败或 Keycloak API 调用超时JIT 权限必须配合监控告警——提权超过 N 分钟未回收时触发 PagerDuty

回滚

如果最小权限策略配得太严导致业务中断:

  1. 紧急回滚:通过 Keycloak Admin Console → Users → 对受影响用户临时赋 admin 角色,恢复访问
  2. 分层回滚:不要删掉整个 Authorization Services 配置——在 Policy 层面将目标 Policy 的 Logic 从 Positive 改为 Negative,或增加一个临时的宽松 Policy
  3. 事后修复:用 Admin Events 日志追溯是谁在什么时间改了哪个 Policy,复盘「为什么测试时没发现」

IAM 最小权限 FAQ

Q1:IAM 里最小权限和 RBAC 有冲突吗?

不冲突,但 RBAC 的默认行为倾向于「角色越多权限越大」。最小权限要求在 RBAC 基础上加三层约束:(1) 角色粒度足够细(原子角色);(2) 默认拒绝而非默认允许;(3) 权限分配有时间边界(JIT 或定期回收)。

Q2:公司刚起步,IAM 权限从什么粒度开始?

三个阶段:

  1. 10 人以下:admin / user 两个角色就够了。但必须约定「admin 是紧急权限,日常用 user」。
  2. 10-50 人:引入职能角色(开发、运维、财务、人事),每个角色 3-5 个权限。开始用 Keycloak Groups 做组织映射。
  3. 50 人以上:参考本指南的模式一「角色粒度分层」,开始做季度权限审计。

关键不是一开始就完美,而是让权限变更可追溯——哪怕只有两个角色,每次角色分配都有一条审计记录。

Q3:IAM 最小权限和零信任是什么关系?

零信任架构的三条核心原则之一是「最低权限访问」。在零信任体系中,IAM 的职责不仅是给你一个角色——而是每次访问都根据用户身份、设备状态、网络位置、行为风险做实时决策。本指南的模式二(JIT 提权)和模式三(默认拒绝)就是零信任理念在 IAM 权限管理中的落地形式。更多架构细节见 零信任 IAM 架构

Q4:已经权限爆炸了,IAM 怎么往回改?

三步走:

  1. 盘点:导出所有用户-角色-权限映射(参考模式四的脚本),找出「一人多角色」和「从未使用的角色」。
  2. 冻结:暂停新增角色。所有新权限需求通过已有的原子角色组合满足,不再创建新角色。
  3. 收敛:每两周清理一批 3 个月未使用的角色。清理前提前一周通知受影响用户。

这个过程通常需要 2-3 个月。关键是第一步的盘点——不知道有多少问题就没法解决问题。

相关阅读