在离线环境中更新 Trivy 漏洞数据库

本文档说明如何通过构建并发布自定义的离线漏洞数据库镜像,在隔离网络环境中保持 Harbor 的 Trivy 扫描器处于最新状态。

默认情况下,Trivy 会从互联网下载漏洞数据库。在离线环境中,这一操作不可用,因此扫描结果会变得过时或不可用。Harbor 支持改为从预构建镜像加载数据库——本文将介绍如何构建该镜像并让 Harbor 使用它。

前提条件

  • 已由此 Operator 管理并运行中的 Harbor 实例。
  • 一台可访问互联网的机器,用于构建数据库镜像。
  • Harbor 集群可访问的私有容器镜像仓库,并具备推送镜像的凭据。
  • 具备编辑 Harbor CR(harbors.operator.alaudadevops.io)的权限。

步骤 1 - 构建离线数据库镜像

在一台可访问互联网的机器上,创建一个包含以下内容的 Dockerfile。将 <TRIVY_VERSION> 替换为构建时可用的最新 Trivy 版本。

FROM jitesoft/trivy:<TRIVY_VERSION> AS source
WORKDIR /opt/trivy
RUN TRIVY_TEMP_DIR=$(mktemp -d) && \
    trivy --cache-dir $TRIVY_TEMP_DIR image --download-db-only && \
    tar -czf ./trivy-offline.db.tgz -C $TRIVY_TEMP_DIR/db metadata.json trivy.db

FROM alpine:3.17
COPY --from=source /opt/trivy/ /
RUN apk add --no-cache jq

将镜像构建并推送到私有镜像仓库:

podman build -t <PRIVATE_REGISTRY>/<PROJECT>/trivy-offline-db:<TAG> .
podman push <PRIVATE_REGISTRY>/<PROJECT>/trivy-offline-db:<TAG>

生成的镜像根目录中必须包含 /trivy-offline.db.tgz——Harbor 的 init 容器会按这个确切路径进行查找。

步骤 2 - 在 Harbor CR 中启用离线扫描

编辑 Harbor CR,将 trivy.offlineScan 设置为 true,然后将 global.images.trivyOfflineDB 指向步骤 1 中构建的镜像:

spec:
  helmValues:
    trivy:
      offlineScan: true
      skipUpdate: true
      skipJavaDBUpdate: true
    global:
      images:
        trivyOfflineDB:
          repository: <PROJECT>/trivy-offline-db
          tag: <TAG>

如果离线数据库 init 容器在解压 trivy-offline.db.tgz 时内存不足,可以仅为 init 容器提高资源配置,而无需增加主 Trivy 容器的常驻资源:

spec:
  helmValues:
    trivy:
      offlineDBInitResources:
        requests:
          cpu: 200m
          memory: 512Mi
        limits:
          cpu: 1
          memory: 2Gi

字段说明:

字段说明
trivy.offlineScan启用 init 容器,将离线数据库解压到 Trivy 的缓存目录中。
trivy.offlineDBInitResourcesinit-offline-db init 容器的可选资源请求与限制。当离线数据库解压所需内存高于主 Trivy 容器在运行时所需内存时,可使用此项。
trivy.skipUpdate阻止 Trivy 尝试从互联网刷新主数据库。建议在完全隔离网络环境中启用。
trivy.skipJavaDBUpdate阻止 Trivy 从互联网刷新 Java 数据库。建议在完全隔离网络环境中启用。
global.images.trivyOfflineDB.repository / .tag标识步骤 1 中构建的镜像。完整镜像地址会基于你配置的镜像仓库前缀进行解析。

应用更改并等待 Trivy Pod 完成滚动更新。

步骤 3 - 验证数据库已加载

确认 init 容器已成功运行,并且 Trivy 已加载新的数据库:

# init 容器应已成功完成
kubectl -n <NAMESPACE> describe pod <RELEASE>-harbor-trivy-0 | grep -A5 init-offline-db

# Trivy Pod 中的数据库元数据应反映较新的构建时间戳
kubectl -n <NAMESPACE> exec -it <RELEASE>-harbor-trivy-0 -- \
  cat /home/scanner/.cache/trivy/db/metadata.json

在 Harbor UI 中触发任意镜像的扫描,并确认漏洞结果按预期显示。

保持数据库更新

由于漏洞数据库会频繁变化,请定期重新构建并推送新镜像,以避免扫描结果过时。推荐通过计划任务型 CI 作业执行步骤 1 中的构建流程,并同步更新 Harbor CR 中的 tag

说明

  • ARM / 多架构。 如果集群运行在非 amd64 架构上,请将 trivyOfflineDB 镜像构建为多架构镜像,或为运行 Trivy Pod 的节点架构单独构建对应镜像。
  • 镜像拉取。 请确保 Harbor 集群可以从你的私有镜像仓库拉取镜像。如果需要认证,请在 Harbor 命名空间中配置 image pull secret。