Kubernetes的DevSec指南 Kubernetes®是真正的容器编排系统,在部署和管理云原生应用时为开发团队提供无与伦比的规模、灵活性和速度。然而,尽管有诸多好处,但也带来了新的复杂性和风险。 在本指南中,我们将探索Kubernetes为云原生应用安全性提供的独特注意事项,以及如何在其内置的安全基础上构建以采用DevSecOps。 我们的主要任务是,利用Kubernetes的内置安全功能和用于配置集群及其组件的安全基础架构即代码(IaC)模板来保护Kubernetes基础架构和容器的安全。 目录 Kubernetes的基本安全注意事项3 每个层级的Kubernetes安全3 内置Kubernetes安全功能3 Kubernetes和IaC4 Kubernetes的基本安全最佳实践5 Kubernetes主机基础架构安全5 Kubernetes集群的IAM安全5 容器注册表安全5 避免上传“最新”容器映像6 避免特权容器和升级6 网络级别的孤立Pod6 加密内部流量6 指定资源限制6 避免使用默认命名空间6 启用审核日志记录7 保护开源Kubernetes组件7 DevOps生命周期的Kubernetes安全7 开发8 构建并部署8 运行时8 反馈和规划9 云原生应用的DevSecOps技巧9 人员9 进程9 工具10 关键性能指标(KPI)10 结论11 Kubernetes的基本安全注意事项 为了帮助管理大规模的容器化,Kubernetes这一真正的容器编排系统越来越受欢迎。在部署和管理云原生应用时,该产品为开发团队提供了无与伦比的规模、灵活性和速度。然而,尽管有诸多好处,但也带来了新的复杂性和安全注意事项。 每个层级的Kubernetes安全 Kubernetes安全具有挑战性的最大原因在于,它并非单一的简单框架,而是一个多层次的复杂框架。每个层级都具有一系列安全挑战,需要唯一的解决方案。由于各层级相互关联,如果一层中存在安全漏洞(如基础架构错误配置),则另一层的任何问题(如容器映像漏洞)都会被放大。以下是需要解决的基本问题: •集群:保护Kubernetes部署需要保护底层基础架构(节点、负载平衡器等)、可配置组件以及集群中运行的应用,包括维护底层节点的状态以及控制API和kubelet的访问权限。阻止恶意工作负载在集群中运行,并通过严格的网络控制隔离工作负载通信也十分重要。 •控制平面:控制平面也称为母节点,包括调度程序、API服务器和其他组件,为集群中的工作节点制定全局决策。最大限度降低管理员级别对控制平面的访问权限,确保您的API服务器不会公开暴露是最重要的安全基础。 •Pod:指Kubernetes节点托管Pod或工作负载,是共享常见配置的容器集合。使用网络策略隔离相互独立的Pod之间的通信,对于阻止发生入侵时在容器中横向移动非常重要。Kubernetes还具有内置功能,用于定义Pod的行为方式及其可以访问的内容。 •容器:容器的安全性取决于组成这些容器的映像安全性。必须使用可信的注册表和存储库,并在构建时扫描其中的漏洞。监控运行时容器中的可疑活动也很重要,例如在内部运行的shell或泄露的敏感数据。 •代码:应用和基础架构代码几乎完全由最终用户控制,因此经常向攻击者展示攻击面中最容易渗透的部分。最大限度减少已知漏洞和攻击载体可以减少应用被恶意利用的方式。 基础架构代码 应用代码 代码 内置Kubernetes安全功能 集群 云API 节点 Pod 容器 kubelet 控制平面 控制程序 调度程序 API服务器 etcd 图1:Kubernetes基础架构图 容器注册表 为了帮助发现复杂且相互关联的攻击面,Kubernetes提供了以下安全功能: •基于角色的Kubernetes访问控制(RBAC):借助RBAC,您可以根据角色和身份限制服务的访问权限。此功能通过授权来控制用户和应用对于资源的访问权限,以便通过限制谁可以访问哪些内容来提高集群的安全性。 •网络策略:这些策略可助您定义Pod通过网络与不同网络元素(端点和服务)通信的方式,以便在IP地址和端口级别调节群集中特定应用的流量。 •准入控制器:这些插件可作为防护措施使用,用来拦截API请求,并在拒绝或修改以符合策略要求之前确定其是否违反预定义策略。如果配置正确,准入控制器可用于提供几个基本的Kubernetes最佳实践,如限制和请求,并确保Pod不会授予过多权限。 •Kubernetes入口的传输层安全(TLS):您可以使用一组规则定义哪些入站连接可以使用哪些服务,以此配置对于Kubernetes入口的访问权限,从而允许您将所有路由规则组合到单个资源中。包含TLS私钥和证书的机密内容可用于保护Kubernetes应用。入口仅支持一个TLS端口443,该端口假定TLS已终止。TLS机密中必须含有名为tls.crt和tls.的密钥,它们分别包含TLS证书和私钥。 •Pod安全策略:PSP允许您通过指定一组要求来控制Pod和容器的行为,Pod必须遵守这些要求才能被集群接受;如果创建或更新Pod的请求不符合要求,则该请求将被拒绝,并返回错误。PSP还十分不完善,这也是它遭到弃用的原因。 这些内置功能为限制Pod和容器行为的访问和控制创建了一些防护措施。也就是说,一个真正安全的Kubernetes 环境需要全面的自动化方法。 Kubernetes和IaC 手动配置Kubernetes集群及其附加组件既耗时又容易出错。IaC利用机器可读文件以编程方式管理数据服务器、存储和网络等资源,从而实现版本控制、可审核性以及更轻松的协作和测试。 apiVersion:应用/v1 类元别数名:据部:署 规格:应用:nginx 标称签:nginx-deployment 复选择制器产:品:3 模板:应用:nginx matchLabels: 元数标据签:: 规格:应用:nginx -名称nginx 容器: 映 像: nginx:1.14.2 -containerPort:80 端口: Kubernetes清单文件是IaC的一个示例。清单以JSON或YAML格式编写,指定您应用清单时Kubernetes维护的对象的期望状态。以下是NGINX部署到Kubernetes集群的示例清单: 此外,经过打包的清单(如Helmcharts和Kustomize文件)通过降低复杂性和重复进一步简化了 Kubernetes。 IaC最大的安全优势是助您在开发生命周期的早期进行扫描,以便在部署之前发现容易被忽视的错误配置。 要点:IaC安全是关键所在 自动化和连续的IaC扫描是DevSecOps的一个重要组成部分,对于保护云原生应用至关重要。 Kubernetes的基本安全最佳实践 实施DevSecOps来保护云原生应用时,了解基本的Kubernetes基础架构陷阱以及IaC如何帮助减轻每项挑战至关重要。 以下是一些最常见的Kubernetes安全错误和错误配置: •导致主机基础架构易受攻击 •为集群和注册表授予过多权限 •在特权模式中运行容器并支持特权升级 •获取“最新”容器映像 •无法隔离Pod及加密内部流量 •忘记指定资源限制及启用审核日志记录 •使用默认命名空间 •合并不安全的开源组件 Kubernetes主机基础架构安全 我们可以从Kubernetes环境最基本的层级:主机基础架构开始。这是作为Kubernetes节点使用的裸机和/或虚拟服务器。保护这种基础架构首先要确保每个节点(无论是工作节点还是父节点)都能抵御安全风险。一种简单方法是使用IaC模板来配置每个节点,这些模板可在配置和操作系统级别实施安全最佳实践。 编写IaC模板时,请确保将映像模板和/或节点的启动脚本配置为仅运行作为节点所必需的软件。应排除无关的存储库、数据包和服务。您可能还希望为节点提供内核级安全强化框架,并采用基本的保护措施,如加密所有关联存储。 Kubernetes集群的IAM安全 除了使用KubernetesRBAC管理集群中的内部访问控制之外,根据Kubernetes的运行位置和方式,您还可以使用外部云服务来管理Kubernetes环境的访问控制。例如,借助AWSEKS,您可使用AWSIAM根据单个用户的需求授予Kubernetes集群不同的访问级别。 使用最低权限方法来管理IaC中的IAM角色和策略,可以最大限度降低手动配置错误的风险,此类错误可能会向错误的用户或服务授予过度宽松的访问权限。您还可以使用IaC扫描工具(如我们的开源工具Checkov)扫描您的配置,从而自动捕获过度宽松或未使用的IAM角色和策略。 容器注册表安全 尽管容器注册表不是原生Kubernetes的一部分,但在基于Kubernetes的应用部署管道中得到广泛使用,以便存储和托管在Kubernetes环境中部署的映像。访问控制框架因容器注册表而有所不同。借助这些工具,您可以通过公有云IAM框架来管理访问。无论如何,您通常可以使用IaC进行定义、应用和管理。 采取这些操作时,您需要确保只有需要访问容器映像的注册表用户才能访问这些内容。您还应该阻止未经授权的用户将映像上传到注册表中,因为不安全的注册表是威胁攻击者将恶意映像推送到您的环境中的绝佳方式。 避免上传“最新”容器映像 Kubernetes从容器注册表中提取映像时,会自动提取注册表中标有“最新”标签的指定映像版本。 虽然这看似合乎逻辑,毕竟,您通常需要最新版本的应用,但从安全角度来看,这可能是有风险的,因为依赖“最新”标记会导致更加难以跟踪您正在使用的容器的特定版本。相反,您可能不清楚容器是否存在安全漏洞或映像入侵攻击,从而影响应用中的特定映像。 为了避免出现这种错误,请指定映像版本,更好的做法是在提取映像时指定映像清单,并审核Kubernetes配置,以检测缺少映像特定版本选择的实例。这需要的工作量更少,但是从Kubernetes安全的角度来看十分值得。 避免特权容器和升级 容器级别的关键安全考虑旨在确保容器不在特权模式下运行。在特权模式下运行容器会授予过多权限,以便不受限制地访问主机级资源,但不幸的是,这个错误经常发生。 securityContext: allowPrivilegeEscalation:false 使用IaC可轻松禁止权限提升。只需编写一个可拒绝权限升级的安全上下文,并确保在定义Pod时添加该上下文即可: 然后,确保不使用“特权”标志或通过授予CAP_SYS_ADMIN来直接授予特权。您可以使用IaC扫描工具来检查是否缺少此安全上下文,并在Pod设置中捕获任何其他权限升级设置。 网络级别的孤立Pod 默认情况下,在Kubernetes中运行的所有Pod都可以通过网络与任何其他Pod对话。因此,除非您的Pod需要相互通信(通常只有当它们是相关工作负载的一部分时才有这种需求),否则您应该进行隔离,以实现工作负载之间更高级别的分段。 只要您有支持网络策略的Kubernetes网络层(大多数都支持,但一些Kubernetes发行版默认使用缺乏这种支持的CNI),您就可以编写网络策略来指定所选Pod在进行入口和出口操作时可以连接到其他哪些Pod。在代码中定义所有内容的价值在于,您可以扫描代码以检查配置错误或疏忽,因为这些内容可能会授予比预期更多的网络访问权限。 加密内部流量 另一个微小而关键的设置是---kubelet-https=...标记。应将其设置为“true”。如果不是,系统就不会对您的 API服务器和kubelets之间的流量进行加密。 完全省略该设置通常也意味着在默认情况下加密流量。但是因为这种行为可能会因您使用的Kubernetes版本和发行版而有所不同,所以最佳做法是明确要求加密kubelet,至少在Kubernetes开发人员默认批量加密流量之前采取此做法。 指定资源限制 您可能认为Kube