Kubernetes RBAC 深度解析
某公司 Kubernetes 集群被入侵调查发现,攻击者获取的是一个普通开发者的 kubectl 配置。这个开发者有权限查看日志、查看 Pod 状态、进入容器调试。理论上,他不应该能造成太大的破坏。
但实际上,他利用了 RBAC 配置的一个缺陷:能够创建临时 Pod 并将宿主机的根目录挂载进去,从而读取了宿主机上的所有凭证文件,最终获取了集群管理员权限。
这不是 Kubernetes RBAC 本身的缺陷,而是 RBAC 配置不当的问题。这个案例说明,理解 RBAC 的每一个细节是安全运维的基础。
Kubernetes RBAC 的核心概念
RBAC(Role-Based Access Control)基于三个核心概念:
Subject(主体):谁在执行操作。包括 User(用户)、Group(用户组)、ServiceAccount(服务账号)。
Resource(资源):对什么执行操作。Kubernetes 中的资源包括 Pod、Service、Deployment、Secret、ConfigMap、PersistentVolume 等。
Verb(动词):执行什么操作。常见动词包括 get(读取)、list(列表)、watch(监听)、create(创建)、update(更新)、delete(删除)、patch(打补丁)、exec(在容器中执行命令)。
Role 与 ClusterRole
RBAC 中的 Role 定义了一组权限规则。Role 和 ClusterRole 的区别在于作用范围。
Role
Role 只在特定命名空间内生效。适用于需要限制在某个命名空间内的权限。
Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
ClusterRole
ClusterRole 是集群级别的角色,可以授予集群范围的资源,也可以授予跨命名空间的资源。
ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch"]
ClusterRole 还可以用于授予非资源类型 URL 的访问权限:
非资源类型
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-reader
rules:
- nonResourceURLs: ["/api/*", "/apis/*"]
verbs: ["get"]
Role 与 ClusterRole 的对照
RoleBinding 与 ClusterRoleBinding
Binding 将 Role/ClusterRole 绑定到 Subject(主体)。
RoleBinding
RoleBinding 将 Role 或 ClusterRole 绑定到特定命名空间内的 Subject。
RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader-binding
namespace: production
subjects:
- kind: User
name: alice@example.com
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding
ClusterRoleBinding 将 ClusterRole 绑定到集群范围的 Subject。
ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: node-admin-binding
subjects:
- kind: Group
name: node-admins
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
Binding 组合图解
flowchart TB
subgraph "RoleBinding"
A1[RoleBinding] --> A2[Role]
A1 --> A3[User/Group/SA]
end
subgraph "ClusterRoleBinding"
B1[ClusterRoleBinding] --> B2[ClusterRole]
B1 --> B3[User/Group/SA]
end
A2 -->|"命名空间内"| C1[Namespace A]
A2 -->|"命名空间内"| C2[Namespace B]
B2 -->|"集群范围"| D1[所有命名空间]
B2 -->|"集群范围"| D2[Non-resource URLs]
最小权限原则在 K8s RBAC 中的实践
最小权限原则(Principle of Least Privilege)要求只授予完成任务所需的最小权限。RBAC 是实施这个原则的主要工具。
权限层级设计
graph TB
A[ClusterRole: admin<br/>所有权限] --> B[ClusterRole: edit<br/>读写大多数资源]
B --> C[ClusterRole: view<br/>只读大多数资源]
C --> D[自定义 Role<br/>最小必要权限]
style A fill:#ffcdd2
style B fill:#fff9c4
style C fill:#c8e6c9
style D fill:#b3e5fc
自定义权限设计
最小权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-service-account-manager
namespace: production
rules:
# 只允许管理特定前缀的 ServiceAccount
- apiGroups: [""]
resources: ["serviceaccounts"]
resourceNames: ["app-*-sa"]
verbs: ["get", "update", "patch"]
# 只允许读取 secrets(不能创建或删除)
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
resourceNames: ["app-config"]
资源名称限制
resourceNames 字段可以进一步限制可以操作的资源实例:
限制特定资源实例
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["app-config", "db-config"]
verbs: ["get", "update"]
这意味着只能操作名为 app-config 和 db-config 的 ConfigMap,不能操作其他 ConfigMap。
内置 Role 的分析
Kubernetes 提供了一组内置的 ClusterRole,了解它们的权限范围对于安全配置至关重要。
system:authenticated
所有经过身份验证的用户都属于此组,权限非常有限。
system:anonymous
所有未认证的用户都属于此组,默认没有特殊权限。
cluster-admin
最高权限角色,拥有集群的完全控制权。应极其谨慎地使用,仅用于紧急恢复场景。
admin(命名空间级别)
命名空间内的管理员权限,包括创建和删除大多数资源。但不包括修改命名空间本身或资源配额。
edit(命名空间级别)
命名空间内的编辑权限,可以读取和修改大多数资源,但不能查看或修改 Secrets。
view(命名空间级别)
命名空间内的只读权限,可以查看大多数资源,但不能查看 Secrets,也不能进入容器执行命令。
admin/edit/view 的安全陷阱
默认的 admin/cluster-admin Role 绑定了 system:masters Group,这个 Group 具有永久的 cluster-admin 权限。如果将普通用户添加到这个 Group,等同于授予 cluster-admin 权限。
常见 RBAC 配置错误与风险
错误一:过度使用 cluster-admin
危险配置
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: developer-cluster-admin
subjects:
- kind: Group
name: developers
roleRef:
kind: ClusterRole
name: cluster-admin
风险:开发者无意或恶意可以修改集群任何配置,包括删除所有命名空间。
正确做法:根据实际需要授予最小权限。
正确配置
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: developer-logs-reader
subjects:
- kind: Group
name: developers
roleRef:
kind: ClusterRole
name: pod-logs-reader
错误二:允许 exec 操作到生产 Pod
危险配置
rules:
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
风险:攻击者通过 Web Shell 获取 foothold 后,可以 exec 到容器执行任意命令。
正确做法:限制 exec 权限的范围和时间。
正确配置
rules:
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
resourceNames: ["debug-pod"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
错误三:ServiceAccount 权限过大
危险配置
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["*"]
风险:攻击者获取 SA 的令牌后,可以创建特权 Pod 发动逃逸攻击。
正确做法:使用更精细的 Role 并限制创建的 Pod 类型。
正确配置
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ci-pipeline-sa
rules:
# 允许部署授权的镜像
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "delete"]
# 允许创建 Deployment(会创建 Pod)
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "create", "update"]
# 限制只能使用特定 ServiceAccount
- apiGroups: [""]
resources: ["pods"]
verbs: ["create"]
resourceNames: ["ci-pipeline-sa"]
RBAC 的审计与监控
审计 API 调用
启用 Kubernetes 审计日志,记录所有 API 调用:
审计策略配置
apiVersion: audit.k8s.io/v1
kind: AuditPolicy
rules:
# 不记录只读请求
- level: None
users: ["system:kube-proxy"]
verbs: ["get"]
resources:
- group: ""
resources: ["endpoints"]
# 记录对 Secret 的所有操作
- level: Metadata
resources:
- group: ""
resources: ["secrets"]
# 记录对敏感资源的所有操作
- level: RequestResponse
resources:
- group: ""
resources: ["pods/exec", "secrets"]
使用 audit2rbac 分析权限
使用
# 从审计日志生成 Role
audit2rbac -filename audit.log > generated-rbac.yaml
# 分析当前配置的风险
audit2rbac --incluster --cluster-wide > current-rbac.yaml
RBAC 的局限性
RBAC 虽然强大,但也有局限性:
无法控制资源内容:RBAC 控制对资源类型的访问,但不控制资源内容(如 Pod 规格中的环境变量)。需要使用 Policy Engine(如 OPA Gatekeeper)控制内容。
无法动态生效:RBAC 配置变更后,新权限会立即生效,旧权限不会自动撤销(除非使用 Bound ServiceAccount Token)。
复杂的组管理:跨多个命名空间的权限管理可能变得复杂。
总结与延伸思考
RBAC 是 Kubernetes 安全的基石。正确的 RBAC 配置可以显著降低安全风险,错误的配置则可能让攻击者获得意想不到的权限。
实践中的建议是「默认拒绝,显式允许」。新用户和 SA 应该有最少的默认权限,然后根据需要逐步增加。同时,建立 RBAC 配置的变更审批流程,确保每次变更都经过安全审查。
思考题
问题 1:为什么说「不给任何人 cluster-admin 权限」是一个好的安全实践?
参考答案
cluster-admin 权限意味着对集群的完全控制,包括删除所有命名空间、修改 RBAC 本身、访问所有 Secret。一旦被滥用或泄露,cluster-admin 权限可以被用于彻底破坏系统或在集群中建立持久化后门。建议做法:cluster-admin 仅用于紧急恢复场景;日常运维使用更小范围的 Role,如 admin(命名空间级别)或自定义的最小权限 Role。
问题 2:攻击者如何利用过度的 RBAC 权限进行容器逃逸?请描述一个攻击链。
参考答案
攻击链示例:1)攻击者获取了一个有「创建 Pod」权限的 ServiceAccount 令牌;2)创建一个特权 Pod(privileged: true);3)将宿主机根目录挂载到 Pod(hostPath: /);4)Pod 内可以访问宿主机的文件系统;5)修改宿主机的 /etc/crontab 或 /root/.ssh/authorized_keys 建立持久化后门;6)或直接通过宿主机的 kubelet 凭证获取集群管理员权限。防护措施:限制 SA 的权限范围,限制创建的 Pod 规格(通过 OPA Gatekeeper),启用 PSP/PSS 限制 Pod 配置。