登录 / 注册 Account
快速跳转

Kubernetes 安全性简介

复制 URL

对于容器Kubernetes 而言,尽管采用率在日益提高,但安全性仍然是最受关注的问题。可喜的是,您可以有很多举措让容器的实现变得更加安全。这篇关于保护 Kubernetes 的简介概述了许多可以采取的容器安全措施。

容器镜像通常是那些可引入到云原生环境中的漏洞的主要来源。对于有效的安全策略而言,其核心部分就是确保在整个组织内遵守安全的镜像构建实践。尽管镜像扫描也是保障组织安全态势的一个重要组成部分,但保护镜像安全是在应用生命周期的早期阶段主动确保容器化应用安全的一种方法。

为了安全地创建容器镜像,请采用以下最佳实践:

  1. 使用尽可能少的基本镜像

    镜像中应仅包含容器所需的库和工具,以减少攻击面。

  2. 使用来自可信来源的基本镜像

    如果您不是从头开始构建镜像,请选择来自可信来源的基本镜像。您应该能够看到 Dockerfile 和所有镜像组件的源代码,并且应该托管在声誉良好的镜像仓库中。此外,基本镜像还应该经常进行更新。

  3. 指定用户

    如果 Dockerfile 没有指定用户,容器就会默认以 root 用户执行,这样不仅扩大了潜在的攻击面,而且在应用受到威胁时还提供了一个方便的权限提升路径。

  4. 验证 Docker 镜像

    确保镜像的可信性堪称是一项挑战,但它也是构建安全镜像的一个重要组成部分。任何基本镜像都应该有签名并经过验证。只有从受信任的镜像仓库中提取镜像,才能确保所有镜像是可信的。

  5. 扫描漏洞

    找到并修复容器镜像中存在的漏洞非常重要,包括那些由开源库引入的漏洞。

  6. 保守秘密

    秘密(包括凭据和密钥等敏感数据)不应嵌入到容器镜像中。

  7. 设置资源限制

    限制容器可访问的 CPU 或内存资源的数量,将有助于控制在容器使用不当时可能造成的损害。

  8. 限制权限

    尽可能严格地设置容器的权限,并且要在容器的配置上确保权限无法升级。

  9. 采用多阶段构建

    对于那些用于生成和编译应用的构建工具,可以在生产系统上运行这些构建工具时再加以使用。不要在构建和运行阶段使用相同的镜像,而是采用多阶段 Dockerfile 从运行时镜像中去除任何不必要的复杂工具。调试器也应该从生产镜像中予以剥离。

  10. 使用注重安全性的编码实践

    这一点可通过使用 linter 在开发过程中捕获不安全的代码来贯彻实施。

虽然这些步骤仅面向镜像构建过程,但在构建安全镜像背后的相关原则也应该让应用的其他部分的安全实践知晓。这些安全实践包括:保持攻击面尽可能小、限制权限和收紧配置,不要使用 Kubernetes 中的默认设置和云原生堆栈的其他方面。

针对网络防御,互联网安全中心(CIS)制定了一些最佳实践。CIS 使用了"众包"的方式来定义其安全建议。CIS 基准是其最受欢迎的工具之一。

组织可以使用 Kubernetes 的 CIS 基准来强化他们的 Kubernetes 环境。有许多开源和商业工具可以自动检查 CIS 基准中所述的设置和控制,以识别不安全的配置。

尽管 CIS 基准提供了许多有用的配置检查功能,但组织还是应将它们视为一个起点并努力超越 CIS 检查的范畴,以确保将最佳实践应用于 Kubernetes,这其中包括实施网络策略、基于角色的访问权限控制(RBAC)设置、管理权限,以及其他面向 Kubernetes API 服务器的保护措施。

Kubernetes 基于角色的访问权限控制(RBAC)提供了用于管理 Kubernetes API 端点授权的标准方法。集群的 RBAC 配置控制着哪些主体可以在哪些命名空间中的哪些资源类型上执行哪些动作。例如,某个配置可能授予用户"alice"查看命名空间 external-api 中"pod"类型资源的访问权限。RBAC API 中包含四个声明性对象:RoleClusterRoleRoleBinding 以及 ClusterRoleBinding

Roles 是一个命名空间资源,它由为单个命名空间设置权限的规则组成,而 ClusterRoles 是非命名空间资源,它可授予面向整个集群的权限或跨越多个命名空间的权限。每个规则都是由动作、资源类型和命名空间选择器组合而成。

角色绑定发挥着桥梁作用,它将用户、用户组或服务帐户(也称为主体)绑定到角色并授予这些用户在该角色中所定义的权限。集群角色绑定则是将 ClusterRole 绑定到集群中的所有命名空间。通过这种方式,RoleBinding 在命名空间内分配权限,而 ClusterRoleBinding 在集群范围内授予这些权限。

根据我们与客户的经验,我们发现了以下五个最常见的 RBAC 配置设置错误。

 

配置错误 1:不必要地授予集群管理员角色

内置的 cluster-admin 角色可授予对集群的无限制访问权限。在从传统 ABAC 控制器过渡到 RBAC 的过程中,有些管理员和用户可能会通过广泛授予 cluster-admin 权限来复制 ABAC 的宽松配置,而忽略了相关文档中的警告。如果用户或组被例行性地授予了 cluster-admin 权限,则帐户泄露或错误可能会带来深远的危害和影响。服务帐户通常也并不需要这种类型的访问权限。在以上这两种情况下,其实都应该创建一个定制化的角色或集群角色,并且只将其授予需要它的特定用户。

配置错误 2:角色聚合使用不当

在 Kubernetes 1.9 及更高版本中,角色聚合可用来简化权限授予,其方法是允许将新权限组合到现有的角色中。但是,如果不仔细审查这些聚合,它们可能会改变角色的预期用途;例如,system:view 角色可能会误将规则与 view 之外的动作聚合在一起,从而违反了授予 system:view 的主体永远不能修改集群这一意图。

配置错误 3:重复的角色授予

角色定义可能相互重叠,从而导致以多种方式为主体授予同一访问权限。管理员有时可能会有意让这种重叠的情况发生,但这种配置会让人难以清楚地知道哪些主体被授予了哪些访问权限。如果管理员没有意识到有多个角色绑定授予了相同的权限,那么这种情况会令访问权限的撤销变得更加困难。

配置错误 4:未使用的角色

已经创建但未授予给任何主体的角色会增加 RBAC 管理的复杂性。同样,仅授予给不存在的主体(例如已删除的命名空间中的服务帐户或已从组织中离职的用户)的角色可能会导致查看重要配置时感觉不方便。删除这些未使用或不活动的角色通常不会带来安全隐患,而且还可以将注意力集中在活动角色上。

配置错误 5:授予不存在的角色

角色绑定可以引用不存在的角色。如果将来出于不同目的重复使用同一角色名称,那么这些不活动的角色绑定可能会突然且意外地将权限授予给新角色创建者预期以外的主体。

 

正确配置集群 RBAC 角色和绑定将有助于最大限度降低因应用受损、用户帐户接管、应用缺陷或单纯的人为错误而造成的影响。

虚拟机(VM)和容器具有完全不同的架构,但它们过于相似,足以引起一些混淆。容器与 VM 之间的差异具有非常重要的安全影响。VM 和容器都提供不同程度的隔离,并且都支持可移植性。虚拟机能做到完全自给自足,有自己的操作系统,且不与其他虚拟机共享资源。容器则与其他容器共享主机,从而使安全边界的概念复杂化。

容器和 Kubernetes 呈现不同的架构模式,需要采用不同的安全方法。那些面向基于主机的安全性的成熟技术无法移植到容器中。其他一些源自主机或 VM 域的安全技术(例如围绕指定的边界构建网络防火墙)也不适用于容器。此外,虚拟机安全最佳实践的一个关键部分是应用安全补丁,但补丁不能应用于正在运行的容器。相反,应该更新容器镜像并重建容器。

为了保护容器的安全,需要做到:

  • 控制容器之间的通信
  • 确保容器没有已知的漏洞
  • 防止容器具有 root 访问权限
  • 限制权限和访问权,使其仅限于应用正常运行所需的权限和访问权

Kubernetes 进一步提高了复杂度,并带来了额外的潜在安全风险。管理 Kubernetes 配置和网络策略对于巩固容器化应用的安全态势可谓至关重要。

此外,迁移至容器化应用所带来的工作流变化也使得在整个生命周期中进行安全性整合变得至关重要。安全性必须从一开始就要融入到应用中,其起点甚至要追溯到镜像和容器的配置。您不能在开发过程结束时(即部署前夕)才为容器化应用添加安全性配置。

容器化应用的安全性要求控制所有组件的来源,包括开源元素、管理配置、扫描镜像以及启用基于角色的细粒度访问权限控制。容器和 Kubernetes 会采用不同的安全方法,但鉴于其声明性和不可变的特性,它们也确实提供了一次构建有史以来最安全应用的机会(如果配置正确)。

在 Kubernetes 中,容器在容器集(Kubernetes 对象)内运行,而每个容器集的运行时配置可以利用容器集规范中的安全环境、容器集安全策略(PSP)或者许可控制器(如开源策略代理(OPA)网守)的组合进行设置和强制执行。

安全环境在部署清单中定义,它允许您定义每个工作负载的确切要求。您可以针对容器集或容器来配置安全环境。容器集安全策略是一个集群级别的 Kubernetes 资源,用于控制容器集可以运行的安全环境。如果为集群启用了 PSP,则任何创建不遵守其关联 PSP 的容器集的尝试都将被 PSP 许可控制器拒绝。

限制容器运行时权限:

  • 不要以 root 身份运行应用进程。将 runAsUser 设置为 MustRunAsNonRoot

  • 不允许进行权限提升。将 allowPrivilegeEscalation 设置为 false

  • 使用只读根文件系统。将 readOnlyRootFilesystem 设置为 true

  • 使用默认(掩蔽的)/proc 文件系统挂载

  • 不要使用主机网络或进程空间。将 hostPIDhostNetworkhostIPC 设置为 false

  • 删除未使用的 Linux 功能,不要添加并非应用绝对需要的可选功能

  • 使用 SELinux 选项进行更加细粒度的流程控制

  • 为每个应用提供自己的 Kubernetes 服务帐户

  • 如果无需访问 Kubernetes API,则不要在容器中挂载服务帐户凭据

 

使用 Kubernetes 命名空间

Kubernetes 命名空间为集群对象提供了范围界定,从而可进行细粒度的集群对象管理。命名空间中的容器/容器集、服务和部署可以利用 Kubernetes 网络策略等控件进行隔离,或使用 Kubernetes 基于角色的访问权限控制(RBAC)来限制其访问权限。

在开始将工作负载部署到集群之前,先规划好如何分配命名空间。如果是让每个应用都拥有一个命名空间,尽管在分配 RBAC 角色权限和默认网络策略时会产生额外的管理开销,但最有利于进行控制。如果您决定将多个应用组合到一个命名空间中,则主要标准应该是这些应用是否具有共同的 RBAC 要求,以及将这些权限授予在该命名空间中需要 Kubernetes API 访问权限的服务帐户和用户是否安全。

从广义上讲,配置管理是指建立有关配置的策略并确保这些策略在整个组织的整个应用生命周期中得到统一应用的工程实践。配置是管理云原生应用安全风险的一个关键组成部分,特别是考虑到容器和 Kubernetes 的许多默认配置并不安全。在 Kubernetes 上运行的容器化应用中,配置错误是最常见的安全风险来源。

配置管理必须自动化,同时还要实现对防护的集中管理,以确保不是由每位开发人员或操作人员来负责手动配置工作负载。这些防护应立足于组织的安全策略。

据 IBM 称,有 95% 的云安全故障是由人为错误造成的。随着应用变得越来越复杂(在容器和 Kubernetes 中的分布式系统上运行),配置错误的风险也在逐渐增大。在没有集中配置管理工具的情况下,组织几乎无法确保一致地应用配置策略。对于采用多云混合云设置的公司来说,实现统一、正确的配置更具挑战性,因为每个环境都需要一组不同的配置。此外,开发人员与操作人员之间也存在不可逾越的技能差距,后者并不总是了解安全配置的最佳实践。

在很多情况下,开发人员为运行的应用设置配置的最简单方法也是最不安全的,例如允许进行 root 访问、授予管理员权限或设置非常高的资源限制。在借助正确工具的情况下,可以将配置管理整合到 DevOps 工作流中,而且也不会降低开发速度。这样做效果最好(称得上是最佳实践),因为它消除了快速发布与保护工作负载配置安全之间的紧张关系。

配置管理应包含一种方法来获得配置的可见性,同时对得到许可的配置进行防护,以便可以自动终止不安全的构建或有风险的部署。组织需要有一个统一的界面来查看容器和 Kubernetes 的所有相关配置,并在遇到有潜在风险的配置时收到警报。

以下要素构成了容器和 Kubernetes 配置管理的基石:

  • 基于角色的访问权限控制(RBAC)。组织需要找出过于宽松的配置和/或不必要的角色。
  • 秘密。一个好的配置管理工具可以主动限制对秘密的访问。
  • 基于策略的评估。制定组织的安全策略是任何安全态势的一个关键组成部分,应该有一种方法可以根据这些预先确定的策略来检查部署情况。
  • 权限。应根据最低特权原则来分配权限。
  • 资源限制。容器和 Kubernetes 集群都应该对可用的 CPU 和内存进行限制。
  • 网络策略。网络策略应尽可能限制应用各部分之间的通信,以控制在容器受到威胁时的潜在损害。

开始着手配置管理的最简单方法是遵循行业公认的最佳实践,如 CIS 基准。随着组织容器采用率的不断提高,最佳做法是围绕配置管理来制定组织监管策略。配置管理应同时涵盖容器和 Kubernetes 的配置,因为只有对这两个地方的配置进行正确管理,才能确保安全态势得以巩固。

默认情况下,Kubernetes 允许集群内的所有容器集自由通信。这样可以方便应用操作,但也带来了安全风险。尽管默认设置显得过于宽松,但 Kubernetes 还具有内置的强制执行功能。通过对其进行配置,可以限制资产之间的通信。网络分段就是限制部署的各部分之间进行通信的一个环节。有些合规性框架也需要网络分段,包括 PCI-DSS。

网络分段的工作原理是将网络分成更小的子网。从安全性的角度看,其主要优势在于:如果不法分子获得了对与其他应用运行在同一 Kubernetes 集群上的某个应用的访问权限,网络分段就会阻止该不法分子访问集群上的所有应用。这也是一种将敏感工作负载和/或特定合规性框架范围内的工作负载与应用的其他部分隔离开的一种方法。

网络策略应尽可能严格,即仅允许各个容器与让应用功能符合设计意图所必需的容器进行通信。

在 Kubernetes 中,网络分段是通过实施网络策略来完成的。这既可以通过 Kubernetes 本地网络执行功能,也可以通过使用额外的基础架构层(如服务网格)来实现。

默认情况下,无论是在同一个命名空间内还是在不同命名空间之间,容器集、容器和节点之间的通信不受限制。制定相应的网络策略来限制通信(通常从拒绝所有通信的策略开始)是一个不错的最佳实践出发点。鉴于容器集之间确实需要进行通信,所以最好系统地列出给定容器集需要与之通信的其他容器集。在允许列表的基础上,还应允许进出公共互联网,但这仅适用于需要此类通信的容器集。

当然,改变网络策略和增加网络分段也存在一些相关的操作风险。利用工具来可视化系统范围内网络策略的更改将如何影响应用,会有助于将调整网络策略所带来的意外风险降至最低。

任何组织都无法拥有完全安全的应用或 IT 基础架构。安全性需要优先考虑并理解与不同操作相关的风险和权衡。风险预测是概述组织已知的安全风险以及与管理该风险相关的策略和实践的过程。每个组织都必须接受一定程度的风险,但同时应该清楚可接受的风险程度。分析预测不仅应针对整个组织,还应针对每个应用。敏感工作负载或合规要求范围内的工作负载与非敏感工作负载具有不同的风险状况。

风险预测还有助于评估环境中所存在的漏洞的重要性。对每个漏洞都做出响应是不可能的,因此强大的安全态势需要评估每个漏洞的风险,以便正确确定修复的优先级。

在分布式容器化应用中,可能难以了解应用的风险状况并确定其优先级。任何潜在应用中都可能存在数百个漏洞,但并非所有漏洞都具有相同的风险。漏洞的安全风险取决于以下因素:

  • 漏洞的严重性

  • 应用是否面向公众

  • 应用是否处于生产阶段

  • 应用是否在合规性法规的范围内

  • 应用是否访问敏感数据

  • 容器的权限级别

  • 容器的网络风险

尽管组织应该提前定义可接受的风险级别(通常是通过制定有关必须以多快的速度来修复每个严重级别漏洞的内部策略),但风险预测不是静态的。评估安全风险的过程(尤其是在容器化应用的环境中)必须在运行时持续进行。

手动对潜在的安全事件、漏洞和策略进行分类是导致错误和倦怠的一个重要原因。尤其是在规模较大的情况下,如果不依赖于自动化工具来发现和确定安全风险的优先级,风险预测通常是不可能的。要想在 Kubernetes 中成功地进行风险预测,就应该利用 Kubernetes 的声明性上下文数据来自动执行优先级排序过程。这样,安全团队就可以首先专注于修复最高风险的部署,而不是将时间花在风险预测过程上。

理想情况下,风险预测既可以用作被动性工具,也可以用作主动性工具。当在一个部署中发现并修复风险时,该信息可用于查找具有类似风险因素的其他部署,并提前主动解决潜在的安全风险。

运行时安全是一道抵御不法分子的关键防线。理想情况下,任何未修补的漏洞、不安全的配置或不安全的凭据都将在构建或部署阶段被捕获。但实际上,运行时检测和响应是必不可少的,因为有时漏洞会在这些早期阶段中漏网,并且还会有新的漏洞不断被发现。同时,出于合规性原因和作为抵御内部威胁的一道防线,运行时安全也同样很重要。

声明性、不可变的工作负载需要一个全新的模型来检测和响应运行时的潜在安全事件。由于容器通常运行最小数量进程,加之 Kubernetes 声明性的特性,实际上使运行时安全的某些方面比基于虚拟机(VM)的应用更便于实现。另一方面,不应该像将安全补丁应用于基于 VM 的应用那样"修补"正在运行的容器;相反,它们应被视为不可变的容器,从而予以终止、更新和重启。

检测是运行时安全的基石。这涉及为应用的行为方式找到基线,并调查偏离基线太远的任何活动。一些可能受到跟踪的活动包括网络请求和流程执行。当这些活动偏离预期时,就可能代表了一种潜在可疑或恶意活动的迹象。例如,试图在不允许的情况下连接至互联网。无论如何,这种异常行为都指向需要解决的问题。

相比基于 VM 的工作负载,容器中的异常检测要更为准确。这是由于容器仅包含一个应用,因此区分容器的基线行为和非基线行为会更容易。不过,异常检测也应该始终与事件响应过程相关联。

根据异常行为的类型,最好的方案可能是自动响应,让平台来终止受影响的容器集或容器。在其他情况下,发送警报并手动对行为做出评估可能更合适。但是,潜在的事件响应应尽可能实现自动化,以最大限度缩短响应时间并提高容器化应用的整体安全性。

kubelet 是在每个节点上运行的主要"节点代理"。正如这篇 Medium 文章所解释的那样,如果对它进行了错误配置,就会使您面临许多安全风险。您可以在运行中的 kubelet 可执行文件上使用参数或是使用 kubelet 配置文件来设置 kubelet 的配置。

要查找 kubelet 配置文件,请运行以下命令:

ps -ef | grep kubelet | grep config

查找 --config 参数,它会为您提供 kubelet 配置文件的位置。

然后,在每个节点上运行以下命令:

ps -ef | grep kubelet

在输出中,确保:

--anonymous-auth 参数为 false。在前面提到的 kubelet 文章中,错误配置之一是匿名(和未经身份验证)请求被允许由 kubelet 服务器提供服务。

--authorization-mode 参数显示为 AlwaysAllow(如果存在)。如果它不存在,请确保有一个由 --config 指定的 kubelet 配置文件,并且该文件已将 authorization: 模式设置为除 AlwaysAllow 以外的其他内容。

--client-ca-file 参数设置为客户端证书颁发机构文件所在的位置(如果存在)。如果它不存在,请确保有一个由 --config 指定的 kubelet 配置文件,并且该文件已将 authentication: x509: clientCAFile 设置为客户端证书颁发机构文件所在的位置。

--read-only-port 参数设置为 0(如果存在)。如果它不存在,请确保有一个由 --config 指定的 kubelet 配置文件,并且将 readOnlyPort 设置为 0

--protect-kernel-defaults 显示为 true。如果它不存在,请确保有一个由 --config 指定的 kubelet 配置文件,并且该文件将 protectKernelDefaults 设置为 true

--hostname-override 参数不存在,目的是确保 kubelet 与 API 服务器之间的 TLS 设置不会中断。

--event-qps 参数设置为 0。如果它不存在,请确保有一个由 --config 指定的 kubelet 配置文件,并且 eventRecordQPS 显示为 0

正确设置 --tls-cert-file--tls-private-key-file 参数,或是在由 --config 指定的 kubelet 配置文件中包含 tlsCertFiletlsPrivateKeyFile 的相应设置。该配置可确保所有连接都通过 kubelet 上的 TLS 进行。

如果您的 kubelet 是从 API 服务器获取证书,则将 RotateKubeletServerCertificate--rotate-certificates 设置为 true,并确保您的 kubelet 仅使用强加密密码

Kubernetes API 服务器处理来自集群内运行的用户或应用的 REST API 调用,以实现集群管理。考虑到 Kubernetes 控制平面的网关,您可以使用 kubectl、客户端库或通过直接发出 API 请求来访问 API 服务器。管理 Kubernetes API 服务器授权的方法之一是使用 Kubernetes 基于角色的访问权限控制(RBAC)。您也可以使用许可控制器来验证 API 服务器请求。

保护 API 服务器应从控制其访问权限入手。互联网安全中心(CIS)提供了相关的配置最佳实践来强化和保护 API 服务器。

在您的主节点上运行以下命令:

ps -ef | grep kube-apiserver

在输出中,检查并确保:

--anonymous-auth 参数显示为 false。该设置可确保未被其他身份验证方法拒绝的请求不会被视为匿名请求,因此按照策略将被允许访问。

--basic-auth-file 参数不存在。基本身份验证将使用明文凭据,而不是首选令牌或证书进行身份验证。

--insecure-allow-any-token 参数不存在。该设置将确保只允许使用经过身份验证的安全令牌。

–kubelet-https 参数要么不存在,要么显示为 true。该配置可确保 API 服务器与 kubelet 之间的连接在传输过程中通过传输层安全性(TLS)而受到保护。

--insecure-bind-address 参数不存在。该配置将防止 API 服务器绑定到不安全的地址,以防在未经身份验证和未加密的情况下访问您的主节点,从而最大限度降低攻击者可能读取传输中的敏感数据的风险。

--insecure-port 参数显示为 0。该设置将阻止 API 服务器在不安全的端口上提供服务,从而防止对主节点的未经身份验证和未加密的访问,并将攻击者控制集群这一风险降至最低。

--secure-port 参数要么不存在,要么显示为 1 到 65535 之间的一个整数。它的作用是确保您的所有流量都通过 https 提供身份验证和授权。

--profiling 参数显示为 false。除非您遭遇瓶颈或需要解决某些问题,否则不需要预测功能;而且,该参数的存在还会让您不必要地暴露系统和程序的详细信息。

--repair-malformed-updates 参数显示为 false。该设置将确保 API 服务器拒绝客户端发出的格式故意错误的请求。

--enable-admission-plugins 参数设置为一个不含 AlwaysAdmit 的值。如果您将此设置配置为 AlwaysAdmit,那么即使请求未得到许可控制器插件的明确允许,它也会承认该请求,这样就会降低插件的有效性。

--enable-admission-plugins 参数设置为一个包含 AlwaysPullImages 的值。该配置可确保用户不能仅通过获知镜像的名称就将镜像从节点提取到任何容器集中。启用该控制后,将始终在启动容器之前提取镜像,而这需要有效的凭据。

--enable-admission-plugins 参数设置为一个包含 SecurityContextDeny 的值。该控制可确保您无法以容器集安全策略中未描述的方式来自定义容器集层面上的安全环境。

--disable-admission-plugins 参数设置为一个不含 NamespaceLifecycle 的值。不要禁用该控制,因为它可以确保不会在不存在的命名空间或已设置为终止的命名空间中创建对象。

--audit-log-path 参数设置为您希望用于存储审计日志的相应路径。对任何可用的 Kubernetes 组件(包括 Kubernetes API 服务器)启用审计始终是一个很好的安全实践。

--audit-log-maxage 参数设置为 30 天,或任何您必须存储审核日志文件以符合内部和外部数据保留策略的天数。

--audit-log-maxbackup 参数设置为 10,或任何一个可以帮助您满足旧日志文件保留数量合规性要求的数字。

--audit-log-maxsize 参数设置为 100,或任何一个可以帮助您满足合规性要求的数字。请注意,这里的数字 100 表示 100 MB。

--authorization-mode 参数存在,但不能设置为 AlwaysAllow。该设置可确保 API 服务器仅允许已得到授权的请求,尤其是在生产集群中。

--token-auth-file 参数不存在。该参数(如果存在)使用基于令牌的静态身份验证,而这种身份验证方式存在几个安全缺陷;请改用其他身份验证方式,例如证书。

--kubelet-certificate-authority 参数存在。当 API 服务器与 kubelet 之间存在连接时,该设置将有助于防止中间人攻击。

--kubelet-client-certificate--kubelet-client-key 参数存在。该配置可确保 API 服务器向 kubelet 的 HTTPS 端点验证自身。(默认情况下,API 服务器不执行这一步骤。)

--service-account-lookup 参数存在,且设置为 true。该设置旨在防止 etcd 中存在这样的实例:API 服务器仅验证身份验证令牌的有效性,但不确保请求中包含服务帐户令牌。

--enable-admission-plugins 参数设置为一个包含 PodSecurityPolicy 的值。

--service-account-key-file 参数存在,且设置为一个用于签署服务帐户令牌的单独公钥/私钥对。如果您不指定公钥/私钥对,它将使用来自 TLS 服务证书的私钥,这样就会禁止您轮转服务帐户令牌的密钥。

--etcd-certfile--etcd-keyfile 参数存在,以便 API 服务器使用客户端证书和密钥向 etcd 服务器标识自己。请注意,etcd 会存储本质上可能敏感的对象,因此任何客户端连接都必须使用 TLS 加密。

--disable-admission-plugins 参数设置为不含 ServiceAccount。该配置将确保在创建新容器集时,它不会使用同一命名空间内的默认服务帐户。

--tls-cert-file--tls-private-key-file 参数存在,以确保 API 服务器仅通过 TLS 提供 HTTPS 流量。

--client-ca-file 参数存在,以确保为 Kube 集群部署配置 TLS 和客户端证书身份验证。

--etcd-cafile 参数存在,其设置旨在确保 API 服务器必须通过 SSL 证书颁发机构文件向 etcd 服务器验证自身。

--tls-cipher-suites 参数的设置是以使用强加密密码为原则。

--authorization-mode 参数存在,且设置为一个包含 Node 的值。该配置将限制 kubelet 可以读取哪些与其节点关联的对象。

--enable-admission-plugins 参数设置为包含值 NodeRestriction。该插件可确保 kubelet 只能修改自己的 Node API 对象以及那些与其节点关联的 Pod API 对象。

--encryption-provider-config 参数设置为 EncryptionConfig 文件,而该文件中应包含所需的所有资源。该设置可确保存放在 etcd 键值存储中的所有 REST API 对象都是静态加密的。

确保对所有所需的资源使用 aescbc 加密提供程序,因为该加密提供程序被认为是最强的。

--enable-admission-plugins 参数包含值 EventRateLimit,用于设置 API 服务器所接受的事件数量限制,以优化集群的性能。

--feature-gates 参数不要设置为包含 AdvancedAuditing=false 的值。换句话说,请确保未出于审计和调查目的而禁用高级审计。

--request-timeout 参数要么不设置,要么设置为适当的值(既不太短也不太长)。默认值为 60 秒。

--authorization-mode 参数存在,且设置为一个包含 Kubernetes RBAC 的值。

该设置可确保 RBAC 处于打开状态。除了打开 RBAC 之外,您还应该遵循其他一些有关如何最好地使用 RBAC 的建议,其中包括:

  • 避免赋予用户 cluster-admin 角色,因为它会赋予对环境非常广泛的权力。如果实在要这么做,也应该非常谨慎。

  • 审核您的角色聚合规则,以确保正确使用它们。

  • 不要向主体授予重复的权限,因为这会令访问权限的撤销变得更加困难。

  • 定期删除未使用的角色。

容器和 Kubernetes 所面对的最大风险之一是这两种技术的默认配置都不安全。要想降低安全事件的风险,就需要在整个组织中统一地主动更改这些默认配置。如果由于疏忽、缺乏知识或工作流中未包含配置管理步骤而忽略这一步操作,会导致工作负载毫无必要地变得易受攻击。

 

容器中的默认设置

许多默认容器设置以及构建容器时的常见做法都会让容器变得易于受到攻击。以下是配置容器时需要注意的一些事项。

  • 指定用户。如果未指定用户,则默认为 root 用户,这样就可能会授予容器对主机的 root 访问权限。

  • 验证镜像。默认设置不会强制进行镜像验证,这样就可能会导致在不知不觉中提取受损害的镜像。

  • 设置资源限制。尽管可以配置资源限制,但默认情况下并没有任何限制。限制容器可以消耗的 CPU 和内存,将有助于防止容器在受损时消耗大量资源。

  • 有选择地安装工具和库。容器中的工具和库越少,不法分子在访问容器时所能利用的工具也就越少。确保不要毫无选择地在每个容器中安装一组标准工具,而是仅安装实际需要的工具。

  • 通过允许列表来控制对镜像仓库的访问。除了确保所用的任何镜像都来自可信的来源之外,还必须严格控制对镜像仓库的访问,最好是通过允许列表将范围限制在受信任的用户上。

Kubernetes 中的默认设置

Kubernetes 还提供了许多用于巩固组织安全态势的工具,但必须进行主动配置才能发挥其安全优势。以下是在 Kubernetes 中需要注意的一些核心事项。

  • 配置基于角色的访问权限控制(RBAC)。在 Kubernetes 1.6 及更高版本中将默认启用 RBAC,但仍需要进行正确配置才能发挥其优势。理想情况下,访问权限应该由命名空间提供,而不是集群。

  • 使用命名空间。默认设置是在同一命名空间中运行所有内容。主动使用命名空间所提供的分隔功能可以将工作负载彼此隔离。

  • 使用 Kubernetes 网络策略。我们没有现成的网络策略,因此组织需要安装网络插件来控制应用的入口和出口流量,并相应地进行策略配置。

  • 启用审计日志。默认情况下通常并不启用审核日志,但为了查看异常 API 调用和授权失败,应将其打开。

缺乏深厚安全专业知识的开发团队往往最先使用容器和 Kubernetes。然而,无论使用何种类型的基础架构,忽视安全性都会让组织面临风险。

正如我们一再提到的那样,默认情况下,容器和 Kubernetes 中的配置都是不安全的。为了发挥其安全优势,必须主动配置 Kubernetes 的本地安全功能。要想让应用尽快上线,最快、最简单的方法通常是赋予它过多的权限和/或设置远远高于应用需求的资源限制——或者保持默认值不变。尽管组织一开始可能会忽视安全问题,尤其是当他们逐渐熟悉容器和 Kubernetes 时,但这样做会使他们面临重大的风险。不法分子可以像使用传统应用那样轻松地使用 Kubernetes 上的容器化应用。

坐以待毙所面临的主要风险就是应用将会被不法分子恶意损害。具体能带来多大的灾难性将取决于组织所属的行业、所使用的应用类型以及违规的范围和种类。因忽视安全而导致事故的可能性还取决于应用是否面向互联网等因素。

如果不采取任何措施来确保您的容器化应用安全无虞,就会让您的应用变得毫无必要地易受攻击。忽视安全会导致:

未修补的安全漏洞。新的安全漏洞在不断被发现,其中一些已经非常严重。这些漏洞一经发布,开源社区和不法分子就会立刻知道。如果不能迅速解决这些漏洞,势必带来风险。

宽松的权限。虽然 Kubernetes 中会默认启用基于角色的访问权限控制(RBAC),但具体实施访问权限控制则由开发人员来完成。如果没有安全指导,开发人员通常会创建具有过多访问权限的工作负载。

未隔离的工作负载。默认情况下,一切都可以在单个默认命名空间中运行。使用命名空间来隔离工作负载是一项基本的安全最佳实践。如果不自觉注意这一步的安全性,就不会有该级别的隔离发生。

网络策略的失控。Kubernetes 网络策略可以帮助组织控制流量,但它们需要网络插件才能进行策略配置。

等待应用安全控制最终将导致安全实践的不连贯,这一安全审查瓶颈会降低开发速度并增大安全事件的风险。相反,应帮助组织尽早并经常性地在软件开发生命周期中实施安全控制。

作为事实上的容器编排系统,Kubernetes 使容器管理成为可能,但同时也为基础架构环境引入了潜在的安全漏洞。容器和 Kubernetes 与虚拟机之间的安全性差异以及 Kubernetes 安全性方面的持续技能差距可能会导致不必要的安全风险。

与所有的安全最佳实践一样,Kubernetes 的安全最佳实践既包括让应用和基础架构更安全的最佳实践,也包括组织和文化实践,其目的是实现对安全性的集中控制。

无论公司依赖何种技术堆栈,制定和执行组织安全策略都称得上是一项最佳实践。安全防护是一个风险管理的过程,不能单纯依靠工具来决定每个应用可以接受多大的风险(举例而言)。这种决定必须由人来做出,他们会综合考虑组织、单个业务部门以及每个应用可以接受的风险程度。

对安全进行集中化控制。针对第一点,组织需要一种方法来确保其制定的安全和监管策略得到遵守。中央团队需要了解整个分布式应用中的配置和漏洞,并应该有一种方法可以轻松地将潜在问题可视化并确定其优先级。此外,他们还需要能够建立防护机制,以便当构建过程中存在风险配置、不安全镜像或其他潜在安全风险时,个人可以获得即时反馈。

尽早与安全部门合作。通过将安全性提前到开发阶段并在开发过程中尽早与安全部门合作,不仅有助于消除安全审查瓶颈并更快地推出应用,而且还降低了出错(会导致漏洞或错误配置被利用)的可能性。

充分利用好自动化。随着 Kubernetes 的足迹扩展到多个集群和数百个命名空间,手动管理配置或监控运行时行为已经是不可能了。

而且,现在还有一些非常重要的技术最佳实践,专门用于提高 Kubernetes 的安全性。

  • 使 Kubernetes 保持最新状态。由于并不总是针对旧版本发布安全补丁,因此最好运行受支持的较新版本。

  • 采用基于角色的访问权限控制。访问权限应始终基于最低特权进行配置。

  • 限制容器集之间的通信。为了让容器集按设计运行,限制应尽可能严格。

  • 使用网络分段。每个容器集都应该只能与其需要的内部或外部资源进行通信,而与其他所有资源保持隔离。

漏洞管理是保障应用安全的一个关键组成部分。它是指在软件开发生命周期的各个阶段识别、评估和修复安全漏洞的过程。云原生容器化应用中的漏洞管理需要实现自动化,并集成到构建和交付应用的 DevOps 流程中。环境过于复杂,因此无法手动管理漏洞。而在现实世界中,如果会减慢开发速度,就会有太多的组织倾向于跳过安全保护措施。

漏洞管理不是应用的必经之门,而是一个持续的过程,即从构建阶段的镜像扫描和自检开始,并在测试和生产环境中贯穿应用的整个生命周期。

在构建阶段进行镜像扫描和实施有关镜像漏洞的策略是实现有效容器原生漏洞管理的第一步。在构建镜像时或在容器运行时按需执行扫描的能力对于发现运行时可能暴露的漏洞至关重要。漏洞管理必须能够发现容器和 Kubernetes 中的风险,因为两者都可能是漏洞的来源。

世上没有完全安全的应用,而良好的漏洞管理不仅可以让团队发现漏洞,而且还可以看到其他信息,从而帮助他们排定某个漏洞对组织所特有的重要性的优先级。例如,即便是高优先级的 CVE 也有不同的风险状况,具体取决于工作负载的敏感性。良好的漏洞管理就是能够平衡、评估修复并排定修复的优先次序,以尽可能地建立最佳安全态势。

对于漏洞管理而言,主要应在云原生应用中实现自动化。这就需要人类的智慧来定义策略,但工具应该负责发现策略违规情况并根据漏洞、风险等级和生命周期来采取适当的行动——从自动终止构建,到阻止部署或在生产中将它们扩展至零(scaling-to-zero)。

镜像和漏洞扫描应在构建阶段开始着手,但必须贯穿整个应用生命周期,包括运行时。这样可以随时发现新的安全漏洞,而在运行的部署中能够检测任何漏洞对于组织的安全态势至关重要。运行的部署中的漏洞可能会导致直接的安全风险,因此组织需要有一种方法来尽快检测和修复它们。

在构建阶段,不合规的镜像(包括那些具有严重漏洞和可修复漏洞的镜像)应终止其构建。DevOps 团队应该直接在 CI 系统中获得反馈。在部署时,安全工具可以应用许可控制来自动阻止那些在镜像中检测到已知漏洞的容器进行部署。了解如何确定修复的优先次序至关重要,具体则要视漏洞的严重性、工作负载的敏感性以及组织对安全风险的总体容忍度而定。组织应花时间创建自定义策略并使用相应的工具,以允许在构建时和部署时通过自动化来实施这些策略。在运行部署后,组织还应该继续扫描漏洞。

 

镜像扫描程序中的不同功能

并非所有镜像扫描程序都提供同等程度的全面检查:有些仅扫描底层操作系统,有些还扫描库,有些还进行语言级别的检查,有些则扫描文件内容。请选择其全面程度至少与组织需求相符的镜像扫描程序,以及与您的应用所使用的编程语言兼容的镜像扫描程序,这一点至关重要。

有些镜像扫描程序在每次拉取镜像时会执行实时扫描,但这种方法会增加延迟,因此组织必须自行决定这些实时信息对性能所造成的影响是否值得。

 

运行时扫描

与构建阶段的镜像扫描一样,并非所有检测到的漏洞都应得到相同的响应。组织需要一种方法,根据工作负载敏感性、数据敏感性、互联网风险以及检测到的漏洞严重性来确定修复重点的优先级。没有任何两个组织会采用相同的程序或服务级别目标来指导对所发现的漏洞做出相应的响应。例如,无论严重性或敏感性如何,在利用所发现的漏洞来阻隔每个容器方面都需要做出权衡。在运行的部署中成功进行漏洞扫描既需要正确的工具来确保正确的可见性和信息,也需要周到的组织安全策略,从而在漏洞管理与运营影响之间取得适当的平衡。

企业网络及其中分布式应用的复杂性在不断升高,用来强化渗透的威胁模式和方法也随之不断发生变化。安全边界只能作为保护内部网络的第一道防线,而不是一项用于保护基础架构和数据的全面策略。强大的安全性需要控制与策略的相互结合。

通过专注于提高内部应用流量的安全性,零信任网络可以担当化解安全难题的一个骨干力量。该模型推翻了过去一直坚持的原则,即防火墙网络内的所有流量都是可信的。相反,它假定:在得到证明之前,任何网络连接都不应该认为是安全的。

传统上,网络管理员的工作假设是:在其内部网络中发现的每个实体(无论是应用、服务器还是网络软件或硬件)都属于那里并且是可以信任的。有些应用不需要对客户端连接进行身份验证,或是依赖于静态的共享凭据(例如数据库的密码)。所有应用都必须处理自己所需要的身份验证或授权方案(如果它们使用的话)。通常,内部网络连接(即使是用于敏感服务的连接)并不使用任何加密措施。

现在,不少企业网络仍然遵循这种模式。然而,对于一个可以进入这一宽松环境中的不法分子而言,无论他是通过直接黑客攻击、被授权人员意外应用特洛伊木马还是仅仅因为网络防火墙中的一个漏洞,都可以利用这一隐含的信任网络来造成严重破坏。这种可能性尽管不是无穷尽的,但却是可预见的。从追踪明文网络数据包,到发现数据库或其他关键系统的应用密码,再到获得对网络设备的控制,这种情况为一些不可接受的风险打开了大门,包括数据泄露或丢失。

零信任构成了安全优先型生产基础架构的基础,而且其数量还在不断增多。它不是假定网络上的每个实体都可以在未经验证的情况下受到信任,而是假定没有任何东西是可以信任的,甚至网络基础架构本身也是如此。零信任框架并不提供规范性的实施或特定的技术集以供使用。相反,它描述了一组原则和目标,而将实施的具体技术细节留给每个组织来完成。

 

零信任架构

零信任架构一般遵循以下原则:

  • 安全控制应平等地应用于所有实体,无论是软件还是硬件,也无论其网络位置如何。

  • 网络连接应在两端(服务器和客户端)进行身份验证。现在通常是通过服务器进行客户端身份验证,但客户端也应验证它们是否已连接到有效的服务器。当连接跨越多个事务时,应重新验证连接,并根据需要重新对请求进行授权。

  • 授权应遵循最低特权原则,即仅允许客户端工作负载所需的最低权限。

  • 为了进行分析,所有的网络连接和事务都应受到持续监控。

在 Kubernetes 中实施零信任模型

Kubernetes 集群中的零信任模型是什么样的?虽然在 Kubernetes 集群中实施零信任原则的方法不仅限于一种,但服务网格已成为许多架构的常用解决方案。

服务网格会创建一个虚拟化网络层来连接和控制分布式应用服务。尽管大多数服务网格解决方案最初关注的并不是网络安全,而是促进和管理智能服务发现和请求路由,但现在最流行的开源项目一般都会提供适合零信任架构的功能。由于许多服务网格在力求创建不需要修改单个应用的覆盖层,因此免除了大部分要进行重大更改以启用严格身份验证和授权控制的负担。

支持 Kubernetes 的服务网格通常使用分散的点对点路由,即为每个单独的集群容器集提供自己的代理实例。这些代理可以管理客户端 TLS 证书;而在与其他服务建立连接或从其他客户端接收连接时,代理可以使用这些证书来证明其身份。这种使用 TLS 证书在客户端和服务器端提供身份证明的方法称为相互传输层安全协议(mTLS)。除了执行连接身份验证外,mTLS 还用于加密网络连接。除了在线身份验证和加密之外,不同的服务网格还支持不同的授权源,其范围涵盖了从静态列表到与第三方单点登录或其他服务的集成。

服务网格并没有为 Kubernetes 集群提供完整的零信任解决方案,但它们确实具有许多核心优势。即使您无法在 Kubernetes 集群中实现完美的零信任架构,在该方向上所做的任何渐进式的改变也将有助于保护您的集群及其工作负载。

Kubernetes 安全性入门

Red Hat OpenShift

企业就绪型 Kubernetes 容器平台,可实现全堆栈自动化运维,从而轻松管理混合云、多云和边缘部署。

Illustration - mail

获取更多类似的内容

免费订阅我们的 Red Hat Shares 通讯邮件