4. SBOM生成工具:syft、cyclonedx-cli与tern实战

说到生成容器镜像的SBOM,市面上的工具其实不少。但我个人最常用的,就是syft、cyclonedx-cli和tern这三把「瑞士军刀」。它们各有侧重,配合起来几乎能覆盖你遇到的所有场景。

今天我就带大家亲手跑一遍。嗯,咱们不搞虚的,直接上命令行。

4.1 为什么是这三款工具?

先说说我的选择逻辑。你想想看,生成SBOM这件事,核心就三步:扫描镜像 → 提取组件 → 输出标准格式。这三款工具正好各司其职:

工具 核心能力 我最看重的点
syft 快速扫描镜像/文件系统,输出SPDX、CycloneDX等格式 速度极快,几秒就能扫完一个中型镜像
cyclonedx-cli SBOM格式转换、验证、合并、差异对比 格式转换的「瑞士军刀」,没有它搞不定的格式
tern 基于Dockerfile构建过程的逐层分析 能追溯到每一层引入了哪些包,审计时特别好用

一句话总结:syft负责「快」,cyclonedx-cli负责「通」,tern负责「深」。三件套齐了,你就能应对从快速扫描到深度审计的所有需求。

4.2 syft:三秒生成SBOM

syft是Anchore家的开源工具,用Go写的。我第一次用的时候,说实话被它的速度惊到了。一个200MB的nginx镜像,三秒不到就扫完了。

4.2.1 安装syft

安装方式很简单,我习惯用一键脚本:

curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

或者你用Docker也行:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock anchore/syft:latest nginx:latest

4.2.2 实战:生成SPDX格式SBOM

我个人最常用的是SPDX格式,因为它在合规审计中认可度最高。来看一个实际例子:

# 扫描本地nginx镜像,输出SPDX 2.3格式
syft nginx:latest -o spdx-json=nginx.sbom.json

# 如果你想要CycloneDX格式
syft nginx:latest -o cyclonedx-json=nginx.cyclonedx.json

跑完之后,你会得到一个JSON文件。打开看看,里面包含了镜像里每一个软件包的名称、版本、许可证、来源等信息。

我的小技巧:syft支持直接从容器镜像仓库扫描,不需要先把镜像拉到本地。比如 syft docker.io/library/nginx:latest,这在CI/CD流水线里特别有用。

4.2.3 避坑指南

我曾经踩过的坑:syft默认会扫描所有层,包括基础镜像层。如果你只关心自己添加的包,记得加 --scope all-layers 参数。另外,对于多架构镜像,syft默认只扫描当前架构,要扫描所有架构得用 --platform 指定。

4.3 cyclonedx-cli:SBOM格式的「翻译官」

syft生成SBOM很快,但有时候客户或监管机构要求特定格式。比如有的客户只要CycloneDX 1.4,有的非要SPDX 2.2。这时候cyclonedx-cli就派上用场了。

4.3.1 安装cyclonedx-cli

# npm安装
npm install -g @cyclonedx/cyclonedx-cli

# 或者用Docker
docker run --rm -v $(pwd):/data cyclonedx/cyclonedx-cli --help

4.3.2 格式转换实战

假设你手里有一个syft生成的SPDX格式SBOM,客户非要CycloneDX 1.4。别慌,一行命令搞定:

# SPDX → CycloneDX 1.4
cyclonedx-cli convert --input-format spdx-json \
  --input-file nginx.sbom.json \
  --output-format cyclonedx-json \
  --output-file nginx.converted.json

反过来也行:

# CycloneDX → SPDX 2.2
cyclonedx-cli convert --input-format cyclonedx-json \
  --input-file nginx.cyclonedx.json \
  --output-format spdx-json \
  --output-file nginx.back.spdx.json

关键点:cyclonedx-cli不仅能转换格式,还能做SBOM的合并和差异对比。比如你扫描了基础镜像和应用层,可以合并成一个完整的SBOM。这在微服务架构里特别实用。

4.3.3 验证SBOM有效性

生成完SBOM,我建议你立刻验证一下。别等到审计时才发现格式不对:

# 验证CycloneDX格式
cyclonedx-cli validate --input-format cyclonedx-json \
  --input-file nginx.cyclonedx.json

# 验证SPDX格式
cyclonedx-cli validate --input-format spdx-json \
  --input-file nginx.sbom.json

4.4 tern:逐层追溯的「考古学家」

tern跟syft的思路不太一样。它不直接扫描最终镜像,而是模拟Dockerfile的构建过程,逐层分析每一层引入了哪些包。说白了,它能告诉你「这个漏洞到底是从哪一层带进来的」。

4.4.1 安装tern

# pip安装
pip install tern

# 或者用Docker
docker pull tern/tern:latest

4.4.2 实战:逐层分析镜像

来看一个实际例子。假设你要审计一个基于ubuntu:20.04的自定义镜像:

# 逐层分析镜像
tern report --image your-registry/your-image:latest \
  --output-file tern_report.html

tern会生成一个HTML报告,里面每一层都列得清清楚楚:

  • 层ID:Docker镜像的层哈希
  • 引入的包:这一层通过apt、pip、npm等安装的包
  • 许可证信息:每个包的许可证类型
  • 漏洞关联:如果集成了漏洞库,还能显示已知漏洞

我的使用习惯:tern特别适合做合规溯源。比如审计时发现一个GPL许可证的包,你可以直接定位到是基础镜像层还是应用层引入的。如果是基础镜像层,那就得跟OS厂商沟通;如果是应用层,那就是你自己的责任。

4.4.3 避坑指南

我曾经踩过的坑:tern依赖Dockerfile的构建历史。如果你用的镜像不是自己构建的,或者构建时用了 --squash 合并了层,tern的分析结果就不准确了。所以我的建议是:生产环境的镜像,一定要保留完整的构建历史。

4.5 三件套实战流程

好了,工具都介绍完了。咱们来一个完整的实战流程,看看这三把「瑞士军刀」怎么配合:

  1. syft快速扫描:生成初始SBOM(SPDX格式)
  2. cyclonedx-cli格式转换:根据客户要求转成CycloneDX或SPDX特定版本
  3. cyclonedx-cli验证:确保SBOM格式正确
  4. tern深度分析:对关键镜像做逐层追溯,定位问题来源
  5. 合并与归档:用cyclonedx-cli合并多个SBOM,生成最终审计报告

下面这张图,就是整个流程的脉络:

SBOM生成三件套实战流程 容器镜像 syft 快速扫描 tern 逐层分析 cyclonedx-cli 转换 SPDX SBOM CycloneDX SBOM 验证 & 合并 合规审计报告 提示:syft负责「快」,tern负责「深」,cyclonedx-cli负责「通」——三件套缺一不可

4.6 工具对比与选型建议

最后,我根据自己的实战经验,给你一个选型参考:

场景 推荐工具 理由
CI/CD流水线快速扫描 syft 速度快,集成简单,支持多种输出格式
合规审计格式转换 cyclonedx-cli 格式转换、验证、合并一条龙
漏洞溯源与逐层分析 tern 能追溯到每一层,适合深度审计
多镜像批量扫描 syft + cyclonedx-cli syft批量扫,cyclonedx-cli统一格式
监管机构提交SBOM syft + cyclonedx-cli syft生成,cyclonedx-cli验证格式合规

我的最终建议:别纠结选哪个。三个都装上,也就几十MB的事。syft做日常扫描,cyclonedx-cli做格式保障,tern做深度审计。三件套在手,合规审计不愁。