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 三件套实战流程
好了,工具都介绍完了。咱们来一个完整的实战流程,看看这三把「瑞士军刀」怎么配合:
- syft快速扫描:生成初始SBOM(SPDX格式)
- cyclonedx-cli格式转换:根据客户要求转成CycloneDX或SPDX特定版本
- cyclonedx-cli验证:确保SBOM格式正确
- tern深度分析:对关键镜像做逐层追溯,定位问题来源
- 合并与归档:用cyclonedx-cli合并多个SBOM,生成最终审计报告
下面这张图,就是整个流程的脉络:
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做深度审计。三件套在手,合规审计不愁。