基于角色的访问控制最佳实践
Kubernetes RBAC 是一种关键的安全控制,旨在确保集群用户和工作负载只拥有执行其角色所需的资源访问权限。集群管理员在设计集群用户的权限时,必须了解可能发生特权升级的区域,以降低过度访问导致安全事件的风险。
此处列出的良好实践应结合一般的 RBAC 文档阅读。
一般良好实践
最小权限原则
理想情况下,应为用户和服务账号分配最小的 RBAC 权限。只应使用其操作明确所需的权限。尽管每个集群都会有所不同,但可以应用一些通用规则:
- 尽可能在命名空间级别分配权限。使用 RoleBinding 而不是 ClusterRoleBinding,以仅在特定命名空间内赋予用户权限。
- 尽可能避免提供通配符权限,特别是对所有资源的通配符权限。由于 Kubernetes 是一个可扩展系统,提供通配符访问权限不仅赋予了对集群中当前存在的所有对象类型的权利,还赋予了对未来创建的所有对象类型的权利。
- 管理员不应使用
cluster-admin
账号,除非特别需要。提供一个具有 模拟权限的低权限账号,可以避免意外修改集群资源。 - 避免将用户添加到
system:masters
组。此组的任何成员都会绕过所有 RBAC 权限检查,并始终拥有不受限制的超级用户访问权限,无法通过删除 RoleBinding 或 ClusterRoleBinding 来撤销。此外,如果集群正在使用授权 Webhook,此组成员身份也会绕过该 Webhook(来自此组成员用户的请求永远不会发送到 Webhook)。
最小化特权令牌的分发
理想情况下,不应为 Pod 分配已授予强大权限(例如,特权升级风险下所列的任何权限)的服务账号。在工作负载需要强大权限的情况下,请考虑以下实践:
- 限制运行强大 Pod 的节点数量。确保你运行的所有 DaemonSet 都是必要的,并以最小权限运行,以限制容器逃逸的影响范围。
- 避免将强大 Pod 与不受信任或公开的 Pod 一同运行。考虑使用 污点和容忍度、节点亲和性或 Pod 反亲和性来确保 Pod 不与不受信任或信任度较低的 Pod 一同运行。特别注意信任度较低的 Pod 不符合 **Restricted** Pod 安全标准的情况。
强化
Kubernetes 默认提供访问权限,这在某些集群中可能不需要。审查默认提供的 RBAC 权限可以提供安全强化的机会。一般来说,不应对提供给 system:
账号的权限进行更改,但存在一些强化集群权限的选项:
- 审查
system:unauthenticated
组的绑定,并在可能的情况下将其删除,因为这会赋予任何能在网络层面联系到 API 服务器的人访问权限。 - 通过设置
automountServiceAccountToken: false
避免默认自动挂载服务账号令牌。有关更多详细信息,请参阅 使用默认服务账号令牌。为 Pod 设置此值将覆盖服务账号设置,需要服务账号令牌的工作负载仍然可以挂载它们。
定期审查
定期审查 Kubernetes RBAC 设置以查找冗余条目和可能的特权升级至关重要。如果攻击者能够创建与已删除用户同名的用户账号,他们可以自动继承已删除用户的所有权限,特别是分配给该用户的权限。
Kubernetes RBAC - 特权升级风险
在 Kubernetes RBAC 中,如果授予某些权限,用户或服务账号可以在集群中升级其特权,或影响集群外的系统。
本节旨在让集群操作员了解需要谨慎的领域,以确保他们不会无意中允许对集群进行超出预期的访问。
列出 Secret
通常很清楚,允许对 Secret 进行 get
访问将允许用户读取其内容。同样重要的是要注意,list
和 watch
访问也有效地允许用户泄露 Secret 内容。例如,当返回 List 响应时(例如,通过 kubectl get secrets -A -o yaml
),响应包含所有 Secret 的内容。
工作负载创建
在命名空间中创建工作负载(Pod 或管理 Pod 的工作负载资源)的权限隐含地授予了对该命名空间中许多其他资源的访问权限,例如可以在 Pod 中挂载的 Secret、ConfigMap 和 PersistentVolume。此外,由于 Pod 可以作为任何服务账号运行,授予创建工作负载的权限也隐含地授予了该命名空间中任何服务账号的 API 访问级别。
能够运行特权 Pod 的用户可以利用该访问权限获取节点访问权限,并可能进一步提升其特权。如果你不完全信任用户或其他主体能够创建足够安全和隔离的 Pod,则应强制执行 **Baseline** 或 **Restricted** Pod 安全标准。你可以使用 Pod 安全准入或其他(第三方)机制来实施该强制措施。
由于这些原因,命名空间应用于分离需要不同信任级别或租户的资源。遵循最小权限原则并分配最小权限集仍然被认为是最佳实践,但命名空间内的边界应被认为是薄弱的。
PersistentVolume 创建
如果允许某人或某个应用程序创建任意 PersistentVolume,则该访问权限包括创建 hostPath
卷,这意味着 Pod 将获得对关联节点上底层主机文件系统(或多个文件系统)的访问权限。授予此能力存在安全风险。
具有对主机文件系统无限制访问权限的容器有许多方法可以升级权限,包括从其他容器读取数据,以及滥用系统服务(如 Kubelet)的凭据。
你只应允许以下人员创建 PersistentVolume 对象:
- 因工作需要此访问权限且你信任的用户(集群操作员)。
- 根据配置为自动配置的 PersistentVolumeClaim 创建 PersistentVolume 的 Kubernetes 控制平面组件。这通常由 Kubernetes 提供商或操作员在安装 CSI 驱动程序时进行设置。
在需要持久存储访问权限的情况下,受信任的管理员应创建 PersistentVolume,受限制的用户应使用 PersistentVolumeClaim 访问该存储。
访问节点的 proxy
子资源
有权访问节点对象的代理子资源的用户拥有 Kubelet API 的权限,这允许在他们有权限的节点上的每个 Pod 上执行命令。此访问权限绕过了审计日志和准入控制,因此在授予此资源权限之前应谨慎行事。
escalate 动词
通常,RBAC 系统会阻止用户创建拥有比用户更多权限的 ClusterRole。此规则的例外是 escalate
动词。如 RBAC 文档所述,拥有此权限的用户可以有效地升级其特权。
bind 动词
与 escalate
动词类似,授予用户此权限允许绕过 Kubernetes 内置的特权升级保护,允许用户创建绑定到其尚未拥有的权限的 Role。
impersonate 动词
此动词允许用户模拟并获得集群中其他用户的权限。在授予此权限时应谨慎,以确保不会通过被模拟的账号获得过多的权限。
CSR 和证书颁发
CSR API 允许具有 CSR create
权限和 certificatesigningrequests/approval
update
权限的用户,其中签署者是 kubernetes.io/kube-apiserver-client
,来创建新的客户端证书,从而允许用户向集群进行身份验证。这些客户端证书可以具有任意名称,包括与 Kubernetes 系统组件重复的名称。这将有效地导致特权升级。
令牌请求
对 serviceaccounts/token
具有 create
权限的用户可以创建 TokenRequest 以颁发现有服务账号的令牌。
控制准入 Webhook
控制 validatingwebhookconfigurations
或 mutatingwebhookconfigurations
的用户可以控制 Webhook,这些 Webhook 可以读取集群中准入的任何对象,对于 mutating Webhook,还可以修改准入的对象。
命名空间修改
能够对命名空间对象执行 **patch** 操作的用户(通过命名空间 RoleBinding 到具有该访问权限的 Role)可以修改该命名空间上的标签。在使用 Pod 安全准入的集群中,这可能允许用户将命名空间配置为比管理员预期更宽松的策略。对于使用 NetworkPolicy 的集群,用户可能会设置标签,间接允许访问管理员不打算允许的服务。
Kubernetes RBAC - 拒绝服务风险
对象创建拒绝服务
有权在集群中创建对象的用户可能能够创建足够大的对象,从而根据对象的大小或数量造成拒绝服务状况,如 Kubernetes 使用的 etcd 易受 OOM 攻击中所述。这在多租户集群中可能特别相关,如果允许半受信任或不受信任的用户对系统进行有限访问。
解决此问题的一种选择是使用 资源配额来限制可以创建的对象数量。
下一步
- 要了解有关 RBAC 的更多信息,请参阅 RBAC 文档。