
Trivy 接入 GitLab CI 完整指南容器扫描、Code Quality 报告与模板源码解析【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivy导读本文面向希望在 GitLab CI/CD 流水线中落地安全扫描的开发者系统讲解如何将 Trivy 集成进.gitlab-ci.yml既包括 GitLab 15.0 起的官方原生集成一行 include 即可也包括可完全自控的三种自定义作业方案docker:dind 构建后扫描、Trivy 容器镜像扫描、Code Climate 格式报告并深入仓库源码剖析 contrib/gitlab.tpl 与 contrib/gitlab-codequality.tpl 两个报告模板的字段映射与实现原理。读完本文你将能够独立编写出可用的 GitLab CI 扫描作业理解--template、--exit-code、TRIVY_*环境变量等关键参数的真实行为并学会把漏洞、配置错误、密钥扫描结果直接呈现在 GitLab 的 Security / Code Quality 界面中。一、GitLab 原生集成从 GitLab 15.0 开始的开箱即用自 GitLab 15.0 起GitLab 官方为免费版用户也提供了与 Trivy 的原生集成。你不需要写任何扫描逻辑只需要在.gitlab-ci.yml中引入官方 CI 模板include: - template: Security/Container-Scanning.gitlab-ci.yml引入后GitLab 会在流水线中自动创建容器扫描作业扫描结果直接呈现在Security Compliance Vulnerability Report页面容器扫描报告功能在 GitLab Ultimate 上完整可用。如果你是GitLab 14.x Ultimate客户也可以使用上述相同的配置方式。原生集成适合“开箱即用”的场景但如果你需要更精细地控制扫描镜像、退出码策略、报告格式例如生成 Code Climate 报告GitLab 官方模板无法覆盖全部需求。下文提供的三种示例配置来自本文关联文档 docs/tutorials/integrations/gitlab-ci.md可以在任意 GitLab 版本中使用且完全可定制。二、方案一docker:dind 构建镜像并下载 Trivy 二进制扫描该方案在 CI 中先通过 Docker-in-Dockerdind构建应用镜像再动态下载对应版本的 Trivy 二进制进行扫描最终产出 GitLab 容器扫描报告并支持按严重级别设置失败策略。stages: - test trivy: stage: test image: docker:stable services: - name: docker:dind entrypoint: [env, -u, DOCKER_HOST] command: [dockerd-entrypoint.sh] variables: DOCKER_HOST: tcp://docker:2375/ DOCKER_DRIVER: overlay2 # See https://github.com/docker-library/docker/pull/166 DOCKER_TLS_CERTDIR: IMAGE: trivy-ci-test:$CI_COMMIT_SHA TRIVY_NO_PROGRESS: true TRIVY_CACHE_DIR: .trivycache/ before_script: - export TRIVY_VERSION$(wget -qO - https://api.github.com/repos/aquasecurity/trivy/releases/latest | grep tag_name: | sed -E s/.*v([^]).*/\1/) - echo $TRIVY_VERSION - wget --no-verbose https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz -O - | tar -zxvf - allow_failure: true script: # Build image - docker build -t $IMAGE . # Build report - ./trivy image --exit-code 0 --format template --template /contrib/gitlab.tpl -o gl-container-scanning-report.json $IMAGE # Print report - ./trivy image --exit-code 0 --severity HIGH $IMAGE # Fail on severe vulnerabilities - ./trivy image --exit-code 1 --severity CRITICAL $IMAGE cache: paths: - .trivycache/ # Enables https://docs.gitlab.com/ee/user/application_security/container_scanning/ (Container Scanning report is available on GitLab Ultimate) artifacts: reports: container_scanning: gl-container-scanning-report.json逐段拆解1. dind 服务配置services中启动了docker:dind并显式重置其entrypoint与command同时设置DOCKER_HOST: tcp://docker:2375/让dockerCLI 客户端连接 dind 守护进程DOCKER_TLS_CERTDIR: 关闭 TLS 目录避免 dind 因证书路径问题无法通信参见 docker-library/docker#166DOCKER_DRIVER: overlay2使用 overlay2 存储驱动。2. 下载指定版本的 Trivybefore_script中通过 GitHub API 获取最新 release 版本号再以wget ... | tar -zxvf -直接解压出trivy二进制到工作目录。这样无需依赖镜像内预装版本扫描器版本始终与上游最新发布保持同步。若你的流水线要求版本固定可复现可以把TRIVY_VERSION硬编码为具体版本号。3. 三段式扫描策略# 1) 生成 GitLab 容器扫描报告任何漏洞都不影响退出码 ./trivy image --exit-code 0 --format template --template /contrib/gitlab.tpl -o gl-container-scanning-report.json $IMAGE # 2) 终端打印 HIGH 及以上漏洞仍不失败便于排查 ./trivy image --exit-code 0 --severity HIGH $IMAGE # 3) 发现 CRITICAL 漏洞即失败 ./trivy image --exit-code 1 --severity CRITICAL $IMAGE这里充分利用了 Trivy 的--exit-code语义指定“当发现安全问题时进程退出码”的值。--exit-code 0表示发现问题也不退出非零用于生成报告--exit-code 1表示一旦发现对应严重级别的问题就以退出码 1 结束从而让 CI 作业失败。结合--severity HIGH/--severity CRITICAL可精确控制“什么级别才算阻断发布”。两个参数的定义见 pkg/flag/report_flags.go--exit-code对应ExitCodeFlag--severity对应SeverityFlag默认值为全部五个级别。4. 缓存与产物TRIVY_CACHE_DIR: .trivycache/配合cache: paths: [.trivycache/]把漏洞数据库与层缓存放进 GitLab 缓存目录跨流水线复用避免每次全量下载 DBTRIVY_NO_PROGRESS: true关闭进度条输出让 CI 日志干净可读尤其便于time统计耗时artifacts.reports.container_scanning声明报告文件路径GitLab 会将其解析进 Container Scanning 报告Ultimate 版本显示allow_failure: true即使 CRITICAL 阻断作业失败流水线整体仍继续适合“扫描结果只告警不阻断”的灰度策略。上述before_script中涉及的-O - | tar -zxvf -为“下载即解压”管道写法实际使用时请将 wget 的--no-verbose参数保留以便在 CI 日志中能看到下载进度与错误信息。三、方案二使用 Trivy 官方容器镜像扫描已推送镜像如果应用镜像已经构建并推送到了 GitLab Container Registry可以用下面的作业直接拉取 Trivy 官方镜像来扫描无需克隆项目仓库也无需安装 Docker。container_scanning: image: name: docker.io/aquasec/trivy:latest entrypoint: [] variables: # No need to clone the repo, we exclusively work on artifacts. See # https://docs.gitlab.com/ee/ci/runners/configure_runners.html#git-strategy GIT_STRATEGY: none TRIVY_USERNAME: $CI_REGISTRY_USER TRIVY_PASSWORD: $CI_REGISTRY_PASSWORD TRIVY_AUTH_URL: $CI_REGISTRY TRIVY_NO_PROGRESS: true TRIVY_CACHE_DIR: .trivycache/ FULL_IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG script: - trivy --version # update vulnerabilities db - time trivy image --download-db-only # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so artifacts: can take it from there - time trivy image --exit-code 0 --format template --template /contrib/gitlab.tpl --output $CI_PROJECT_DIR/gl-container-scanning-report.json $FULL_IMAGE_NAME # Prints full report - time trivy image --exit-code 0 $FULL_IMAGE_NAME # Fail on critical vulnerabilities - time trivy image --exit-code 1 --severity CRITICAL $FULL_IMAGE_NAME cache: paths: - .trivycache/ # Enables https://docs.gitlab.com/ee/user/application_security/container_scanning/ (Container Scanning report is available on GitLab EE Ultimate or GitLab.com Gold) artifacts: when: always reports: container_scanning: gl-container-scanning-report.json tags: - docker-runner关键点说明entrypoint: []必须清空Trivy 镜像默认入口是trivy命令若不清空script中的每行trivy ...将无法正常执行GitLab 会把它作为参数传给入口命令。GIT_STRATEGY: none作业只针对已存在的镜像产物工作无需拉取代码可显著缩短作业时长。私有仓库认证非公开 GitLab 项目的镜像需要认证才能拉取。这里通过TRIVY_USERNAME/TRIVY_PASSWORD/TRIVY_AUTH_URL三个环境变量完成认证TRIVY_USERNAME: $CI_REGISTRY_USER、TRIVY_PASSWORD: $CI_REGISTRY_PASSWORD是 GitLab 预置的 CI 凭据变量分别对应当前用户/令牌与注册表密码TRIVY_AUTH_URL: $CI_REGISTRY指定注册表地址。这三个环境变量对应 Trivy 内部注册表认证配置在 pkg/flag/registry_flags.go 中可以确认TRIVY_PASSWORD与TRIVY_USERNAME正是密码与用户名标志的环境变量映射密码处注释特别提示“出于安全原因应使用 TRIVY_PASSWORD”。--download-db-only先单独下载漏洞数据库用time统计耗时把网络开销与扫描阶段分开便于观察 DB 下载瓶颈。--output $CI_PROJECT_DIR/gl-container-scanning-report.json将报告写到默认工作目录这样artifacts.reports.container_scanning才能从该路径取走文件。artifacts.when: always保证即使后续 CRITICAL 扫描失败报告产物依然上传。tags: [docker-runner]如果你的 Runner 池包含多种类型通过 tag 指定具备拉取/执行容器能力的 runner。四、方案三Code Climate 替代模板镜像 文件系统 合并报告GitLab 的容器扫描模板在部分版本/工作流下无法满足需求例如你想同时扫描文件系统、并把结果展示在Code Quality页面。仓库在 contrib/gitlab-codequality.tpl 提供了 Code Climate 格式模板作为补充方案。stages: - test trivy: stage: test image: docker:stable services: - name: docker:dind entrypoint: [env, -u, DOCKER_HOST] command: [dockerd-entrypoint.sh] variables: DOCKER_HOST: tcp://docker:2375/ DOCKER_DRIVER: overlay2 # See https://github.com/docker-library/docker/pull/166 DOCKER_TLS_CERTDIR: IMAGE: trivy-ci-test:$CI_COMMIT_SHA TRIVY_NO_PROGRESS: true TRIVY_CACHE_DIR: .trivycache/ before_script: - export TRIVY_VERSION$(wget -qO - https://api.github.com/repos/aquasecurity/trivy/releases/latest | grep tag_name: | sed -E s/.*v([^]).*/\1/) - echo $TRIVY_VERSION - wget --no-verbose https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz -O - | tar -zxvf - allow_failure: true script: # Build image - docker build -t $IMAGE . # Image report - ./trivy image --exit-code 0 --format template --template /contrib/gitlab-codequality.tpl -o gl-codeclimate-image.json $IMAGE # Filesystem report - ./trivy filesystem --scanners misconfig,vuln --exit-code 0 --format template --template /contrib/gitlab-codequality.tpl -o gl-codeclimate-fs.json . # Combine report - apk update apk add jq - jq -s add gl-codeclimate-image.json gl-codeclimate-fs.json gl-codeclimate.json cache: paths: - .trivycache/ # Enables https://docs.gitlab.com/ee/user/application_security/container_scanning/ (Container Scanning report is available on GitLab EE Ultimate or GitLab.com Gold) artifacts: paths: - gl-codeclimate.json reports: codequality: gl-codeclimate.json与容器扫描方案的差异模板与报告类型变化把--template /contrib/gitlab.tpl换成--template /contrib/gitlab-codequality.tpl产物类型从container_scanning换成codequality。GitLab 会据此把结果渲染到Code Quality界面而非 Vulnerability Report。文件系统扫描新增trivy filesystem --scanners misconfig,vuln ... .对仓库工作目录同时启用 misconfig配置错误与 vuln漏洞两类扫描器输出到gl-codeclimate-fs.json。合并两份报告GitLab 目前只支持单个codequality 报告官方有 feature request 支持多报告。因此在得到镜像报告gl-codeclimate-image.json与文件系统报告gl-codeclimate-fs.json后用jq -s add合并jq -s add gl-codeclimate-image.json gl-codeclimate-fs.json gl-codeclimate.json若你的流水线中已有其他 Code Quality 报告例如prev-codeclimate.json同样可以用该命令合并jq -s add prev-codeclimate.json trivy-codeclimate.json gl-codeclimate.json注意按产物命名规则可能需要重命名文件避免与既有 artifact 名称冲突。效果预览合并后的报告可在 GitLab 流水线的 Code Quality 界面查看文件系统的漏洞与配置错误会链接到具体文件而镜像漏洞则显示其来源镜像、操作系统/运行时/库。如上图所示报告中混合呈现了镜像漏洞如src/requirements.txt中的 CVE-2020-14343、nginx 镜像 debian 11.2 中的 curl CVE与配置错误如 Kubernetes 特权容器 KSV017、Dockerfile 使用 root 用户 DS002、Terraform 网络策略 AVD-KUBE-0001。五、源码级解析GitLab 报告模板是如何工作的前文所有示例都依赖--template /contrib/gitlab.tpl语法。理解模板引擎的实现有助于你按需改造报告字段。1.--template与前缀的加载机制在 pkg/report/template.go 中NewTemplateWriter会先检查模板参数是否以开头若存在该前缀则把后续字符串当作文件路径读取文件内容作为模板否则直接把参数当作模板字符串解析。这就是为什么示例中统一写作--template /contrib/gitlab.tpl。模板解析基于 Go 标准库text/template并注入了 Masterminds/sprig 的全部函数以及 Trivy 自定义函数appVersion返回 Trivy 自身版本号写入报告的scan.analyzer.versionescapeXML/escapeString对输出做 XML / HTML 转义endWithPeriod确保描述以句号结尾sourceID将字符串转换为数据源 ID 类型见 pkg/report/template.go。--format template与--template的校验逻辑在 pkg/flag/report_flags.go两者必须成对出现且指定的文件必须以.tpl结尾否则会给出警告或被忽略。2.gitlab.tpl容器扫描 JSON 报告结构contrib/gitlab.tpl 输出 GitLab Container Scanning 报告schema 版本 15.0.7scan.type container_scanning。其核心映射包括扫描器元信息analyzer/scanner均标记为trivy、厂商 Aqua Security、版本取{{ appVersion }}镜像与 OS 推断遍历结果从Class os-pkgs的目标字符串中正则提取镜像名与括号内的操作系统{{ $os $target | splitList ( | last | trimSuffix ) }}写入每条漏洞的location.operating_system与location.image严重级别映射Trivy 的UNKNOWN/LOW/MEDIUM/HIGH/CRITICAL被映射为 GitLab 风格的Unknown/Low/Medium/High/Critical修复建议若存在FixedVersion生成Upgrade 包名 to 版本形式的solution否则输出No solution provided标识与链接identifiers中写入 CVE 类型标识type: cve及PrimaryURLlinks数组仅保留以http(s)://或ftp://开头的引用 URL结果容器vulnerabilities遍历所有目标的Vulnerabilitiesremediations留空。模板中两处 TODO 注释也值得留意见 contrib/gitlab.tploperating_system与 CVEtype字段尚无直接数据映射模板采用了上述推断/固定写法改造报告时需要注意这一限制。3.gitlab-codequality.tplCode Climate 报告结构contrib/gitlab-codequality.tpl 遵循 Code Climate 规范输出 JSON 数组每个问题是一个type: issue对象描述漏洞条目拼接VulnerabilityID - PkgName - InstalledVersion - Title配置错误拼接Misconfig - ID - Title密钥拼接Secret - RuleID - Title指纹用sha1sum对关键字段做哈希生成fingerprint保证同一问题在多次流水线间可稳定去重严重级别映射LOW → info、MEDIUM → minor、HIGH → major、CRITICAL → critical未知级别默认info定位漏洞的location.path指向目标$target配置错误与密钥则进一步携带CauseMetadata.StartLine/StartLine行号让 GitLab 能把问题精确定位到源码文件的具体行覆盖三类结果模板同时处理Vulnerabilities、Misconfigurations、Secrets三组数据这正是方案三中文件系统扫描可以一次输出 misconfig 与 vuln 的原因。4. 报告写入与测试佐证模板执行完成后由TemplateWriter.Write将渲染结果写入输出流见 pkg/report/template.go其数据源是report.Results。仓库还提供了多份 Golden 文件用于验证模板输出与既有报告格式的兼容性例如 integration/testdata/alpine-310.gitlab.golden 与 integration/testdata/alpine-310.gitlab-codequality.golden可作为你改造模板后的回归基准。六、接入 GitLab CI 的实践建议综合以上三种方案给出如下选型与实践建议优先用原生集成GitLab 15.0 直接include: - template: Security/Container-Scanning.gitlab-ci.yml维护成本最低需要深度定制时再切换到自建作业。按“镜像是否已推送”选方案流水线内先docker build的用方案一dind 二进制镜像已推送注册表的用方案二Trivy 官方镜像 GIT_STRATEGY: none记得清空entrypoint并配置TRIVY_USERNAME/TRIVY_PASSWORD/TRIVY_AUTH_URL。报告格式决定展示位置需要 Vulnerability Report 用/contrib/gitlab.tplartifacts.reports.container_scanning需要 Code Quality 页面用/contrib/gitlab-codequality.tplartifacts.reports.codequality。退出码与严重级别是门禁核心--exit-code 0负责“只报告不阻断”--exit-code 1配合--severity CRITICAL负责“阻断发布”allow_failure决定阻断时流水线是否整体失败。缓存与日志始终设置TRIVY_CACHE_DIR并纳入cache.paths开启TRIVY_NO_PROGRESS保持日志整洁对耗时步骤如--download-db-only使用time前缀便于观测性能。改造模板有依据所有模板基于text/template sprig 函数渲染可在 pkg/report/template.go 确认可用函数修改后建议对照 integration/testdata 下的.gitlab.golden/.gitlab-codequality.golden文件校验输出格式。相关资源GitLab 集成教程原文docs/tutorials/integrations/gitlab-ci.md容器扫描报告模板contrib/gitlab.tplCode Climate 报告模板contrib/gitlab-codequality.tpl模板加载与渲染实现pkg/report/template.go报告相关 CLI 标志定义pkg/flag/report_flags.go注册表认证标志与环境变量pkg/flag/registry_flags.go报告格式回归基准integration/testdata/alpine-310.gitlab.golden 与 integration/testdata/alpine-310.gitlab-codequality.golden供 CI 试运行的示例仓库可在 GitLab 上搜索aquasecurity/trivy-ci-test文内示例即出自该仓库的流水线实践【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考