基于角色的访问控制良好实践
Kubernetes RBAC 是一个关键的安全控制,以确保集群用户和工作负载仅具有执行其角色所需的资源访问权限。重要的是要确保,在为集群用户设计权限时,集群管理员了解可能发生特权升级的区域,以降低过度访问导致安全事件的风险。
此处列出的良好实践应与通用的 RBAC 文档 一起阅读。
通用良好实践
最小权限
理想情况下,应为用户和服务帐户分配最小的 RBAC 权限。应仅使用其操作明确需要的权限。虽然每个集群都将有所不同,但可以应用一些通用规则:
- 尽可能在命名空间级别分配权限。使用 RoleBindings 而不是 ClusterRoleBindings,以仅在特定命名空间内授予用户权限。
- 尽可能避免提供通配符权限,尤其是不对所有资源。由于 Kubernetes 是一个可扩展的系统,提供通配符访问不仅会授予当前集群中存在的所有对象类型的权限,还会授予将来创建的所有对象类型的权限。
- 除非有特殊需要,否则管理员不应使用
cluster-admin
帐户。提供具有模拟权限的低权限帐户可以避免意外修改集群资源。 - 避免将用户添加到
system:masters
组。任何属于此组的成员都会绕过所有 RBAC 权限检查,并且始终具有不受限制的超级用户访问权限,这不能通过删除 RoleBindings 或 ClusterRoleBindings 来撤销。顺便说一句,如果集群正在使用授权 Webhook,则此组的成员身份也会绕过该 Webhook(来自该组成员的请求永远不会发送到 Webhook)
最大限度地减少特权令牌的分发
理想情况下,不应为 Pod 分配已被授予强大权限的服务帐户(例如,特权升级风险下列出的任何权限)。在工作负载需要强大权限的情况下,请考虑以下实践:
- 限制运行强大 Pod 的节点数量。确保您运行的所有 DaemonSet 都是必需的,并且以最小权限运行,以限制容器逃逸的影响范围。
- 避免在不可信或公开暴露的 Pod 旁边运行强大的 Pod。考虑使用 污点和容忍度,节点亲和性 或 Pod 反亲和性,以确保 Pod 不与不可信或信任度较低的 Pod 一起运行。特别注意信任度较低的 Pod 未达到 受限 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 可以以任何ServiceAccount身份运行,因此授予创建工作负载的权限也隐式授予该命名空间中任何服务帐户的 API 访问级别。
可以运行特权 Pod 的用户可以使用该访问权限来获得节点访问权限,并有可能进一步提升其特权。如果您不完全信任用户或其他主体有能力创建足够安全和隔离的 Pod,则应强制执行 基线 或 受限 Pod 安全标准。您可以使用 Pod 安全准入或其他(第三方)机制来实现该强制执行。
出于这些原因,命名空间应用于分隔需要不同信任级别或租户的资源。遵循最小权限原则并分配最小的权限集仍然被认为是最佳实践,但命名空间内的边界应被认为是弱边界。
持久卷创建
如果允许某人(或某个应用程序)创建任意的 PersistentVolume,那么该访问权限将包括创建 hostPath
卷,这意味着 Pod 将能够访问关联节点上底层的主机文件系统。授予此权限是一种安全风险。
许多情况下,对主机文件系统具有不受限制访问权限的容器可以提升权限,包括从其他容器读取数据,以及滥用系统服务(如 Kubelet)的凭据。
您应该仅允许以下用户创建 PersistentVolume 对象:
- 需要此访问权限来完成工作并且您信任的用户(集群运维人员)。
- Kubernetes 控制平面组件,这些组件根据配置为自动供应的 PersistentVolumeClaims 创建 PersistentVolume。 这通常由 Kubernetes 提供商或操作员在安装 CSI 驱动程序时进行设置。
如果需要访问持久存储,应由受信任的管理员创建 PersistentVolume,受限用户应使用 PersistentVolumeClaims 来访问该存储。
访问节点的 proxy
子资源
有权访问节点对象的 proxy 子资源的用户有权访问 Kubelet API,该 API 允许在他们有权访问的节点上的每个 Pod 上执行命令。 此访问权限绕过审计日志记录和准入控制,因此在授予此资源的权限之前应谨慎行事。
escalate 动词
通常,RBAC 系统会阻止用户创建权限高于用户自身权限的 clusterrole。 但 escalate
动词是一个例外。正如在 RBAC 文档 中所述,拥有此权限的用户可以有效地提升自己的权限。
bind 动词
与 escalate
动词类似,授予用户此权限允许绕过 Kubernetes 内置的防止特权提升的保护机制,允许用户创建与他们本身不具备的权限的角色绑定。
impersonate 动词
此动词允许用户模拟并获得集群中其他用户的权限。在授予此权限时应谨慎,以确保不会通过其中一个模拟帐户获得过多的权限。
CSR 和证书颁发
CSR API 允许具有 CSR 的 create
权限和 certificatesigningrequests/approval
的 update
权限(签名者为 kubernetes.io/kube-apiserver-client
)的用户创建新的客户端证书,从而允许用户向集群进行身份验证。这些客户端证书可以具有任意名称,包括 Kubernetes 系统组件的重复项。这将有效地允许特权提升。
令牌请求
对 serviceaccounts/token
具有 create
权限的用户可以创建 TokenRequest 来为现有服务帐户颁发令牌。
控制准入 Webhook
对 validatingwebhookconfigurations
或 mutatingwebhookconfigurations
具有控制权的用户可以控制可以读取集群中任何已准入对象的 Webhook,并且对于 mutating webhook,还可以修改已准入的对象。
命名空间修改
能够对命名空间对象执行 patch 操作的用户(通过对具有该访问权限的 Role 的命名空间 RoleBinding)可以修改该命名空间上的标签。在使用 Pod 安全准入的集群中,这可能允许用户将命名空间配置为比管理员预期的更宽松的策略。对于使用 NetworkPolicy 的集群,用户可以设置标签,从而间接允许访问管理员不打算允许的服务。
Kubernetes RBAC - 拒绝服务风险
对象创建拒绝服务
有权在集群中创建对象的用户可能会创建足够大的对象,从而导致拒绝服务的情况,无论基于对象的大小还是数量,正如 Kubernetes 使用的 etcd 容易受到 OOM 攻击 中讨论的那样。如果允许半信任或不受信任的用户有限地访问系统,这在多租户集群中可能尤其相关。
缓解此问题的一种方法是使用 资源配额 来限制可以创建的对象数量。
下一步
- 要了解有关 RBAC 的更多信息,请参阅 RBAC 文档。