基于角色的访问控制最佳实践
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 安全标准的情况。
加固
Kubernetes 默认提供可能并非每个集群都需要访问权限。审查 RBAC 提供的默认权限可以提供安全加固的机会。通常,不应更改提供给 system: 帐户的权限,存在一些加固集群权限的选项:
- 审查
system:unauthenticated组的绑定,并在可能的情况下删除它们,因为这会授予可以从网络级别联系到 API 服务器的任何人访问权限。 - 通过设置
automountServiceAccountToken: false避免默认自动挂载服务帐户令牌。有关详细信息,请参阅 使用默认服务帐户令牌。为 Pod 设置此值将覆盖服务帐户设置,仍然可以挂载服务帐户令牌的工作负载。
定期审查
定期审查 Kubernetes RBAC 设置以查找冗余条目和可能的权限提升至关重要。如果攻击者能够创建一个与已删除用户同名的用户帐户,他们可以自动继承所有已删除用户的权限,尤其是分配给该用户的权限。
Kubernetes RBAC - 权限提升风险
在 Kubernetes RBAC 中,存在一些如果授予,可能允许用户或服务帐户在集群中或影响集群外部系统提升其权限的权限。
本节旨在提供集群操作员应注意的领域的可视性,以确保他们不会无意中允许对集群的访问权限超出预期。
列出 Secrets
显然,允许对 Secrets 进行 get 访问将允许用户读取其内容。同样重要的是要注意,list 和 watch 访问也有效地允许用户泄露 Secret 内容。例如,当返回 List 响应时(例如,通过 kubectl get secrets -A -o yaml),响应包括所有 Secret 的内容。
工作负载创建
在命名空间中创建工作负载(Pod 或 管理 Pod 的工作负载资源)的权限隐式授予了该命名空间中许多其他资源的访问权限,例如可以挂载到 Pod 中的 Secrets、ConfigMaps 和 PersistentVolumes。此外,由于 Pod 可以作为任何 ServiceAccount 运行,因此授予创建工作负载的权限也隐式授予了该命名空间中任何服务帐户的 API 访问级别。
可以运行特权 Pod 的用户可以使用该访问权限来获得节点访问权限,并可能进一步提升其权限。如果您不完全信任用户或其他主体具有创建足够安全和隔离的 Pod 的能力,则应强制执行 基线 或 限制性 Pod 安全标准。您可以使用 Pod 安全准入 或其他(第三方)机制来实现该强制执行。
出于这些原因,应使用命名空间来分隔需要不同信任级别或租户的资源。遵循 最小权限原则 并分配最少权限集仍然被认为是最佳实践,但应将命名空间内的边界视为薄弱的边界。
持久卷创建
如果允许某人或某个应用程序创建任意 PersistentVolumes,则该访问权限包括创建 hostPath 卷,这意味着 Pod 将获得对关联节点上底层主机文件系统的访问权限。授予该权限是一种安全风险。
拥有对主机文件系统不受限制的访问权限的容器可以通过读取其他容器的数据以及滥用系统服务的凭据(例如 Kubelet)来提升权限。
您应该仅允许以下人员创建 PersistentVolume 对象:
- 需要此访问权限进行其工作且您信任的用户(集群操作员)。
- 基于 PersistentVolumeClaims 配置为自动调配而创建 PersistentVolumes 的 Kubernetes 控制平面组件。这通常由 Kubernetes 提供程序或在安装 CSI 驱动程序时由操作员设置。
如果需要对持久存储的访问权限,受信任的管理员应创建 PersistentVolumes,而受约束的用户应使用 PersistentVolumeClaims 来访问该存储。
访问节点的 proxy 子资源
具有访问 nodes/proxy 子资源的权限的用户具有 Kubelet API 的权限,该权限允许在他们具有权限的节点上的每个 Pod 上执行命令。此访问权限绕过审核日志记录和准入控制,因此在授予对此资源的任何权限之前应小心。这些 API 可以通过 websocket HTTP GET 请求行使,只需要对 get 动词进行授权。这意味着对 nodes/proxy 的 get 权限不是只读权限。
有关更多信息,请参阅 Kubelet 身份验证/授权。
Escalate 动词
通常,RBAC 系统会阻止用户创建具有比用户自身更多权限的 clusterroles。此规则的例外情况是 escalate 动词。如 RBAC 文档 中所述,具有此权限的用户可以有效地提升其权限。
Bind 动词
类似于 escalate 动词,授予用户此权限允许绕过 Kubernetes 内置的权限提升保护机制,允许用户创建绑定到具有他们当前未拥有权限的角色。
Impersonate 动词
此动词允许用户模拟集群中其他用户并获得他们的权限。在授予此权限时应谨慎,以确保无法通过模拟的帐户获得过多的权限。
CSR 和证书颁发
CSR API 允许具有 CSR 上的 create 权限和 certificatesigningrequests/approval 上的 update 权限(其中签名者为 kubernetes.io/kube-apiserver-client)的用户创建新的客户端证书,这些证书允许用户向集群进行身份验证。这些客户端证书可以具有任意名称,包括 Kubernetes 系统组件的重复名称。这将有效地允许权限提升。
Token 请求
具有 serviceaccounts/token 上 create 权限的用户可以创建 TokenRequests 以为现有的服务帐户颁发令牌。
控制准入 Webhook
对 validatingwebhookconfigurations 或 mutatingwebhookconfigurations 具有控制权的用户可以控制可以读取提交到集群的任何对象的 webhook,并且对于 mutating webhook,还可以修改提交的对象。
Namespace 修改
可以对 Namespace 对象执行 patch 操作的用户(通过命名空间 RoleBinding 到具有该访问权限的角色)可以修改该命名空间的标签。在使用了 Pod Security Admission 的集群中,这可能会允许用户配置比管理员预期更宽松的策略的命名空间。对于使用了 NetworkPolicy 的集群,用户可能会设置间接允许访问管理员未打算允许的服务标签。
Kubernetes RBAC - 拒绝服务风险
对象创建拒绝服务
在集群中具有创建对象权限的用户可能能够创建足够大的对象,从而基于对象的大小或数量创建拒绝服务条件,如 Kubernetes 使用的 etcd 容易受到 OOM 攻击 中所述。这在多租户集群中尤其相关,如果允许半可信或不可信用户对系统进行有限访问。
缓解此问题的一种选择是使用 资源配额 来限制可以创建的对象数量。
接下来
- 要了解有关 RBAC 的更多信息,请参阅 RBAC 文档。