「引言」
Kubernetes 是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它提供了丰富的功能,如服务发现、负载均衡、自动缩放等。随着 Kubernetes 在云原生领域的广泛应用, 「有效管理谁可以对 Kubernetes 集群执行何种操作变得至关重要」 。本文将简要介绍 Kubernetes的认证与授权体系以及RBAC授权原理。通过实际案例展示RBAC管理不当可能导致的安全风险,然后向大家分享RBAC安全研发与运维的最佳实践,以及我们在字节跳动内部的安全防护和治理经验。
背景知识
本章节将对 Kubernetes 的认证和授权体系进行概述,了解这些机制的原理有助于理解不同场景下集群权限的安全风险。特别是那些能够被轻易利用的未授权访问漏洞,以及那些容易被忽视的权限提升与横向移动攻击风险。
Kubernetes 认证与授权体系
Kubernetes 的认证与授权体系主要用于满足对关键服务 API(API Server、Kubelet Server)的访问控制。在经过多年的发展后,Kubernetes 已经实现了一套比较完善的认证与授权机制,可以满足用户大多数场景的使用需求。
「API Server」
Kubernetes 是一个以容器技术为基础,以声明式 API Server 为核心的分布式容器编排系统。Kubernetes 几乎所有的功能都通过 API Server 对外暴露。而 API Server 支持了多种认证机制,内置了多种授权模式和准入控制器,允许用户根据需要灵活配置和使用。
简单来说,当一个用户访问 Kubernetes 的 API Server 时,API Server 会使用启用的认证器依次对请求进行身份认证,API Server 使用第一个成功认证的身份来标识请求者;然后再使用启用的授权器依次对请求进行授权策略的检查,当有任意一个授权器显式地允许、拒绝一个请求时,则立刻返回当前授权结果(如果没有授权器显式地授权,那么请求也将被拒绝)。除此之外,在 API Server 真正处理请求前,它还会使用启用的准入控制器对请求进一步变异和验证。只有所有的准入控制器都验证通过后,请求才会被真正处理。
「KubeletServer」
Kubernetes 中还有一个非常重要的组件,那就是 Kubelet。它充当了分布式系统中的 Agent 角色,并使用节点专属的用户证书访问 API Server,管理节点上的资源。但 Kubelet 自身也会作为服务端,对外提供服务。从而实现在容器内执行命令、获取指标信息、容器日志、宿主机日志等功能。
Kubernetes 也为 Kubelet Server 提供了多种认证和授权模式。值得一提的是其中的 webhook 认证和 webhook 授权,它们本质上是向 API Server 发送 TokenReview 和 SubjectAccessReview 请求,对客户端的身份进行认证与授权。
「小结」
Kubernetes 为 API Server 和 Kubelet Server 支持了多种认证机制、授权机制、准入控制器,以及灵活的自定义接口。这些机制虽然能够满足各种用户需求,但也给用户带来了困扰。因为如果不了解这些机制的原理和负面影响,就很容易为集群引入安全风险和入侵检测盲点。特别是那些能够被轻易利用的未授权访问漏洞,以及那些容易被忽视的提权与横向移动攻击风险。
请参见附录和参考文献,了解更多 API Server 和 Kubelet Server 的认证、授权、准入控制的技术细节。
Kubernetes RBAC 授权原理
RBAC 是 Kubernetes 默认启用的授权机制,也是 Kubernetes 核心组件所使用的授权机制。用户在使用集群时,往往需要使用 RBAC 授权机制来为其用户账号授权,以便部署、运维工作负载及所需的各种资源。各类云原生应用的 Operator、Controller 往往也需要利用 RBAC 授权机制来为其服务账户授权,以确保它们能够访问必要的资源,从而实现其功能。
下面的示意图展示了用户账号和服务账号访问 API Server 时的认证、授权、准入控制过程。
在 Kubernetes 的 RBAC 授权体系中,引入了以下几种概念:
「Role & ClusterRole」
「Role & ClusterRoleBinding」
由以上可知,和
ClusterRole
内的代表一系列显式授予的权限,遵从 Deny-by-Default 安全模型。由于不支持 "deny" 规则,因而不支持显式的排除某些权限。
这一特点使得某些应用场景无法利用 RBAC 授权机制实现:在授予所有已知、未知 CRD 资源操作权限的同时,显式地排除某些敏感权限。但我们可以借助 ABAC、Webhook 授权模式,结合准入控制器来为此类场景的服务账号进行权限管理,从而缓解这类问题。
下面是一个通过 RBAC 授权机制为 ServiceAccount 绑定权限的示例:
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:name: example-clusterrolenamespace: example-nsrules:- apiGroups:- appsresources:- daemonsets- deployments- replicasets- statefulsetsresourcesNames:- testverbs:- '*'- nonResourceURLs:- /healthz- /healthz/*verbs:- get---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: example-rolebindingnamespace: example-nsroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: example-clusterrolesubjects:- kind: ServiceAccountname: example-sanamespace: example-ns
RBAC 安全风险剖析
Kubernetes 是一个分布式的容器编排系统。除了要确保 Kubernetes 基础组件的配置安全(例如 API Server、Kubelet Server 基本的认证授权配置等,对应 CIS Kubernetes Benchmark 中的第一至第四章中的要求)外,我们还需要对其 RBAC 授权配置进行精细化管理。
正确的授予主体 RBAC 权限能够避免为集群引入不必要的稳定性 & 安全性风险,而不恰当的权限设置可能导致敏感数据泄露、资源滥用、权限提升,甚至威胁整个集群的安全。接下来我们将借助文献和案例来进一步说明其安全风险。
概述
在 Kubernetes 中,可以通过对资源的操作来实现信息窃取、权限提升、横向移动等攻击。例如可以利用 pods/exec 资源的 create 权限通过 API Server 在指定容器内执行任意命令,也可以利用 nodes/proxy 资源的 create 权限直接访问 Kubelet Server 在指定容器内执行任意命令,还可以利用 pods 的 create 权限创建具有安全风险的容器、利用 pods 的 patch 权限在指定 Pod 的容器内执行代码...... 「随着 Kubernetes 的广泛使用,此类风险在云厂商、PaaS平台、云原生应用、SaaS产品中愈演愈烈,轻则被用于后渗透入侵,重则会给产品引入安全漏洞。」
Palo Alto Networks 的安全研究员深入分析了 Kubernetes 中的所有敏感权限,并根据其危害类型将其分类和分级[2](严重等级请参考开源项目 rbac-police 的风险权限扫描策略集)。如下图所示,在这些敏感权限中,有许多都可以被攻击者用于信息泄漏、权限提升、横向移动等攻击,最终实现整个集群的接管。
Palo Alto Networks 的研究结果表明,在针对主流公有云、CNI 厂商的分析中,有将近 50% 的厂商存在容器逃逸后轻易导致集群沦陷的安全问题。另外有 25% 的厂商存在容器逃逸后在一定条件下导致集群沦陷的安全风险[2]。
公开案例
风险示例
下面的示例演示了攻击者可以利用任意 secrets 的 create 权限,来获取了包含敏感权限的 ServiceAccount(这里以窃取 prometheus-agent SA 的 token 为例)的 token。对此,我们建议使用专用命名空间中的 Role 来定义所需权限,从而与 kube-system 等敏感命名空间隔离。
下面的示例演示了攻击者可以利用任意 secrets 的 get 权限,来爆破获取保存 SA token 的 secrets。虽然爆破 SA token 需要较长时间(爆破一个拥有 5 个随机字符串的 SA token 最多需要 27^5 次),但此权限也可能被用于窃取其他已知名称的 secrets 资源。对此,我们建议使用 Role 定义角色,或者通过 resourceNames 对 secrets 的权限范围进行约束,而非授予全部命名空间中任意 secrets 的 get 权限。
以上数据和案例表明,Kubernetes RBAC 权限管理已成为一个必须认真对待并及时采取有效防御措施的安全问题。
RBAC 安全研发与运维最佳实践
基于我们在字节跳动内部的安全实践,我们为 RBAC 授权配置总结了如下原则,以指引大家进行 Kubernetes RBAC 权限管理,从而降低由此为集群引入的安全风险。
遵循最小权限原则
在 RBAC 角色中分配权限时,请遵循最小权限原则授予执行任务所需的最低权限。例如:
RBAC 权限最小化不应被视作“非黑即白”,哪怕组件的某些敏感权限无法收敛,最小化权限仍然对降低风险、增加入侵检测的机率有重要作用。
避免使用默认角色/用户/用户组
一般情况下,Kubernetes 和基于 Kubernetes 的 PaaS 平台会自动将一些默认角色绑定到默认用户和用户组,以保证系统的正常运行。如需查看 Kubernetes 创建的默认角色和绑定的完整列表,请参阅 Default roles and role bindings。
大部分默认角色(例如 cluster-admin, edit, system:node 等)都会被授予较广泛的权限。因此,我们 「不建议」 将默认角色绑定到服务账号,除非您知道并接受由此带来的安全风险。用户可以根据实际需要将其绑定到用户账号上。
除此之外,我们 「应当避免」 为系统用户(例如 system:anonymous, system:serviceaccounts:NAMESPACE:default 等)、系统用户组(例如 system:authenticated, system:serviceaccounts 等)绑定额外的角色,这会导致权限的非预期扩散,引入严重的安全风险。
避免为 default 服务账号授予权限
在附录 1 的“准入控制机制”一节中,我们提到了默认启用的 ServiceAccount 准入控制器。创建 Pod 时如果未指定 ServiceAccount,那么 ServiceAccount 准入控制器会将命名空间内名为 default 的 ServiceAccount 分配给 Pod。
因此,我们 「应当避免」 为 default 服务账号授予权限,这会导致非预期的权限泄露。
尽量避免使用通配符
字符是一个适用于所有内容的通配符, 「应尽量避免」 在规则中使用通配符。这容易造成授权范围过大,除非您明确知晓并接受此行为可能引入的安全风险。建议您在 RBAC 规则中明确指定 API 组(apiGroups)、资源(resources)、动词(verbs),甚至是资源名称(resourceNames)。
例如,在字段中指定将授予、、、、、
deletecollection
和等权限。下表举例说明了如何避免在规则中使用通配符。
尽量避免使用敏感权限
设计角色前,请先仔细评估存在权限提升、命令执行、信息泄漏等安全风险的权限。例如 secrets 的操作权限、证书签发权限、pods/exec 访问权限等,更多请参考 Kubernetes RBAC - privilege escalation risks和 风险权限扫描策略集。
为应用服务、控制组件授予敏感权限会给整个集群引入安全风险。在系统设计和开发时, 「应尽量避免」 使用它们,并配合其他手段进行安全编排、安全加固和入侵检测。
尽量使用单独规则对特定资源授予权限
规划规则时,建议您尝试以下简要步骤,在每个角色中采用更高效、可读、易于维护的规则设计[4]:
这种方法可实现更有条理的规则设计,将对多个资源授予相同动词的规则组合起来,将为资源授予不同动词的规则彼此分散[4]。
例如,如果您的工作负载需要获取
deployments
资源的权限,但需要
daemonsets
资源的和权限,则您应该在创建角色是使用单独规则。当您将 RBAC 角色绑定到工作负载时,该角色将无法对
deployments
资源进行操作[4]。
再举一例,如果您的工作负载需要资源和
daemonsets
资源的和权限,您可以将它们组合成一条规则,因为工作负载需要在这两个资源上使用相同的动词[4]。
在下表中,这两种规则设计均有效,但拆分规则会根据需要更精细地限制资源访问权限[4]。
安全编排与其它
有些场景下,业务需求可能与安全要求产生冲突。例如一些应用必需某些敏感权限才可以正常运行或提供必要功能。对此,我们建议您考虑采取以下安全编排、纵深防御策略来尽量降低风险。
「使用专用命名空间」
「制定特殊调度策略」
「单独部署敏感组件」
「建设纵深防御」
RBAC 安全防护与治理实践
在许多企业中,往往会因为安全意识不足、云原生安全建设开展较晚、使用开源云原生应用等原因,已经为系统引入了大量 RBAC 权限风险。但由于涉及基础设施,并且缺乏相应的知识和手段,针对这类风险的防护和治理往往充满挑战。接下来笔者将向大家介绍我们在字节跳动内部的一些经验和实践,抛砖引玉供大家参考。
整体思路
通过公开案例和红蓝演练等方式,向研发团队展示 K8s RBAC 错误配置对生产环境安全性和稳定性造成的危害。与 DevOps 团队在风险认知上达成一致,从而自上而下对齐治理目标。在开展治理工作前,应根据企业的实际情况制定合理的计划。同时,安全团队应提供治理所需的知识库、工具和系统,与 Ops 团队构建合适的治理流程,以确保治理工作顺利推进。此外,安全团队还应持续加强反入侵能力建设,为 K8s RBAC 等安全风险提供兜底保障。
制定计划
制定切实可行的计划,以及提供必要的工具与系统,是收敛 K8s RBAC 安全风险的重要前提和保障。
「数据驱动」
「明确优先级」
「增量管控 & 存量整改」
防护与治理框架
在字节内部,我们构建了如下图所示的安全防护和治理框架,并推进了权限治理工作。
在开发与集成阶段,我们借助最佳安全实践来指导研发部门进行安全的 RBAC 权限设计和开发。并在部分 CI/CD 流水线中集成了安全扫描,对存在危险 RBAC 配置的 chart 产物进行拦截、告警和记录。
在部署阶段,我们通过与 PaaS 平台集成的准入控制机制、K8s 准入控制器来对非法的应用和资源进行增量管控。并指导关键业务通过安全编排等手段来降低具有敏感权限的控制组件的安全风险。这里我们基于开源项目 Kyverno 的策略引擎,实现了 Policy as Code。从而在流水线安全扫描、准入控制中实现策略兼容,降低了安全策略的维护成本。
在运行阶段,我们通过定期扫描(基于开源项目 rbac-police)来持续识别风险。此外,我们还设计实现了针对服务账号和用户账号的行为建模能力。此能力基于账户行为来生成最小权限的角色定义,为组件的权限收敛提供参考。由于不是所有的敏感权限都能得到整改,因此,在实践中我们会基于 K8s 的审计日志进行入侵检测,从而发现潜在的攻击行为。
通过以上机制,我们构建了针对 K8s RBAC 安全风险的防护和治理框架,为字节内部大规模生产集群的 RBAC 安全治理和防护提供了必要能力。
总结
RBAC 是 Kubernetes 中的一项重要的授权机制,正确地配置 RBAC 对于保障基于 Kubernetes 的系统安全至关重要。在设计中,我们应遵循最小权限原则进行权限设计,并理解敏感权限的安全风险,为其引入必要的防护能力。在开发中,我们要注意避免过度授权、权限混乱等问题。在安全防护和运营中,我们还要平衡安全要求和业务需求,持续收敛安全风险,建立纵深防御体系。
希望本文能让大家更好地理解 Kubernetes 的权限体系,了解 RBAC 授权模式的安全风险和最佳安全实践,从而指导系统的安全设计、开发和防护,最终构建更加安全可靠的系统。
参考文献
本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载者并注明出处:https://www.jmbhsh.com/keji/34889.html