4. SBOM生成实战(一):对Java项目(Maven/Gradle)生成SBOM、对Python项目(pip/poetry)生成SBOM。
好,咱们直接进入正题。前面聊了那么多SBOM的理论和标准,今天终于要动手了。我个人习惯,学任何东西,先跑起来再说。你想想看,光看文档不敲命令,永远记不住。
这一章,我们聚焦两个最主流的生态:Java 和 Python。说白了,就是搞定 Maven/Gradle 和 pip/poetry 的项目。我会带着你,一行命令一行命令地生成真正的 SPDX 和 CycloneDX 格式的 SBOM。
核心目标:今天结束后,你能对自己手头的 Java 或 Python 项目,用一条命令生成一份可用的 SBOM 文件。
4.1 为什么先从这两个生态开始?
我在项目中遇到过不少团队,一上来就想搞全量扫描,结果被各种奇奇怪怪的依赖报错搞崩溃。其实,Java 和 Python 的包管理工具最成熟,社区对 SBOM 的支持也最完善。先把这两个啃下来,后面再搞 Go、JavaScript 甚至容器镜像,就顺理成章了。
嗯,这里要注意:生成 SBOM 不是目的,目的是拿到一份准确的、可被工具解析的依赖清单。所以,我们不仅要会跑命令,还要知道生成的 SBOM 里到底写了啥。
4.2 Java 项目:Maven 生成 SBOM
Maven 是 Java 生态的老大哥。我建议你直接用 CycloneDX Maven 插件,它稳定、更新快,而且生成的 CycloneDX 格式是目前最通用的。
4.2.1 安装与配置
在项目的 pom.xml 里,加入插件配置。别怕,就几行代码。
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>2.7.9</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>makeAggregateBom</goal>
</goals>
</execution>
</executions>
</plugin>
这里我用了 makeAggregateBom 而不是 makeBom。为什么?前者会聚合所有模块的依赖,包括父子模块。如果你是多模块项目,一定要用这个。我曾经见过有人用错了,结果只生成了子模块的 SBOM,漏掉了公共依赖,排查了半天。
4.2.2 执行生成
配置好后,直接运行:
mvn package
或者,如果你只想生成 SBOM 而不想打包:
mvn cyclonedx:makeAggregateBom
命令跑完后,在 target/ 目录下会生成 bom.json 和 bom.xml 两个文件。默认是 CycloneDX 格式。
小技巧:如果你需要 SPDX 格式,可以用 mvn cyclonedx:makeAggregateBom -Dcyclonedx.outputFormat=spdx。不过我个人更推荐 CycloneDX,它对组件元数据的支持更丰富。
4.2.3 验证 SBOM 内容
打开 bom.json,你会看到类似这样的结构:
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"version": 1,
"metadata": {
"component": {
"name": "my-java-app",
"version": "1.0.0"
}
},
"components": [
{
"type": "library",
"name": "log4j-core",
"version": "2.17.1",
"purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1"
}
]
}
注意看 purl 字段,这是包统一资源标识符,它是 SBOM 的灵魂。有了它,安全工具才能精准定位到具体的组件版本。
4.3 Java 项目:Gradle 生成 SBOM
Gradle 用户也别急。我建议用 CycloneDX Gradle 插件,用法和 Maven 版本几乎一样。
4.3.1 配置
在 build.gradle 里添加:
plugins {
id 'org.cyclonedx.bom' version '1.7.4'
}
4.3.2 执行
./gradlew cyclonedxBom
生成的文件在 build/reports/ 目录下,默认也是 bom.json 和 bom.xml。
避坑指南:我曾经在 Gradle 6.x 版本上遇到过插件不兼容的问题。如果你用的是老版本 Gradle,记得先升级到 7.0 以上,或者指定兼容的插件版本。否则,生成的 SBOM 可能会缺少传递性依赖。
4.4 Python 项目:pip 生成 SBOM
Python 的情况稍微复杂一点。pip 本身不直接生成 SBOM,但我们可以借助 cyclonedx-bom 这个工具。
4.4.1 安装工具
pip install cyclonedx-bom
4.4.2 生成 SBOM
假设你的项目已经生成了 requirements.txt:
cyclonedx-py -i requirements.txt -o bom.json
如果你用的是 pipenv,可以这样:
cyclonedx-py -p -o bom.json
这里 -p 参数表示从 Pipfile.lock 读取依赖。
4.4.3 一个重要的细节
嗯,这里要注意:pip 生成的 SBOM 质量,完全取决于你的 requirements.txt 是否准确。如果你只是随便 pip freeze > requirements.txt,里面可能包含了大量全局环境的包,而不是项目真正需要的。我建议你始终使用虚拟环境,并且只导出项目依赖。
最佳实践:在 CI/CD 中,每次构建前都重新生成 requirements.txt,确保 SBOM 与当前构建的代码一致。
4.5 Python 项目:Poetry 生成 SBOM
Poetry 用户就幸福多了。它原生支持导出 SBOM,而且格式更规范。
4.5.1 生成 CycloneDX 格式
poetry export --format cyclonedx --output bom.json
4.5.2 生成 SPDX 格式
poetry export --format spdx --output bom.spdx.json
你看,一行命令搞定。Poetry 的 poetry.lock 文件本身就包含了精确的版本和依赖树,所以生成的 SBOM 非常可靠。
个人经验:如果你在团队里推广 SBOM,我建议优先推荐 Poetry。它把依赖管理和 SBOM 生成整合得很好,减少了出错的环节。我在一个 50 人的 Python 团队里推过,反馈非常好。
4.6 知识体系:SBOM 生成流程总览
为了让你更直观地理解整个流程,我画了一张图。它展示了从项目源码到最终 SBOM 文件的完整路径。
4.7 工具对比与选择建议
为了帮你快速决策,我整理了一个对比表。你可以根据自己项目的实际情况选择。
| 生态 | 工具 | 推荐格式 | 生成速度 | 依赖完整性 |
|---|---|---|---|---|
| Java (Maven) | cyclonedx-maven-plugin | CycloneDX | 快 | 高(含传递依赖) |
| Java (Gradle) | cyclonedx-gradle-plugin | CycloneDX | 快 | 高(含传递依赖) |
| Python (pip) | cyclonedx-bom | CycloneDX | 中 | 中(依赖 requirements.txt 质量) |
| Python (Poetry) | poetry export | CycloneDX / SPDX | 快 | 高(基于 lock 文件) |
重要提醒:无论你用哪个工具,生成 SBOM 后一定要做一次完整性校验。我见过太多人跑完命令就不管了,结果 SBOM 里缺了关键依赖。最简单的办法:用 jq 或 python 解析生成的 JSON,统计组件数量,再和项目实际依赖数对比一下。
4.8 实战小结
好了,今天的内容就到这里。你学会了:
- 对 Maven 项目,用
cyclonedx-maven-plugin生成 SBOM - 对 Gradle 项目,用
cyclonedx-gradle-plugin生成 SBOM - 对 pip 项目,用
cyclonedx-bom工具生成 SBOM - 对 Poetry 项目,用
poetry export直接导出 SBOM