基于角色的访问控制最佳实践

用于集群操作员的良好 RBAC 设计的原则和实践。

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 中,有一些权限,如果授予,可以允许用户或服务帐户在集群中升级其权限或影响集群外部的系统。

本节旨在提供集群操作员应注意的区域的可见性,以确保他们不会无意中允许对集群的访问权限超过预期。

列出秘密

通常很清楚,允许对 Secrets 进行 get 访问将允许用户读取其内容。同样重要的是要注意,listwatch 访问实际上也允许用户泄露 Secret 内容。例如,当返回 List 响应时(例如,通过 kubectl get secrets -A -o yaml),响应将包括所有 Secrets 的内容。

工作负载创建

在命名空间中创建工作负载(无论是 Pod 还是 管理 Pod 的工作负载资源)的权限隐式授予对该命名空间中许多其他资源的访问权限,例如可以在 Pod 中挂载的 Secrets、ConfigMaps 和 PersistentVolumes。此外,由于 Pod 可以以任何 ServiceAccount 运行,因此授予创建工作负载的权限也隐式授予该命名空间中任何服务帐户的 API 访问级别。

可以运行特权 Pod 的用户可以使用该访问权限获得节点访问权限,并可能进一步提升其权限。如果您不完全信任用户或其他主体具有创建足够安全和隔离的 Pod 的能力,则应强制执行 **基线** 或 **受限** Pod 安全标准。您可以使用 Pod 安全准入 或其他(第三方)机制来实施该强制执行。

出于这些原因,应使用命名空间来分离需要不同信任级别或租户的资源。仍然建议遵循 最小权限 原则并分配最少的权限集,但应将命名空间内的边界视为薄弱环节。

持久卷创建

如果有人(或某个应用程序)被允许创建任意 PersistentVolumes,则该访问权限包括创建 hostPath 卷,这意味着 Pod 将获得对关联节点上的底层主机文件系统(s)的访问权限。授予该能力是一个安全风险。

具有对主机文件系统的无限制访问权限的容器可以通过多种方式升级权限,包括从其他容器读取数据以及滥用系统服务的凭据,例如 Kubelet。

您应该只允许访问创建 PersistentVolume 对象,以供

  • 需要此访问权限才能完成工作且您信任的用户(集群操作员)。
  • 根据为自动配置配置的 PersistentVolumeClaims 创建 PersistentVolumes 的 Kubernetes 控制平面组件。这通常由 Kubernetes 提供者或操作员在安装 CSI 驱动程序时设置。

在需要访问持久存储的情况下,受信任的管理员应创建 PersistentVolumes,而受约束的用户应使用 PersistentVolumeClaims 来访问该存储。

访问节点的 proxy 子资源

具有访问节点对象的 proxy 子资源权限的用户具有对 Kubelet API 的权限,这允许对他们有权访问的节点上的每个 Pod 执行命令。此访问权限会绕过审计日志记录和准入控制,因此在授予对该资源的权限之前应谨慎行事。

升级动词

通常,RBAC 系统会阻止用户创建比用户拥有的权限更多的权限的集群角色。对此的例外是 escalate 动词。如 RBAC 文档 中所述,具有此权限的用户可以有效地升级其权限。

绑定动词

escalate 动词类似,授予用户此权限允许绕过 Kubernetes 内置的防止特权升级的保护,允许用户将绑定创建到他们没有权限的角色。

模拟动词

此动词允许用户模拟并获得集群中其他用户的权限。在授予它时应谨慎行事,以确保无法通过模拟的帐户之一获得过多的权限。

CSR 和证书颁发

CSR API 允许拥有 create 权限的用户创建 CSR(证书签名请求)以及拥有 update 权限的用户更新 certificatesigningrequests/approval(其中签名者为 kubernetes.io/kube-apiserver-client),从而创建新的客户端证书,这些证书允许用户对集群进行身份验证。这些客户端证书可以具有任意名称,包括 Kubernetes 系统组件的重复名称。这将有效地允许特权升级。

令牌请求

拥有 create 权限的用户可以在 serviceaccounts/token 上创建 TokenRequests 来为现有的服务帐户颁发令牌。

控制准入 Webhook

拥有 validatingwebhookconfigurationsmutatingwebhookconfigurations 控制权的用户可以控制 Webhook,这些 Webhook 可以读取进入集群的任何对象,并且在 mutating Webhook 的情况下,还可以修改进入的对象。

命名空间修改

能够对 Namespace 对象执行 patch 操作的用户(通过对具有该访问权限的角色的命名空间 RoleBinding)可以修改该命名空间的标签。在使用 Pod 安全准入的集群中,这可能允许用户为命名空间配置比管理员预期的更宽松的策略。对于使用 NetworkPolicy 的集群,用户可能会设置标签,这些标签间接允许访问管理员不打算允许的服务。

Kubernetes RBAC - 拒绝服务风险

对象创建拒绝服务

拥有在集群中创建对象的权限的用户可能能够创建足够大的对象,以根据对象的大小或数量创建拒绝服务条件,如 Kubernetes 使用的 etcd 容易受到 OOM 攻击 中所述。如果允许半信任或不受信任的用户有限访问系统,这可能与多租户集群特别相关。

缓解此问题的一种选择是使用 资源配额 来限制可以创建的对象数量。

下一步

  • 要了解有关 RBAC 的更多信息,请参阅 RBAC 文档
最后修改时间:2024 年 3 月 27 日下午 4:36 PST:与样式指南保持一致 (54e1d3308e)