Elasticsearch:减少 Elastic 容器镜像中的 CVE(常见的漏洞和暴露)
作者:来自 Elastic Maxime Greau
在这篇博文中,我们将讨论如何通过在 Elastic 产品中切换到最小基础镜像并优化可扩展漏洞管理程序的工作流程来显著减少 Elastic 容器镜像中的常见漏洞和暴露 (Common Vulnerabilities and Exposures - CVEs)。
基于 Chainguard 镜像的 Elastic Stack
Chainguard 镜像是满足安全软件供应链要求的容器镜像集合,包括可验证签名、出处、软件物料清单 (software bills of materials - SBOM)、少量 CVEs 和小镜像尺寸。这些镜像建立在 Wolfi 项目之上,该项目旨在为容器化应用程序提供安全且最小的基础镜像。
从 8.16 版开始,Elastic 提供了基于 Chainguard 镜像的 Elastic Stack 容器变体。几天前发布的 Elasticsearch 8.16 的 Chainguard 变体与之前的版本相比 CVEs 数量较少,而正在开发的 8.17 开发版本已经降至仅 1 个低 CVE。
$ snyk container test docker.elastic.co/elasticsearch/elasticsearch-wolfi:8.17.1-SNAPSHOT
Package manager: apk
✔ Tested 58 dependencies for known issues, no vulnerable paths found.
...
Tested 108 projects, 1 contained vulnerable paths.
使用以下命令提取基于 Wolfi 的 Elastic Stack 镜像,如每个产品文档页面所述:
docker pull docker.elastic.co/elasticsearch/elasticsearch-wolfi:<VERSION>
docker pull docker.elastic.co/kibana/kibana-wolfi:<VERSION>
docker pull docker.elastic.co/logstash/logstash-wolfi:<VERSION>
docker pull docker.elastic.co/apm/apm-server-wolfi:<VERSION>
docker pull docker.elastic.co/elastic-agent/elastic-agent-wolfi:<VERSION>
docker pull docker.elastic.co/beats/filebeat-wolfi:<VERSION>
docker pull docker.elastic.co/beats/metricbeat-wolfi:<VERSION>
基于 Wolfi 的镜像不是默认镜像,原因如下:
- 为了避免破坏依赖 Ubuntu 软件包的客户工作负载
- 为了确保非 Elastic 用户可以继续从源代码构建默认镜像
- 为了在从 Docker Official、Docker Hub、AWS ECR 和 Elastic 容器注册表中提取默认 Elasticsearch 镜像时保持相同的用户体验
注意与 Docker 版本 20.10.10 或更高版本的兼容性
对于依赖 Docker 作为容器引擎的用户,部署基于 Wolfi 的 Elastic Stack 映像需要 Docker 版本 20.10.10(截至 2023 年 12 月 10 日将停止使用)或更高版本。不兼容是由于最近的映像使用了 glibc 版本 2.34 以上。glibc 2.34+ 默认使用新的 clone3 系统调用。为了向后兼容,glibc 在遇到 ENOSYS 错误时会尝试回退到 clone。但是,Docker 20.10.9 及更低版本中的默认 seccomp 过滤器会导致 EPERM 错误,glibc 会将其视为致命错误并阻止回退发生。已将修复程序反向移植到 Docker 版本 20.10.10 及更高版本,解决了兼容性问题。运行 Elastic Stack 8.16+ 的 ECE 客户需要 Docker 版本 20.10.10 或更高版本。
解决漏洞的方法
工程和信息安全团队致力于解决漏洞管理挑战,以实现多个目标:为我们的客户提供强化的容器;帮助遵守法规;改善我们的供应链安全态势;并减轻我们的客户、工程、安全和支持团队解决和分类 CVEs 的负担。影响涉及 Elastic 产品,包括 Elastic 自主管理产品 (Elastic Stack)、Kubernetes 上的 Elastic Cloud (ECK) 和 Elastic Cloud(无服务器和托管)。
从高层次上讲,第一步是定义组织内的团队如何遵守漏洞管理计划以及用于衡量合规性的相关服务级别目标 (SLO)。接下来,我们专注于部署工具和流程,以确保主动通知工程团队,使他们能够有效地管理他们的项目,以实现这些目标,并在违反这些 SLO 时做出适当的反应。该计划基于以下原则:
- (1) 建立安全基础:通过在 Chainguard 镜像之上构建,我们为在整个组织内默认安全构建奠定了成功的基础 — 提供自动快速的漏洞修复,而不会增加工程师的负担。
- (2) 针对容器工作负载进行优化:容器镜像中包含的每个组件都必须是目标运行时环境所必需的和优化的。
- (3) 持续代码分析:软件组合分析 (Software composition analysis - SCA) 工具持续运行,以在 Elastic 产品中构建全面的开源第三方组件清单,并主动识别和缓解可能因使用它们而影响我们产品的问题。
- (4) CVE SLO 质量门:在容器镜像发布或部署到生产环境之前启用 CVE SLO 检查的强制执行。
- (5) 持续监控:当生产中运行的产品不再合规时,团队会自动收到通知,因为经常会发现新的漏洞,包括影响在部署到生产环境时没有漏洞的容器镜像。
- (*) 频繁更新:对于该计划的成功至关重要,如果不频繁部署,(1) 至 (5) 中的努力将毫无用处。我们已制定流程,确保 (1)、(3) 或 (5) 触发的事件会导致新部署通知。
通过自动更新建立安全基础
确保 Elastic 工程师在为其容器产品使用基于安全的镜像并使其保持最新状态的工作流程建立在 Chainguard 镜像产品、Renovate 项目和供应链安全最佳实践的基础上。
Elastic 使用 Chainguard 开发人员和生产镜像的混合,这些镜像定期与它们的签名和 SBOM 同步到 Elastic 容器注册表。在同步之前,每个镜像签名都使用 cosign 进行验证。将这些镜像存储在 Elastic 注册表中可为 Elastic 工程师提供最佳的开发人员体验,降低第三方系统发生事故的风险,并确保控制生产中容器的来源。
我们向工程师提供概述几项关键实践的文档。首先,它强调了为每个使用的基础镜像引用标签和摘要的重要性 —— 将容器镜像固定到摘要可确保最大程度的构建可重复性,虽然镜像标签是可变的,但摘要不是。此外,鼓励工程师使用 Docker 多阶段构建,将构建时的全功能镜像与运行时的无发行版镜像相结合。无发行版镜像仅包含应用程序及其运行时依赖项,从而显著减少了容器的攻击面,从而最大限度地降低了与基础镜像相关的漏洞风险。
Renovate 是一个开源工具,用于自动维护软件依赖项。它配置为通过自动提出拉取请求来修改基础镜像摘要,从而改善开发人员更新 Elastic GitHub 存储库中使用的 Chainguard 镜像的体验,只要有新的镜像可用。如下所示,Renovate 在 Elasticsearch 存储库中配置为确保当 Chainguard 提供新版本时,基础镜像摘要会在可发布的 git 分支上自动更新:
ECK 2.16 发布,无 CVE
ECK 基于 Kubernetes Operator 模式构建,扩展了基本的 Kubernetes 编排功能,以支持 Elastic Stack 的设置和管理。2024 年 12 月 18 日,ECK 2.16.0 发布,无 CVE!
$ snyk container test docker.elastic.co/eck/eck-operator:2.16.0
✔ Tested 3 dependencies for known issues, no vulnerable paths found.
...
✔ Tested 707 dependencies for known issues, no vulnerable paths found.
Tested 2 projects, no vulnerable paths were found.
查看 ECK 存储库代码库,尤其是 Dockerfile,它说明了上面提到的最佳实践:
- 使用 Chainguard Go 映像的多阶段构建阶段从 Elastic 容器注册表构建二进制文件,该二进制文件通过标签和摘要值引用,以确保构建可重复性和自动更新:
# Build the operator binary
FROM docker.elastic.co/wolfi/go:1.23.4@sha256:0c563962687ca1d5677b810d2fcb6c1dcb7bd650c822999c715ad715590f14bb AS builder
...
# Build
RUN --mount=type=cache,mode=0755,target=/go/pkg/mod \
CGO_ENABLED=0 GOOS=linux LICENSE_PUBKEY=/$LICENSE_PUBKEY make go-build
- 使用无发行(distroless)版镜像的多阶段运行时阶段可减少始终由标签+摘要值引用的攻击面:
FROM docker.elastic.co/wolfi/static:latest@sha256:5ff428f8a48241b93a4174dbbc135a4ffb2381a9e10bdbbc5b9db145645886d5
...
COPY --from=builder /go/src/github.com/elastic/cloud-on-k8s/elastic-operator /elastic-operator
...
ENTRYPOINT ["/elastic-operator"]
CMD ["manager"]
本文中描述的任何特性或功能的发布和时间均由 Elastic 自行决定。任何当前不可用的特性或功能可能无法按时交付或根本无法交付。
原文:Reducing CVEs in Elastic container images | Elastic Blog