3. SBOM生成工具(一):使用Syft生成容器镜像与文件系统的SBOM
聊到SBOM生成,Syft是我个人最常用的工具之一。它轻量、快速,而且对容器镜像和文件系统都支持得很好。说白了,它就是一把瑞士军刀——你给它一个镜像或目录,它就能把里面的软件包清单给你扒得清清楚楚。
我记得第一次在项目里用Syft,是因为客户要求交付一份完整的依赖清单。当时手动去数镜像里的包,差点没把我累死。后来发现Syft几秒钟就能搞定,嗯,从那以后我就再也没手动数过包了。
3.1 Syft是什么?它能做什么?
Syft是一个用Go语言编写的CLI工具,专门用来从容器镜像和文件系统中生成SBOM。它支持多种输出格式,包括SPDX、CycloneDX和Syft自己的JSON格式。
你想想看,一个容器镜像里可能装了上百个软件包,有操作系统层的(比如glibc、openssl),也有应用层的(比如Python的requests库、Node.js的express框架)。Syft能把这些包全部识别出来,并且告诉你它们的版本号、许可证信息、来源等等。
核心能力一览:
- 从容器镜像(Docker、OCI)中提取软件包清单
- 从本地文件系统或目录中提取软件包清单
- 支持多种包管理器:dpkg、rpm、apk、pip、npm、gem、cargo等
- 输出格式:SPDX 2.2/2.3、CycloneDX 1.4/1.5、JSON、表格式
- 支持与Grype集成进行漏洞扫描
3.2 安装Syft
安装Syft非常简单。我个人习惯用脚本安装,几秒钟就搞定。
# 使用安装脚本(推荐)
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# 或者用Homebrew(macOS/Linux)
brew install syft
# 或者用Docker直接运行
docker run -v /var/run/docker.sock:/var/run/docker.sock anchore/syft:latest
我曾经在CI流水线里踩过一个坑——直接用Docker方式运行Syft,结果发现它访问不到本地的镜像缓存。后来我加上了-v /var/run/docker.sock:/var/run/docker.sock挂载,问题就解决了。嗯,这里要注意,如果你用Docker方式运行,一定要挂载Docker socket,否则Syft只能扫描远程仓库的镜像。
3.3 生成容器镜像的SBOM
这是Syft最常用的场景。你只需要给它一个镜像名称或ID,它就能自动拉取并分析。
# 扫描本地镜像
syft nginx:latest
# 扫描远程仓库的镜像(会自动拉取)
syft docker.io/library/alpine:3.18
# 指定输出格式为SPDX JSON
syft nginx:latest -o spdx-json=sbom.nginx.spdx.json
# 指定输出格式为CycloneDX XML
syft nginx:latest -o cyclonedx-xml=sbom.nginx.cdx.xml
我个人习惯用SPDX格式,因为它在开源社区里接受度更高。不过如果你的客户要求用CycloneDX,Syft也支持得很好。
小技巧:如果你只想看摘要,不加-o参数,Syft默认会输出一个漂亮的表格。我经常用这个来快速检查镜像里装了哪些包。
3.4 生成文件系统的SBOM
除了容器镜像,Syft也能扫描本地文件系统。这个功能在分析构建产物或解压后的文件系统时特别有用。
# 扫描当前目录
syft dir:.
# 扫描指定目录
syft dir:/path/to/your/project
# 扫描解压后的rootfs
syft dir:/path/to/rootfs -o spdx-json=sbom.rootfs.spdx.json
我记得有一次,客户给了一个tar包,里面是嵌入式设备的文件系统。我先把tar解压,然后用syft dir:扫描,几秒钟就生成了完整的SBOM。要是手动去翻,估计得花半天。
3.5 理解Syft的输出
Syft的输出结构很清晰。我们以SPDX格式为例,看看里面都包含了什么。
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "nginx:latest",
"packages": [
{
"name": "libcrypto3",
"versionInfo": "3.0.9-r4",
"SPDXID": "SPDXRef-1a2b3c4d",
"supplier": "Organization: Alpine Linux",
"licenseConcluded": "OpenSSL",
"externalRefs": [
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:a:alpine:libcrypto:3.0.9-r4:*:*:*:*:*:*:*"
}
]
}
]
}
你想想看,每个包都有唯一的SPDXID、版本号、供应商、许可证信息,还有CPE(通用平台枚举)标识。这些信息在后续做漏洞关联分析时特别重要。
注意:Syft生成的CPE不一定100%准确。我曾经遇到过它把某个包的CPE写错了,导致漏洞扫描时漏报。建议在关键项目里,手动核对一下关键包的CPE信息。
3.6 Syft的包检测机制
Syft是怎么知道镜像里装了哪些包的?它主要靠两种方式:
- 包管理器数据库:比如Debian系的
/var/lib/dpkg/status、Red Hat系的/var/lib/rpm、Alpine的/lib/apk/db/installed。Syft会读取这些数据库文件,提取已安装的包信息。 - 文件指纹匹配:对于没有包管理器的场景(比如Go二进制、Java JAR包),Syft会通过文件路径、哈希值、元数据等特征来识别。
我个人建议,如果你要扫描的镜像比较特殊(比如用了多阶段构建,最终阶段没有包管理器),可以先用syft packages命令看看它到底识别出了哪些包。如果发现漏了,可以考虑用--source-version参数指定包管理器的版本。
3.7 实战:从镜像到SBOM的完整流程
下面是一个完整的实战示例,从拉取镜像到生成SBOM,再到简单的分析。
# 1. 拉取一个常用的镜像
docker pull node:18-alpine
# 2. 生成SPDX格式的SBOM
syft node:18-alpine -o spdx-json=sbom.node18.spdx.json
# 3. 查看SBOM中的包数量
cat sbom.node18.spdx.json | jq '.packages | length'
# 4. 查看所有包的名称和版本
cat sbom.node18.spdx.json | jq '.packages[] | {name: .name, version: .versionInfo}'
我记得第一次跑这个流程时,发现node:18-alpine这个镜像里居然有120多个包。大部分是Alpine的基础库,比如musl、libcrypto、zlib等。嗯,这就是为什么容器镜像也要做SBOM——你以为只装了一个Node.js,实际上底层依赖了一堆东西。
3.8 Syft的常用参数速查
| 参数 | 说明 | 示例 |
|---|---|---|
-o |
指定输出格式和文件路径 | -o spdx-json=sbom.json |
--scope |
扫描范围:all-layers(所有层)或 squashed(合并层) |
--scope all-layers |
--exclude |
排除匹配的文件或目录 | --exclude '/usr/share/doc/**' |
--platform |
指定目标平台(如 linux/arm64) |
--platform linux/arm64 |
-v |
显示详细日志,方便调试 | -v |
避坑指南:我曾经在扫描多架构镜像时忘了加--platform参数,结果Syft默认拉取了当前架构的镜像,导致生成的SBOM和实际部署的镜像不一致。如果你在CI里构建多架构镜像,一定要显式指定平台。
3.9 Syft的局限性
没有工具是完美的,Syft也有它的短板:
- 对自编译二进制支持有限:如果你镜像里有自己编译的Go或C++程序,Syft可能识别不出来。它主要依赖包管理器和已知的文件指纹。
- 许可证信息可能不准确:Syft从包管理器里读取的许可证信息,有时候和实际使用的许可证不一致。我建议在合规审计时,还是以官方文档为准。
- 大镜像扫描较慢:如果镜像有几十层,Syft需要逐层分析,速度会慢一些。不过对于大多数场景,几秒钟到一分钟内都能搞定。
你想想看,Syft虽然不能解决所有问题,但作为SBOM生成的起点,它已经足够好了。后续我们可以用Grype做漏洞关联,用Trivy做更全面的扫描——这些我们后面会讲到。
3.10 本章小结
Syft是一个简单但强大的SBOM生成工具。它能从容器镜像和文件系统中提取软件包清单,支持多种输出格式,而且和Grype无缝集成。我个人建议,每个DevSecOps工程师都应该把Syft加入自己的工具箱。
嗯,这里要记住:SBOM不是目的,而是手段。生成SBOM只是第一步,后续的漏洞关联分析、许可证合规检查、供应链风险管理才是真正创造价值的地方。