LabHub
学习 学习路径 课程

CNPE — 云原生平台工程师

自助服务的围栏挡住的是什么

在 LabHub 中继续学习

一句话总结

schema 管请求内容,RBAC 管主体权限,ResourceQuota 管 Namespace 上限。获准的请求仍可能被配额拒绝;查询失败也不是安全拒绝的证据。

流程图: 一句话总结 · 为什么需要它 · 工作原理 · 区分权限查询和真实请求

为什么需要它

假设 blue-dev 的 Role 只有 AppClaim 读取与创建权限,但它仍能读取 Secret。不要立即断定 Role 应用错误,应查看同一主体关联的其他 binding。RBAC 权限会合并所有允许规则,从一个 Role 删除 verb 并不会撤销其他 Role 的允许,它不是 deny。

RoleBinding 也可引用 ClusterRole,此时权限只在该 RoleBinding 的 Namespace 内生效。不能只看 ClusterRole 名称就认定为全集群权限,必须看哪个 binding 以什么范围连接。参阅官方 RBAC 规则与绑定

工作原理

区分权限查询和真实请求

kubectl auth can-i 查询 authorization 判定。“可以 create”不表示输入 schema 和 ResourceQuota 也会通过。最终行为应以该主体真实请求或安全的 server dry-run 验证。server dry-run 经过 API 验证路径但不保存对象,并不执行所有应用逻辑。参阅官方 API dry-run

在练习管理员上下文可执行:

kubectl auth can-i get appclaims.platform.labhub.io \
  -n tenant-blue --as=system:serviceaccount:tenant-blue:blue-dev
kubectl auth can-i patch appclaims.platform.labhub.io \
  --subresource=status -n tenant-blue \
  --as=system:serviceaccount:tenant-blue:blue-dev

普通用户不会自动获得对任意主体使用 --as 的权限。第二条若省略 --subresource=status,问的就是另一件事;把 status 写在 resource/name 的 name 位置也不等于查询子资源权限。参阅官方 can-i 用法

本练习验证的 kubectl 中,明确允许输出 yes 并返回 0,明确拒绝输出 no 并返回 1。不能把空 stdout、认证错误、连接失败统统解释成“不是 yes,所以是 no”。应先用正常 get 作为对照,再准确判断拒绝;CLI 或鉴权方式变化时要重新确认输出格式。

分离 API 使用权限和策略管理权限

请求 本练习策略 原因
AppClaim get·list·watch·create·update·patch 允许 团队申请、观察、修改
AppClaim status patch·update 拒绝 分离用户与观测结果写入者
quota create·patch 拒绝 用户不能修改自己的上限
Role·RoleBinding create 拒绝 策略管理与自助 API 分离
Secrets get、其他 Namespace AppClaim list 拒绝 限制凭据与租户范围
AppClaim delete 拒绝 本练习采用运维回收策略

获得 Role 创建权限不等于立即能创建管理员权限。Kubernetes 会限制把自己没有的权限写入或绑定 Role;escalatebind 是越过相关检查的特殊权限,应更谨慎。本练习不关闭该防御,同时把 Role 管理排除在租户业务之外。参阅官方权限提升防护

通配符可能把未来新增资源也纳入权限。默认 edit 角色不能只凭名字判断安全,它可能影响 Secret 等资源。应以具体 API group、resource、verb 描述工作,并审查实际 binding。参阅官方 RBAC 最佳实践

对象数量配额不测 CPU 或外部成本

count/appclaims.platform.labhub.io: "2" 只限制该类对象数量。一个 claim 即使创建十个外部数据库,也不会自动计算其成本。对象数限制用于防止控制面对象无限增长;工作量、成本、过期策略需另行设计。非 CRD 的 aggregation API 配额还要确认扩展 API server 的责任。参阅官方对象数配额

诊断配额时要区分 spec.hard(期望上限)、status.hard(已应用上限)、status.used(观测用量)。没有用量字段不等于 0。参阅官方 ResourceQuota 字段

若 used 为空,先检查 CRD Established、API discovery、真实 AppClaim 列表和 quota status,等待同步后重读;持续异常则由管理员调查控制器。exceeded quotastatus unknownForbidden 和连接错误不是同一种失败。提高上限或删除 quota 不能代替诊断。

禁止删除不是 Kubernetes 的必然规则

本练习禁止租户 delete,由运维回收;实际平台也可允许用户删除,再由控制器通过 finalizer 清理外部资源。finalizer 不是执行代码,只是表示清理责任的键。删除请求设置 deletionTimestamp,控制器完成清理并移除 finalizer 后对象才删除。没有负责控制器,仅添加键不会执行清理。参阅官方 finalizer 行为

现场表现

向旧评分器注入权限查询错误时,空响应也曾被当作“确认拒绝”。修复后要求同时存在正常 get 和明确 no。配额也要核对实际数量 2、上限 2、used 2,并确认第三次请求确实因 quota 失败。只记录“被拒绝”无法区分认证故障与正确策略。

下一步

下一练习会填写 blue-dev 的允许与拒绝清单,并分别检查 status 和其他 Namespace。quota 满后会通过两个 served 版本发送第三个 claim。最终报告只记录实际查询值,不能猜测无法读取的数据。