用 RBAC 把权限切开
目标
为 ServiceAccount 授予最小权限,确认权限不会越过 namespace 边界,并进一步配置集群作用域权限和 Aggregated ClusterRole。
为什么这很重要
RBAC 题目在考试中是稳定得分项,但比创建正确答案更重要的是确认答案是否正确。kubectl auth can-i --as= 只会创建 SubjectAccessReview 向 apiserver 查询,并不会发送实际请求,因此可以在无副作用的情况下反复确认。
本实验特别加入了确认 no 的步骤。RBAC 权限只会累加,没有拒绝规则,因此如果误用了 ClusterRoleBinding,开放范围会远超预期。我们经常确认权限是否已开放,却很少确认它是否没有被开放。没有“确认不能做什么”的习惯,就无法真正遵守最小权限原则。
步骤
- 创建 namespace
cka-rbac和cka-rbac-other。在cka-rbac中创建 ServiceAccountdeploy-bot,并在cka-rbac-other中创建一个用于边界确认的 ConfigMapboundary-probe。 - 在
cka-rbac中创建 Rolepod-reader。apiGroups 为 core(空字符串),resources 仅包含pods和pods/log,verbs 仅包含get、list、watch。 - 在
cka-rbac中创建 RoleBindingpod-reader-bind,将 Rolepod-reader绑定到 ServiceAccountcka-rbac/deploy-bot。 - 将模拟
deploy-bot身份的权限检查结果保存到/root/cka-rbac/can-i.txt。在cka-rbac中,get Pod 应为 yes,delete 应为 no。 - 使用同一账户检查能否读取
cka-rbac-other中的 Pod,并将结果保存到/root/cka-rbac/boundary.txt。结果应为 no。 - 创建 ClusterRole
node-viewer(apiGroups 为 core,resources 为nodes,verbs 为get/list/watch)和 ClusterRoleBindingnode-viewer-bind,并绑定到cka-rbac/deploy-bot。list 节点应变为 yes。 - 创建 ClusterRole
cka-monitoring-endpoints。添加标签rbac.labhub.io/aggregate-to-monitoring=true,规则允许对 core 组中的services和endpoints执行get、list。然后创建 ClusterRolecka-monitoring,使 aggregationRule 通过选择器选中该标签。 - 在
cka-rbac中创建 ServiceAccountno-token,并设置automountServiceAccountToken: false。创建 Podlocked-down(镜像nginx:1.27),将 serviceAccountName 设为no-token,并在 Pod spec 中也明确设置automountServiceAccountToken: false。不要为该账户绑定任何权限。
参考
- 模拟 ServiceAccount 身份时,名称格式为
system:serviceaccount:<네임스페이스>:<이름>。 - 第 4、5 步的文件中直接保存命令输出(yes 或 no)即可。
- 常见错误 1:第 3 步在 subjects 中遗漏 namespace。即使位于同一 namespace,也必须明确填写。
- 常见错误 2:第 6 步使用 RoleBinding。节点是集群作用域资源,无法通过 namespace 作用域的绑定授予访问权限。
ServiceAccount 与实验 namespace
创建 namespace cka-rbac 和 cka-rbac-other。在 cka-rbac 中创建 ServiceAccount deploy-bot,并在 cka-rbac-other 中创建一个用于边界确认的 ConfigMap boundary-probe。
ServiceAccount 是 namespace 作用域资源。为了确认边界,在不应允许访问的一侧也必须存在一个资源。
创建只读 Role
在 cka-rbac 中创建 Role pod-reader。apiGroups 为 core(空字符串),resources 仅包含 pods 和 pods/log,verbs 仅包含 get、list、watch。
core 组使用空字符串。日志被视为与 Pod 不同的子资源,因此需要单独填写。不要加入写操作动词。
通过 RoleBinding 建立连接
在 cka-rbac 中创建 RoleBinding pod-reader-bind,将 Role pod-reader 绑定到 ServiceAccount cka-rbac/deploy-bot。
subjects 的 kind 为 ServiceAccount;除了名称,还必须填写该账户所在的 namespace。
确认权限已生效
将模拟 deploy-bot 身份的权限检查结果保存到 /root/cka-rbac/can-i.txt。在 cka-rbac 中,get Pod 应为 yes,delete 应为 no。
auth can-i 不会发送实际请求,只会发起查询。--as 所用的 ServiceAccount 名称有固定格式。
确认无法越过 namespace 边界
使用同一账户检查能否读取 cka-rbac-other 中的 Pod,并将结果保存到 /root/cka-rbac/boundary.txt。结果应为 no。
如果这里得到 yes,说明选择了错误的绑定类型。请重新检查 RoleBinding 与 ClusterRoleBinding 的差异。
开放集群作用域资源访问权限
创建 ClusterRole node-viewer(apiGroups 为 core,resources 为 nodes,verbs 为 get/list/watch)和 ClusterRoleBinding node-viewer-bind,并绑定到 cka-rbac/deploy-bot。list 节点应变为 yes。
节点不属于任何 namespace。无法通过 namespace 作用域的绑定授予访问权限。
配置 Aggregated ClusterRole
创建 ClusterRole cka-monitoring-endpoints。添加标签 rbac.labhub.io/aggregate-to-monitoring=true,规则允许对 core 组中的 services 和 endpoints 执行 get、list。然后创建 ClusterRole cka-monitoring,使 aggregationRule 通过选择器选中该标签。
不要在使用 aggregationRule 的角色中直接编写 rules。规则应写在带标签的其他角色中。
综合:创建不挂载令牌的 Pod
在 cka-rbac 中创建 ServiceAccount no-token,并设置 automountServiceAccountToken: false。创建 Pod locked-down(镜像 nginx:1.27),将 serviceAccountName 设为 no-token,并在 Pod spec 中也明确设置 automountServiceAccountToken: false。不要为该账户绑定任何权限。
可以在 ServiceAccount 和 Pod 两侧关闭令牌挂载,Pod 侧设置优先。同时在两处明确配置,意图会更清楚。