一句话总结
RBAC 控制"谁能对什么资源做什么操作", 准入控制在资源创建/修改时拦截并校验请求.
两者结合实现: 人不能做超权操作(RBAC), 资源不能违反安全规范(Admission Controller).
RBAC 回顾与深入
K8s 08 篇概览了 RBAC 四件套. 本篇从安全视角深入: 如何设计最小权限, 常见过度授权问题, ServiceAccount 的安全隐患.
四件套回顾
| 对象 | 作用域 | 含义 |
|---|---|---|
| Role | Namespace | 定义"能对哪些资源做什么" |
| ClusterRole | 集群 | 跨 Namespace 的权限定义 |
| RoleBinding | Namespace | 把 Role 绑定给用户/组/ServiceAccount |
| ClusterRoleBinding | 集群 | 把 ClusterRole 绑定给全集群 |
RBAC = 酒店的房卡系统.
Role = 一张房卡能开哪些门(104 房间 + 泳池).
RoleBinding = 把这张房卡发给谁(张三).
ClusterRole = 万能房卡模板(能开所有楼层).
ClusterRoleBinding = 把万能卡发给酒店经理. 普通住客只需要自己楼层的房卡, 给所有人发万能卡就是安全灾难.
最小权限设计原则
|
最危险的权限组合
secrets的list权限 = 可以读取 Namespace 内所有密钥pods/exec权限 = 可以进入任何 Pod 执行命令(等于拥有 Pod 的全部权限)*通配符 = 对所有资源的所有操作
审计 RBAC 时重点检查这三类.
ServiceAccount 安全
默认 SA 的风险
每个 Namespace 有一个 default ServiceAccount, 所有未指定 SA 的 Pod 自动使用它. 问题:
- 如果给
defaultSA 绑定了 Role → 该 Namespace 的所有 Pod 都获得这个权限 - SA Token 自动挂载到 Pod 的
/var/run/secrets/kubernetes.io/serviceaccount/token - 攻击者进入任意 Pod → 可以用这个 Token 调用 K8s API
最佳实践
|
三条铁律
- 每个服务用专属 ServiceAccount, 不共用 default
- 不需要调用 K8s API 的 Pod 设置
automountServiceAccountToken: false - 永远不要给 default ServiceAccount 绑定任何权限
准入控制(Admission Controller)
RBAC 控制"谁能创建 Pod", 准入控制决定"Pod 的配置是否符合规范". 即使有权限创建 Pod, 如果 Pod 配置了 privileged=true, 准入控制器可以拒绝.
准入流程
|
| 阶段 | 作用 | 示例 |
|---|---|---|
| Mutating | 修改请求内容(注入默认值) | 自动注入 Sidecar, 添加默认 labels |
| Validating | 校验请求是否合规(不修改) | 拒绝 privileged 容器, 要求必须有 resource limits |
内置准入控制器
| 控制器 | 功能 |
|---|---|
| PodSecurity | 按 PSS 级别拒绝不合规 Pod(上一篇讲过) |
| LimitRanger | 强制 Pod 必须设置 resource limits |
| ResourceQuota | 限制 Namespace 资源总量 |
| MutatingAdmissionWebhook | 调用外部 Webhook 修改请求 |
| ValidatingAdmissionWebhook | 调用外部 Webhook 校验请求 |
Webhook 准入控制示例
|
failurePolicy 的选择
Fail: Webhook 不可用时拒绝所有请求, 安全但可能阻塞部署.
Ignore: Webhook 不可用时放行, 可用性好但安全降级.
生产环境建议 Fail + 确保 Webhook 高可用(多副本 + PDB).
审计日志(Audit Logging)
RBAC 管"防", 审计日志管"查", 谁在什么时间对什么资源做了什么操作.
|
审计日志的安全价值:
- 事后溯源: 谁删除了生产环境的 Deployment?
- 异常检测: 某 SA 突然开始 list secrets → 可能是 token 被盗
- 合规要求: SOC2, ISO27001 等认证需要完整的操作审计
常见安全配置错误
| 错误 | 风险 | 修复 |
|---|---|---|
| 给所有开发者 cluster-admin | 任何人可以做任何事 | 按团队/Namespace 分配最小权限 Role |
| default SA 有 list secrets 权限 | 所有 Pod 可以读取所有密钥 | 创建专属 SA + automountToken=false |
| Webhook failurePolicy=Ignore | 安全策略可被绕过 | 改为 Fail + 确保 Webhook 高可用 |
| 没有开启审计日志 | 安全事件无法溯源 | 配置 audit policy + 日志存储 |
| RoleBinding 绑定到 Group 通配符 | 意外授权给过多用户 | 显式列出 subjects |
快速回顾
- RBAC 最小权限: 按需分配, 重点审计 secrets/list, pods/exec, 通配符权限
- ServiceAccount: 每服务专属 SA + automountServiceAccountToken=false
- 准入控制: Mutating(修改)→ Validating(校验), 安全策略在此拦截
- Webhook: 自定义准入逻辑, failurePolicy=Fail 确保安全优先
- 审计日志: 记录所有敏感操作, 支持事后溯源和异常检测
- 第 07 篇会讲如何用 Kyverno/OPA 以声明式方式定义准入策略(不用自己写 Webhook 代码)
动手练习
- 检查 default SA 权限: 用
kubectl auth can-i --list --as=system:serviceaccount:default:default检查 default SA 的权限, 确认没有敏感权限 - 最小权限测试: 创建一个只能 get/list Pods 的 Role, 绑定给一个新 ServiceAccount, 用该 SA 的 token 尝试 create deployment(应被拒绝)
- 过度授权验证: 在测试 Namespace 给 default SA 绑定 cluster-admin, 从 Pod 内 curl K8s API 执行
kubectl get secrets -A, 观察结果(然后立即删除这个 binding) - PSS enforce 测试: 给 Namespace 启用 PodSecurity enforce=restricted, 尝试部署一个 privileged Pod 观察被拒绝的错误信息