容器镜像是云原生环境中各类应用的标准交付格式。由于容器镜像需要大量分发和部署,因此,需要确保容器镜像在构建、分发和运行全生命周期内的安全。镜像扫描是检查操作系统和安装包中是否存在已知漏洞的一项基本措施。除此之外,还有很多措施可以加强容器镜像的安全。如下表所示,基于镜像安全4个阶段,11个要求,28项检查点,全面检测容器生命周期各个阶段的镜像风险,确保容器镜像的安全。
构建阶段
基础设施的安全
为了从源头开始确保镜像安全,实现安全左移,需要确保镜像构建、CI/CD基础设施的安全,防止将外部漏洞引入到镜像当中来。
下列措施有助于确保构建基础设施和管道的安全:
限制对构建镜像相关的基础设施的管理访问权限
仅允许使用规定的网络入口
谨慎管理各类秘钥,并且仅授予完成必要工作所需的最低权限
从第三方站点拉取源文件或其它文件时,仔细审查文件是否存在漏洞,可使用白名单,仅允许受信站点访问
确保扫描工具的安全性和可靠性,才能获得可靠的扫描结果
根镜像
在现有的第三方根镜像上构建镜像,则需要考虑到以下因素:
根镜像来源和托管机构的可信度。镜像是来自知名公司还是开源组织?其维护的镜像仓库是否拥有良好的信誉?镜像中所有组件的Dockerfile和源代码是否可用?
更新频率。避免使用不经常更新的镜像,尤其是不对相关漏洞做出披露的镜像。
默认安装的软件。从最基本的根镜像开始,有选择性地安装应用所需的工具和库,这要比从现成镜像中找出需删除的软件包,更安全可靠。
下面是一些常见选择根镜像的方案:
Google Distroless——Google针对几种常见语言预先构建的最小根镜像。镜像中没有软件包安装程序,如果需要其他软件,可以将文件复制到镜像中。
Red Hat通用根镜像(UBI)——基于RHEL的镜像。其镜像分为三层——最小根镜像、标准平台和多服务。它还支持多种语言的镜像。
自己从头开始构建根镜像。
删除不必要的软件
如果恶意攻击者确实访问了运行中的容器,那么也该确保攻击者进入容器后,容器内不会有其它地方存在漏洞成为黑客进一步攻击的抓手。使用最小根镜像就是一个很好的入手点,但是如果Dockerfiles安装了很多工具,就不如使用最小根镜像那么安全了。使用最小镜像的另一个好处就是,可以减少遇到0day漏洞的可能性,从而减少了对镜像打补丁和进行维护的需求,也加快了镜像的存储和拉取速度。
将镜像限制为二进制文件、库和配置文件,可提供最佳保护。特别是,尽量要避免安装以下工具:
软件包管理器:例如apt、yum、apk
Unix shell:例如sh、bash。删除shell程序后,在运行时无法再使用shell脚本,但可以使用编译语言。
编译器和调试器。只有在构建和开发容器时,才使用编译器和调试器,而在生产容器中则绝不使用。
如果在生产镜像中需要安装这些工具进行应用调试,建议创建临时调试镜像。Kubernetes目前也支持临时容器,可以将容器放置在现有的pod中进行调试。
容器的构建
在生产系统上运行时,用于生成和编译应用的构建工具会被黑客利用。应该将容器视为短暂存在的临时实体。不要想着对运行中的容器进行打补丁或更改容器。只能通过构建一个新镜像,然后替换过时的容器部署。使用多级Dockerfile,在运行时镜像以外的地方进行软件编译。
秘钥
切勿将任何秘钥嵌入镜像,即便只是供内部使用,也不建议这样做,因为任何能够拉取镜像的人都可以提取秘钥。秘钥包括TLS证书秘钥、云提供商的凭据、SSH私钥和数据库密码等等。只在运行时提供敏感数据,这还可确保能够在不同的运行时环境中使用同一镜像。这样,无需重新构建镜像,就能够简化更新过期秘钥或吊销秘钥的流程。
不使用嵌入式秘钥时,还可以向Kubernetes Pod提供秘钥作为Kubernetes秘钥,或使用其他秘钥管理系统。
镜像扫描
若镜像中所含的软件存在安全漏洞,则容器在运行时就更容易受到攻击。因此,通过CI/CD构建镜像时,镜像扫描是一个必然要求。不安全的镜像不能推送到镜像仓库中去,以免在生产中误用了存在漏洞的镜像。
目前,有一些开源的镜像扫描工具可供使用,但它们提供的覆盖范围不尽相同。有些扫描工具只是扫描已安装的操作系统软件包,有些会扫描已安装的运行时存储库,而另一些则可能会提供二进制指纹验证或文件内容扫描。
具体选择什么样的扫描工具,取决于所需要扫描的范围(编程语言等),以及对漏洞风险的接受度。对于那些安全要求高的企业,选择商用的镜像扫描,例如青藤蜂巢产品,可以实现更高质量镜像扫描。
分发阶段
选择镜像仓库
构建好容器镜像后,需要将其进行存储。使用内部的私有镜像仓库可最大限度地确保安全和配置,但是也需要谨慎管理镜像仓库的基础架构和访问控制。大多数云提供商还提供托管镜像仓库服务,其通常会自带云访问管理功能。
使用镜像仓库,可以减轻许多管理开销。安全工程师和开发人员将需要根据其安全要求和基础架构资源,为其组织选择最佳解决方案。
镜像控制
镜像仓库支持对镜像添加不可变标签,防止对不同版本的镜像重复使用同一个标签,从而能够执行确定的镜像运行时。例如,要想能够准确地知道要在什么时间,部署某个应用的、某个镜像的、某个版本,在这种情况下,如果每个镜像都标记“最新”标签,就会造成混乱。
镜像签名也可以增强安全防护。通过镜像签名,镜像仓库会生成标记镜像内容的校验和,然后使用私钥来创建含有镜像元数据的加密签名。客户端仍然可以在不验证签名的情况下,拉取并运行镜像,但是在安全环境中,运行时应支持镜像验证要求。镜像验证使用签名密钥的公钥,来解密镜像签名的内容,然后可以将其与提取的镜像进行比较,以确保镜像内容未被篡改。
运行阶段
镜像扫描
在镜像构建时进行镜像扫描,并不意味着运行时就不需要镜像扫描了。相反,对于可能使用的任何第三方镜像和自己的镜像(其中可能包含新发现的安全漏洞),在运行时进行镜像扫描更为重要。可以在Kubernetes集群中使用自定义或第三方访问控制器来避免部署不安全的容器镜像。
尽管某些扫描工具支持将扫描结果存储在数据库或缓存中,但用户需要权衡信息失效和每次拉取镜像进行扫描所引起的延迟。
镜像仓库和镜像信任
在“分发”部分,我们讨论了选择镜像仓库的标准以及某些镜像仓库支持的一些其他安全功能。尽管确保镜像配置正确,且使用了安全的镜像仓库很重要,但是如果不在客户端强制执行这些保护措施,安全依然无法得到保障。
Kubernetes本身并不提供安全镜像的拉取服务。这就需要部署一个Kubernetes访问控制器,验证Pod使用的是受信任的镜像仓库。为了支持签名镜像,控制器需要能够验证镜像的签名。
后期维护
镜像的漏洞管理
在容器的全生命周期内,镜像扫描是至关重要的,这时就需要权衡组织机构的风险承受能力和交付速度。组织机构需要制定对应策略和流程来处理镜像安全和漏洞管理。
根据以下指标来确定漏洞管理标准:
漏洞严重性
漏洞数量
这些漏洞是否具有可用的补丁或修补程序
漏洞是否影响配置错误的镜像的部署
基于漏洞严重性、漏洞数量、是否具有补丁等标准,首先,可以帮助用户决定是否允许存在问题(不严重)镜像进行部署上线。其次,发现新的漏洞后,是否要阻止使用现有镜像进行部署,最后,确定对于已经部署了有问题镜像的容器,该如何处理。
写在最后
持续进行镜像扫描是检查镜像中是否存在已知漏洞的一个重要手段,对于确保镜像安全有很大的作用。上文不仅介绍了在容器全生命周期内要对镜像进行持续扫描,还介绍了一些重要措施,可大大增强镜像安全。
原文链接:https://mp.weixin.qq.com/s/fJ2ZsK8vV15iuyYTMG91TQ
http://dockone.io/article/10542