容器扫描

您的应用程序的 Docker 镜像本身可能基于包含已知漏洞的 Docker 镜像。通过在流水线中包含一个额外的容器扫描作业来扫描这些漏洞,并在合并请求中显示它们,您可以使用极狐GitLab 来审核基于 Docker 的应用程序。

容器扫描通常被认为是软件组合分析 (SCA) 的一部分。SCA 可以包含检查代码使用的项目的各个方面。这些项目通常来自从外部源导入的应用程序和系统依赖项,而不是来自您自己编写的项目。

极狐GitLab 提供容器扫描和依赖扫描,确保覆盖所有依赖类型。为了尽可能多地覆盖您的风险区域,我们鼓励您使用我们所有的安全扫描器。

概览

极狐GitLab 与开源工具集成,用于容器中的漏洞静态分析:

您可以通过执行以下操作之一来启用容器扫描:

极狐GitLab 比较源分支和目标分支之间发现的漏洞,并在合并请求中直接显示信息。

Container Scanning Widget

要求

要在流水线中启用容器扫描,您需要满足以下条件:

  • 容器扫描在默认情况下可用的 test 阶段运行。如果在 .gitlab-ci.yml 文件中重新定义阶段,则需要 test 阶段。
  • GitLab Runner 与 docker 或在 Linux/amd64 上的 kubernetes executor。
  • 在私有化部署版上,Docker 18.09.03 或更高版本与 runner 安装在同一台计算机上。
  • 支持的发行版匹配的镜像。
  • 构建并推送 Docker 镜像到您项目的容器镜像库。
  • 如果您使用第三方容器镜像库,您可能需要通过 DOCKER_USERDOCKER_PASSWORD 配置变量提供身份验证凭据。 有关如何使用这些变量的更多详细信息,请参阅向远端镜像库进行身份验证
  • GitLab CI/CD 流水线必须包含 test 阶段,除非被 stages 关键字覆盖,否则该阶段可用。

配置(#configuration)

要启用容器扫描,请添加 Container-Scanning.gitlab-ci.yml 模板.gitlab-ci.yml 文件:

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

包含的模板:

  • 在 CI/CD 流水线中创建一个 container_scanning 作业。
  • 从项目的容器镜像库中提取构建的 Docker 镜像(请参阅 要求)并扫描它,查找可能的漏洞。

系统将结果保存为 Container Scanning 报告产物,您可以稍后下载和分析。下载时,您始终会收到最新的产物。如果启用依赖扫描,还会创建依赖扫描报告产物。

以下是构建 Docker 镜像、将其推送到容器镜像库并扫描镜像的示例 .gitlab-ci.yml

include:
  - template: Jobs/Build.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:$CI_COMMIT_SHA

设置 CS_DEFAULT_BRANCH_IMAGE 可以避免在镜像名称跨分支不同时重复发现漏洞。 CS_DEFAULT_BRANCH_IMAGE 的值表示扫描镜像的名称,它出现在默认分支上。 有关如何实现此重复数据删除的更多详细信息,请参阅设置默认分支镜像

自定义容器扫描设置

在某些情况下,您可能想要自定义极狐GitLab 扫描容器的方式。例如,您可能希望启用更详细的输出、访问需要身份验证的 Docker 镜像库等等。要更改此类设置,请使用 .gitlab-ci.yml 中的 variables 参数来设置 CI/CD 变量。 您在 .gitlab-ci.yml 中设置的变量会覆盖 Container-Scanning.gitlab-ci.yml

此示例包含容器扫描模板并为分析器启用详细输出:

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

variables:
    SECURE_LOG_LEVEL: 'debug'

扫描远端镜像库中的镜像

要扫描位于项目以外的镜像库中的镜像,请使用以下 .gitlab-ci.yml

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    DOCKER_IMAGE: example.com/user/image:tag

向远端镜像库进行身份验证

扫描私有镜像库中的镜像需要身份验证。在 DOCKER_USER 变量中提供用户名,在 DOCKER_PASSWORD 配置变量中提供密码。

例如,要从 AWS Elastic Container Registry 扫描镜像:

container_scanning:
  before_script:
    - ruby -r open-uri -e "IO.copy_stream(URI.open('https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip'), 'awscliv2.zip')"
    - unzip awscliv2.zip
    - ./aws/install
    - aws --version
    - export AWS_ECR_PASSWORD=$(aws ecr get-login-password --region region)

include:
  - template: Security/Container-Scanning.gitlab-ci.yml
    DOCKER_IMAGE: <aws_account_id>.dkr.ecr.<region>.amazonaws.com/<image>:<tag>
    DOCKER_USER: AWS
    DOCKER_PASSWORD: "$AWS_ECR_PASSWORD"

依赖列表

引入于 14.6 版本。

CS_DISABLE_DEPENDENCY_LIST CI/CD 变量控制扫描是否创建依赖列表报告。变量的默认设置 false 允许扫描创建报告。要禁用报告,请将变量设置为 true

例如:

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    CS_DISABLE_DEPENDENCY_LIST: "true"

报告特定语言的 findings

引入于 14.6 版本。

CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN CI/CD 变量控制扫描是否报告与编程语言相关的 findings。支持的语言取决于使用的扫描器

默认情况下,报告仅包括由操作系统 (OS) 包管理器管理的包(例如,yumaptapktdnf)。要报告非操作系统包中的安全 findings,请将 CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN 设置为 "false"

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN: "false"

当您启用此功能时,如果为您的项目启用了依赖扫描,您可能会在漏洞报告中看到重复的 findings。发生这种情况是因为系统无法自动对两个不同分析器报告的 findings 进行重复数据删除。

可用的 CI/CD 变量(#available-cicd-variables)

您可以使用以下 CI/CD 变量配置分析器:

CI/CD 变量 默认值 描述 扫描器
ADDITIONAL_CA_CERT_BUNDLE "" 您想要信任的 CA 证书捆绑包。查看使用自定义 SSL CA 证书颁发机构获取详情。 All
CI_APPLICATION_REPOSITORY $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG 要扫描的镜像的 Docker 仓库 URL。 All
CI_APPLICATION_TAG $CI_COMMIT_SHA 要扫描的镜像的 Docker 仓库标记。 All
CS_ANALYZER_IMAGE registry.gitlab.cn/security-products/container-scanning:4 分析器的 Docker 镜像。 All
CS_DEFAULT_BRANCH_IMAGE "" 默认分支上的 DOCKER_IMAGE 的名称。查看设置默认分支镜像获取详情。引入于 14.5 版本。 All
CS_DISABLE_DEPENDENCY_LIST "false" 禁用扫描镜像中安装的软件包的依赖扫描。引入于 14.6 版本。 All
CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN "true" 禁用扫描安装在扫描镜像中的特定语言包。引入于 14.6 版本。 All
CS_DOCKER_INSECURE "false" 允许在不验证证书的情况下使用 HTTPS 访问安全的 Docker 镜像库。 All
CS_IMAGE_SUFFIX "" 后缀添加到 CS_ANALYZER_IMAGE。如果设置为 -fips,则使用 FIPS-enabled 镜像进行扫描。有关详细信息,请参阅启用 FIPS 的镜像。引入于 14.10 版本。 All
CS_IGNORE_UNFIXED "false" 忽略未修复的漏洞。 All
CS_REGISTRY_INSECURE "false" 允许访问不安全的镜像库(仅限 HTTP)。仅应在本地测试镜像时设置为 true。适用于所有扫描器,但镜像库必须侦听端口 80/tcp 才能使 Trivy 工作。 All
CS_SEVERITY_THRESHOLD UNKNOWN 严重级别阈值。扫描器输出严重级别高于或等于此阈值的漏洞。支持的级别为未知、低、中、高和严重。 Trivy
DOCKER_IMAGE $CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG 要扫描的 Docker 镜像。如果设置,此变量将覆盖 $CI_APPLICATION_REPOSITORY$CI_APPLICATION_TAG 变量。 All
DOCKER_PASSWORD $CI_REGISTRY_PASSWORD 用于访问需要身份验证的 Docker 镜像库的密码。仅当 $DOCKER_IMAGE 位于 $CI_REGISTRY 时才设置默认值。 All
DOCKER_USER $CI_REGISTRY_USER 用于访问需要身份验证的 Docker 镜像库的用户名。 仅当 $DOCKER_IMAGE 位于 $CI_REGISTRY 时才设置默认值。 All
DOCKERFILE_PATH Dockerfile 用于生成修复的 Dockerfile 的路径。默认情况下,扫描器会在项目的根目录中查找名为 Dockerfile 的文件。仅当 Dockerfile 位于非标准位置(例如子目录)时,才应配置此变量。查看漏洞解决方案获取详情 All
SECURE_LOG_LEVEL info 设置最低日志记录级别。输出此日志级别或更高级别的消息。从最高到最低严重性,日志记录级别是:fatalerrorwarninfodebug。引入于 13.1 版本。 All

支持的发行版

支持取决于扫描器:

启用 FIPS 的镜像

引入于 14.1 版本。

提供 FIPS-enabled Red Hat UBI 版本的容器扫描镜像。因此,您可以使用基于 UBI 的镜像替换标准镜像。要配置镜像,将 CS_IMAGE_SUFFIX 设置为 -fips 或修改 CS_ANALYZER_IMAGE 变量为标准标签加上 -fips 扩展名。

扫描器名称 CS_ANALYZER_IMAGE
默认 (Trivy) registry.gitlab.cn/security-products/container-scanning:4-fips
Grype registry.gitlab.cn/security-products/container-scanning/grype:4-fips
Trivy registry.gitlab.cn/security-products/container-scanning/trivy:4-fips
note在 15.0 版本之前,还可以使用 -ubi 镜像扩展名。15.0 及更高版本仅支持 -fips

从 14.10 版本开始,当在极狐GitLab 实例中启用 FIPS 模式时,-fips 会自动添加到 CS_ANALYZER_IMAGE

启用自动合并请求上的容器扫描

引入于 14.9 版本。

要在项目中启用容器扫描,请从“安全配置”页面创建合并请求:

  1. 在要启用容器扫描的项目中,转到 安全与合规 > 配置
  2. 容器扫描 行中,选择 使用合并请求进行配置

将自动创建一个合并请求,其中包含启用容器扫描所需的更改。 要完成配置,请查看并合并此合并请求。

配置工具在无现有 .gitlab-ci.yml 文件或最小配置文件的情况下效果最佳。如果您有一个复杂的 GitLab 配置文件,可能解析不成功,可能会报错。

覆盖容器扫描模板

如果您想覆盖作业定义(例如,更改诸如 variables 之类的属性),则必须在模板包含后,声明并覆盖作业,然后指定任何其它键。

此示例将 GIT_STRATEGY 设置为 fetch

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    GIT_STRATEGY: fetch

更换扫描器

容器扫描分析器可以使用不同的扫描器,具体取决于 CS_ANALYZER_IMAGE 配置变量的值。

可以使用以下选项:

扫描器名称 CS_ANALYZER_IMAGE
默认 (Trivy) registry.gitlab.cn/security-products/container-scanning:4
Grype registry.gitlab.cn/security-products/container-scanning/grype:4
Trivy registry.gitlab.cn/security-products/container-scanning/trivy:4

如果您从 13.x 版本迁移到 14.x 版本并自定义了 container_scanning 作业或其 CI 变量,则可能需要在 CI 文件中执行以下迁移步骤:

  1. 删除这些变量:

    • CS_MAJOR_VERSION
    • CS_PROJECT
    • SECURE_ANALYZERS_PREFIX
  2. 查看 CS_ANALYZER_IMAGE 变量,它不再依赖于上面的变量,它的新默认值是registry.gitlab.cn/security-products/container-scanning:4。如果您有离线环境,查看在离线环境中运行容器扫描

  3. 如果存在,请删除 .cs_commoncontainer_scanning_new 配置部分。

  4. 如果 container_scanning 部分存在,基于新版本的 Container-Scanning.gitlab-ci.yml 模板从头开始创建一个会更安全。一旦完成,不应该有任何仅适用于 Klar 或 Clair 的变量。有关受支持变量的完整列表,查看可用变量

  5. 对所选扫描器进行任何必要的自定义。我们建议您尽量减少此类自定义,因为它们可能需要在未来的极狐GitLab 主要版本中进行更改。

  6. 触发包含 container_scanning 作业的流水线的新运行。检查作业输出并确保日志消息未提及 Clair。

note在 14.0 版本之前,在 container_scanning 范围内定义的任何变量都不会被考虑用于除 Clair 之外的扫描仪。在 14.0 及更高版本中,所有变量都可以定义为全局变量或在 container_scanning 下。

设置默认分支镜像

引入于 14.5 版本。

默认情况下,容器扫描假定镜像命名约定将任何特定于分支的标识符存储在镜像标签中,而不是镜像名称中。当默认分支和非默认分支之间的镜像名称不同时,先前检测到的漏洞会在合并请求中显示为新检测到的漏洞。

当同一镜像在默认分支和非默认分支上具有不同的名称时,您可以使用 CS_DEFAULT_BRANCH_IMAGE 变量来指示该镜像在默认分支上的名称。 然后系统在非默认分支上运行扫描时可以正确确定是否存在漏洞。

例如,假设以下情况:

  • 非默认分支使用命名约定 $CI_REGISTRY_IMAGE/$CI_COMMIT_BRANCH:$CI_COMMIT_SHA 发布镜像。
  • 默认分支使用命名约定 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA 发布镜像。

在此示例中,您可以使用以下 CI/CD 配置来确保不重复漏洞:

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  before_script:
    - export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$CI_COMMIT_BRANCH:$CI_COMMIT_SHA"
    - |
      if [ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]; then
        export DOCKER_IMAGE="$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
      fi

对于给定的 DOCKER_IMAGECS_DEFAULT_BRANCH_IMAGE 应该保持不变。如果它发生变化,则会创建一组重复的漏洞,必须手动消除这些漏洞。

使用 Auto DevOps 时,CS_DEFAULT_BRANCH_IMAGE 会自动设置为 $CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:$CI_APPLICATION_TAG

使用自定义 SSL CA 证书颁发机构

您可以使用 ADDITIONAL_CA_CERT_BUNDLE CI/CD 变量来配置自定义 SSL CA 证书颁发机构,用于在从使用 HTTPS 的镜像库获取 Docker 镜像时验证对等方。ADDITIONAL_CA_CERT_BUNDLE 值应包含 X.509 PEM 公钥证书的文本表示形式。例如,要在 .gitlab-ci.yml 文件中配置此值,请使用以下命令:

container_scanning:
  variables:
    ADDITIONAL_CA_CERT_BUNDLE: |
        -----BEGIN CERTIFICATE-----
        MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
        ...
        jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
        -----END CERTIFICATE-----

ADDITIONAL_CA_CERT_BUNDLE 值也可以配置为 UI 中的自定义变量,或者配置为 file, 需要证书的路径,或者作为变量(需要证书的文本表示)。

漏洞许可名单

要将特定漏洞列入白名单,请执行以下步骤:

  1. 按照 覆盖容器扫描模板 中的说明,在 .gitlab-ci.yml 文件中设置 GIT_STRATEGY: fetch
  2. 在名为 vulnerability-allowlist.yml 的 YAML 文件中定义列入许可名单的漏洞。必须使用 vulnerability-allowlist.yml 数据格式 中描述的格式。
  3. vulnerability-allowlist.yml 文件添加到项目 Git 仓库的根文件夹中。

vulnerability-allowlist.yml 数据格式

vulnerability-allowlist.yml 文件是一个 YAML 文件,它指定了允许存在的漏洞的 CVE ID 列表,主要原因包括 误报不适用

如果在 vulnerability-allowlist.yml 文件中找到匹配条目,则会发生以下情况:

  • 当分析器生成 gl-container-scanning-report.json 文件时,漏洞不包括在内。
  • 流水线的安全选项卡不显示漏洞。它不包含在 JSON 文件中,即安全选项卡内容的真实来源。

示例 vulnerability-allowlist.yml 文件:

generalallowlist:
  CVE-2019-8696:
  CVE-2014-8166: cups
  CVE-2017-18248:
images:
  registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:
    CVE-2018-4180:
  your.private.registry:5000/centos:
    CVE-2015-1419: libxml2
    CVE-2015-1447:

此示例从 gl-container-scanning-report.json 中排除以下漏洞:

  1. 所有具有 CVE ID 的漏洞:CVE-2019-8696CVE-2014-8166CVE-2017-18248
  2. registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256 容器镜像中发现的所有 CVE ID 为 CVE-2018-4180 的漏洞。
  3. your.private.registry:5000/centos 容器中发现的所有 CVE ID 为 CVE-2015-1419CVE-2015-1447 的漏洞。
文件格式
  • generalallowlist 块允许您在全局范围内指定 CVE ID。具有匹配 CVE ID 的所有漏洞都将从扫描报告中排除。

  • images 块允许您为每个容器镜像独立指定 CVE ID。给定镜像中具有匹配 CVE ID 的所有漏洞都将从扫描报告中排除。镜像名称是从用于指定要扫描的 Docker 镜像的环境变量之一检索的,例如 $CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAGDOCKER_IMAGE。此块中提供的镜像必须匹配此值并且不得包含标签值。例如,如果您使用 DOCKER_IMAGE=alpine:3.7 指定要扫描的镜像,则可以在 images 块中使用 alpine,但不能使用 alpine:3.7

    您可以通过多种方式指定容器镜像:

    • 仅镜像名称(例如 centos)。
    • 带有主机名的完整镜像名称(例如 your.private.registry:5000/centos)。
    • 带有镜像库主机名和 sha256 标签的完整镜像名称(例如 registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256)。
noteCVE ID 后面的字符串(上例中的cupslibxml2)是可选的注释格式,对漏洞的处理没有影响。您可以包含注释来描述漏洞。
容器扫描作业日志格式

您可以通过查看容器扫描分析器在 container_scanning 作业详细信息中生成的日志来验证扫描结果和 vulnerability-allowlist.yml 文件的正确性。

该日志包含以表格形式列出的已发现漏洞列表,例如:

+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
|   STATUS   |      CVE SEVERITY       |      PACKAGE NAME      |    PACKAGE VERSION    |                            CVE DESCRIPTION                             |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
|  Approved  |   High CVE-2019-3462    |          apt           |         1.4.8         | Incorrect sanitation of the 302 redirect field in HTTP transport metho |
|            |                         |                        |                       | d of apt versions 1.4.8 and earlier can lead to content injection by a |
|            |                         |                        |                       |  MITM attacker, potentially leading to remote code execution on the ta |
|            |                         |                        |                       |                             rget machine.                              |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
| Unapproved |  Medium CVE-2020-27350  |          apt           |         1.4.8         | APT had several integer overflows and underflows while parsing .deb pa |
|            |                         |                        |                       | ckages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extr |
|            |                         |                        |                       | acttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This |
|            |                         |                        |                       |  issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1 |
|            |                         |                        |                       | .6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions  |
|            |                         |                        |                       | prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0 |
|            |                         |                        |                       |                                  .1;                                   |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
| Unapproved |  Medium CVE-2020-3810   |          apt           |         1.4.8         | Missing input validation in the ar/tar implementations of APT before v |
|            |                         |                        |                       | ersion 2.1.2 could result in denial of service when processing special |
|            |                         |                        |                       |                         ly crafted deb files.                          |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+

将对应的 CVE ID 添加到 vulnerability-allowlist.yml 文件时,日志中的漏洞会被标记为 Approved

在离线环境中运行容器扫描

对于通过 Internet 对外部资源进行有限、受限或间歇性访问的环境中的自我管理 GitLab 实例,需要进行一些调整才能使容器扫描作业成功运行。

离线容器扫描的要求

要在离线环境中使用容器扫描,您需要:

  • 带有 dockerkubernetes executor 的 GitLab Runner。
  • 使用容器扫描镜像的副本配置本地 Docker 容器镜像库。您可以在它们各自的镜像库中找到这些镜像:
GitLab Analyzer Container Registry
Container-Scanning Container-Scanning container registry

请注意,GitLab Runner 的默认 pull policyalways,这意味着即使本地副本可用,runner 也会尝试从 GitLab 容器镜像库中提取 Docker 镜像。如果您更喜欢仅使用本地可用的 Docker 镜像,则可以在离线环境中将 GitLab Runner pull_policy 设置为 if-not-present。但是,如果不在离线环境中,我们建议将拉取策略设置保持为 always,因为这样可以在 CI/CD 流水线中使用更新的扫描程序。

支持自定义证书颁发机构

以下版本中引入了对自定义证书颁发机构的支持:

扫描器 版本
Trivy 4.0.0
Grype 4.3.0

在 Docker 镜像库中提供极狐GitLab 容器扫描分析器镜像

对于容器扫描,将以下镜像从 registry.gitlab.cn 导入您的本地 Docker 容器镜像库

registry.gitlab.cn/security-products/container-scanning:4
registry.gitlab.cn/security-products/container-scanning/grype:4
registry.gitlab.cn/security-products/container-scanning/trivy:4

将 Docker 镜像导入本地离线 Docker 镜像库的过程取决于您的网络安全策略。请咨询您的 IT 人员,找到一个接受和批准的流程,您可以通过该流程导入或临时访问外部资源。这些扫描程序定期更新,您可以自己进行不定期更新。

有关将 Docker 镜像作为文件保存和传输的详细信息,请参阅 Docker 关于 docker save 的文档,docker loaddocker exportdocker import

设置容器扫描 CI/CD 变量来使用本地容器扫描分析器

  1. 覆盖容器扫描模板 在您的 .gitlab-ci.yml 文件中引用托管在本地 Docker 容器镜像库上的 Docker 镜像:

    include:
      - template: Security/Container-Scanning.gitlab-ci.yml
    
    container_scanning:
      image: $CI_REGISTRY/namespace/gitlab-container-scanning
    
  2. 如果您的本地 Docker 容器镜像库通过 HTTPS 安全运行,但您使用的是自签名证书,则必须在 .gitlab-ci.yml 的上述 container_scanning 部分中设置 CS_DOCKER_INSECURE: "true"

使用流水线自动进行容器扫描漏洞数据库更新

我们建议您设置一个计划流水线,按照预设的计划获取最新的漏洞数据库。 使用流水线自动执行此操作意味着您不必每次都手动执行。您可以使用以下 .gitlab-ci.yml 示例作为模板。

variables:
  SOURCE_IMAGE: registry.gitlab.cn/security-products/container-scanning:4
  TARGET_IMAGE: $CI_REGISTRY/namespace/gitlab-container-scanning

image: docker:stable

update-scanner-image:
  services:
    - docker:dind
  script:
    - docker pull $SOURCE_IMAGE
    - docker tag $SOURCE_IMAGE $TARGET_IMAGE
    - echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY --username $CI_REGISTRY_USER --password-stdin
    - docker push $TARGET_IMAGE

上述模板适用于在本地安装上运行的 GitLab Docker 镜像库。但是,如果您使用的是非 GitLab Docker 镜像库,则必须更改 $CI_REGISTRY 值和 docker login 凭据来匹配本地镜像库的详细信息。

扫描外部私有镜像库中的镜像

要扫描外部私有镜像库中的镜像,您必须配置访问凭据,以便容器扫描分析器可以在尝试访问要扫描的镜像之前对其进行身份验证。

如果您使用 GitLab Container RegistryDOCKER_USERDOCKER_PASSWORD configuration variables 会自动设置,您可以跳过这个配置。

此示例显示了在私有 Google Container Registry 中扫描镜像所需的配置:

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    DOCKER_USER: _json_key
    DOCKER_PASSWORD: "$GCP_CREDENTIALS"
    DOCKER_IMAGE: "gcr.io/path-to-you-registry/image:tag"

在提交此配置之前,为包含 JSON 的 GCP_CREDENTIALS 添加 CI/CD 变量 密钥,如 Google Cloud Platform Container Registry 文档中所述。 同时:

  • 变量的值可能不符合 隐藏变量 选项的隐藏要求,因此该值可能会暴露在作业日志中。
  • 如果您选择 保护变量 选项,扫描可能不会在不受保护的功能分支中运行。
  • 如果未选择这些选项,请考虑创建具有只读权限的凭据并定期轮换它们。

运行独立的容器扫描工具

可以针对 Docker 容器运行 GitLab 容器扫描工具,而无需在 CI 作业的上下文中运行它。要直接扫描镜像,请执行以下步骤:

  1. 运行 Docker DesktopDocker Machine

  2. 运行分析器的 Docker 镜像,在 CI_APPLICATION_REPOSITORYCI_APPLICATION_TAG 变量中传递要分析的镜像和标签:

    docker run \
      --interactive --rm \
      --volume "$PWD":/tmp/app \
      -e CI_PROJECT_DIR=/tmp/app \
      -e CI_APPLICATION_REPOSITORY=registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256 \
      -e CI_APPLICATION_TAG=bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e \
      registry.gitlab.cn/security-products/container-scanning
    

结果存储在 gl-container-scanning-report.json 中。

报告 JSON 格式

容器扫描工具会发出一个 JSON 报告文件。

示例如下:

{
  "version": "14.0.0",
  "vulnerabilities": [
    {
      "id": "df52bc8ce9a2ae56bbcb0c4ecda62123fbd6f69b",
      "category": "container_scanning",
      "message": "CVE-2019-3462 in apt-1.4.8",
      "description": "Incorrect sanitation of the 302 redirect field in HTTP transport method of apt versions 1.4.8 and earlier can lead to content injection by a MITM attacker, potentially leading to remote code execution on the target machine.",
      "severity": "High",
      "confidence": "Unknown",
      "solution": "Upgrade apt from 1.4.8 to 1.4.9",
      "scanner": {
        "id": "trivy",
        "name": "trivy"
      },
      "location": {
        "dependency": {
          "package": {
            "name": "apt"
          },
          "version": "1.4.8"
        },
        "operating_system": "debian:9.4",
        "image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e",
        "default_branch_image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0:latest"
      },
      "identifiers": [
        {
          "type": "cve",
          "name": "CVE-2019-3462",
          "value": "CVE-2019-3462",
          "url": "http://www.securityfocus.com/bid/106690"
        }
      ],
      "links": [
        {
          "url": "http://www.securityfocus.com/bid/106690"
        },
        {
          "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-3462"
        },
        {
          "url": "https://lists.apache.org/thread.html/8338a0f605bdbb3a6098bb76f666a95fc2b2f53f37fa1ecc89f1146f@%3Cdevnull.infra.apache.org%3E"
        },
        {
          "url": "https://lists.debian.org/debian-lts-announce/2019/01/msg00013.html"
        },
        {
          "url": "https://lists.debian.org/debian-lts-announce/2019/01/msg00014.html"
        },
        {
          "url": "https://security.netapp.com/advisory/ntap-20190125-0002/"
        },
        {
          "url": "https://usn.ubuntu.com/3863-1/"
        },
        {
          "url": "https://usn.ubuntu.com/3863-2/"
        },
        {
          "url": "https://usn.ubuntu.com/usn/usn-3863-1"
        },
        {
          "url": "https://usn.ubuntu.com/usn/usn-3863-2"
        },
        {
          "url": "https://www.debian.org/security/2019/dsa-4371"
        }
      ]
    }
  ],
  "remediations": []
  "scan": {
    "scanner": {
      "id": "trivy",
      "name": "Trivy",
      "url": "https://github.com/aquasecurity/trivy/",
      "vendor": {
        "name": "GitLab"
      },
      "version": "0.16.0"
    },
    "type": "container_scanning",
    "start_time": "2021-04-14T19:45:58",
    "end_time": "2021-04-14T19:46:18",
    "status": "success"
  }
}

安全仪表盘

安全仪表盘向您展示了您的群组、项目和流水线中的所有安全漏洞的概览。

与漏洞交互

发现漏洞后,您可以解决它

漏洞解决方案(自动修复)

一些漏洞可以通过应用极狐GitLab 自动生成的解决方案来修复。

要启用补救支持,扫描工具必须有权访问由 DOCKERFILE_PATH CI/CD 变量指定的 Dockerfile

为确保扫描工具可以访问此文件,有必要按照本文档覆盖容器扫描模板部分中描述的说明在您的 .gitlab-ci.yml 文件中设置 GIT_STRATEGY: fetch

故障排查

docker: Error response from daemon: failed to copy xattrs

当 runner 使用 docker 执行器并使用 NFS 时(例如,/var/lib/docker 在 NFS 挂载上),容器扫描可能会失败,并出现如下错误:

docker: Error response from daemon: failed to copy xattrs: failed to set xattr "security.selinux" on /path/to/file: operation not supported.

这是 Docker 中的一个错误的结果,现在 已修复。为防止出现错误,请确保 runner 使用的 Docker 版本为 18.09.03 或更高版本。