4、SBOM的存储与管理:本地存储、版本控制(Git)、SBOM仓库(如 Dependency-Track)
SBOM 生成出来只是第一步。怎么存、怎么管、怎么让团队能随时找到它,这才是真正的挑战。我见过不少团队,SBOM 生成完就往某个共享文件夹一丢,结果三个月后谁也找不到哪个版本对应哪个构建。
今天咱们就聊聊 SBOM 的三种存储方式:本地文件、Git 仓库、以及专业的 SBOM 仓库。每种方式都有它的适用场景,也有各自的坑。
4.1 本地存储:最直接,但别太依赖
本地存储,说白了就是把 SBOM 文件直接放在构建产物旁边。比如 Jenkins 构建完成后,把生成的 SPDX 或 CycloneDX JSON 文件存到 build/reports/ 目录下。
适用场景:开发调试、临时验证、单机环境。
我早期做的一个嵌入式项目就是这么干的。每次 CI 跑完,SBOM 文件就跟着固件一起归档。听起来挺合理,对吧?但问题很快就来了——
- 版本混乱:同一个组件迭代了 5 个版本,SBOM 文件散落在不同目录,根本分不清哪个对应哪个。
- 无法追溯:三个月后想查某个历史版本的依赖清单,发现文件早被覆盖了。
- 协作困难:团队成员各自在本地生成 SBOM,没人知道最新的那份在哪。
注意:本地存储只适合临时用途。千万别把它当成正式的 SBOM 管理方案。我曾经吃过这个亏——客户要求提供某个旧版本的 SBOM,我翻遍了所有备份都没找到,最后只能重新生成,但生成的依赖版本已经和当时不一样了。
4.2 版本控制(Git):让 SBOM 和代码一起演进
把 SBOM 纳入 Git 管理,是我个人比较推荐的做法。原因很简单:SBOM 和代码版本是一一对应的,放在同一个仓库里,追溯起来特别方便。
4.2.1 怎么放?
我习惯在项目根目录下建一个 sboms/ 文件夹,按版本或构建时间命名:
project-root/
├── sboms/
│ ├── v1.0.0_sbom.spdx.json
│ ├── v1.0.1_sbom.spdx.json
│ └── v1.1.0_sbom.cyclonedx.json
├── src/
├── Dockerfile
└── .gitignore
4.2.2 CI/CD 自动提交
手动提交 SBOM 太累,也容易忘。我一般在 CI 流水线里加一个步骤:构建完成后自动生成 SBOM,然后提交到 Git。
下面是一个 GitHub Actions 的示例片段:
jobs:
generate-sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate SBOM
run: |
# 使用 CycloneDX 工具生成 SBOM
cyclonedx-bom -o sboms/${{ github.sha }}_sbom.json
- name: Commit SBOM
run: |
git config user.name "CI Bot"
git config user.email "ci@example.com"
git add sboms/
git commit -m "Add SBOM for commit ${{ github.sha }}"
git push
小技巧:如果担心 SBOM 文件太多导致仓库膨胀,可以用 Git LFS 来管理。或者只保留最近 N 个版本的 SBOM,历史版本归档到对象存储里。
4.2.3 Git 管理的优势
| 优势 | 说明 |
|---|---|
| 版本对应 | 每个 SBOM 都对应一个确切的代码版本,不会错乱 |
| 审计追溯 | 通过 git log 就能看到 SBOM 的变更历史 |
| 权限统一 | 复用代码仓库的权限体系,不用额外管理 |
| 自动化友好 | CI/CD 可以自动生成、提交、打标签 |
4.3 SBOM 仓库(Dependency-Track):专业的事交给专业的工具
Git 虽然好用,但 SBOM 多了之后,你会发现它缺少一些关键能力:
- 没法做跨项目的依赖分析
- 没法自动检测漏洞并关联到 SBOM
- 没法生成全局的依赖视图
这时候就需要专业的 SBOM 仓库了。我个人最常用的是 Dependency-Track,它是一个开源的组件分析平台,专门用来管理 SBOM 和跟踪漏洞。
4.3.1 Dependency-Track 能做什么?
说白了,Dependency-Track 就是一个 SBOM 的「中央数据库」。你把所有项目的 SBOM 都上传上去,它帮你做几件事:
- 集中存储:所有 SBOM 统一管理,按项目、版本、时间检索。
- 自动漏洞匹配:它会从 NVD、GitHub Advisory 等源拉取漏洞数据,自动匹配你的组件。
- 策略引擎:可以设置规则,比如「禁止使用 GPL 协议的组件」或「CVSS 评分超过 7 的组件必须修复」。
- 通知机制:发现新漏洞时,自动发邮件、Slack 或 Webhook 通知。
- 审计追踪:谁在什么时候修复了哪个漏洞,都有记录。
4.3.2 部署 Dependency-Track
部署其实很简单。官方提供了 Docker Compose 文件,几分钟就能跑起来:
version: '3.8'
services:
dtrack-apiserver:
image: dependencytrack/apiserver:latest
ports:
- "8080:8080"
environment:
- ALPINE_DATABASE_MODE=external
- ALPINE_DATABASE_URL=jdbc:postgresql://postgres:5432/dtrack
- ALPINE_DATABASE_DRIVER=org.postgresql.Driver
- ALPINE_DATABASE_USERNAME=dtrack
- ALPINE_DATABASE_PASSWORD=dtrack
volumes:
- dtrack-data:/data
dtrack-frontend:
image: dependencytrack/frontend:latest
ports:
- "8081:8080"
environment:
- API_BASE_URL=http://localhost:8080
postgres:
image: postgres:15
environment:
- POSTGRES_DB=dtrack
- POSTGRES_USER=dtrack
- POSTGRES_PASSWORD=dtrack
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
dtrack-data:
postgres-data:
启动后,访问 http://localhost:8081 就能看到 Web 界面。默认管理员账号是 admin / admin,首次登录会要求改密码。
4.3.3 上传 SBOM 到 Dependency-Track
上传方式有两种:手动上传和 API 自动上传。
手动上传:在 Web 界面里选择项目,点击「Upload BOM」,选择文件即可。
API 自动上传:我更喜欢这种方式,可以在 CI 里自动完成:
curl -X "PUT" "http://your-dtrack-server/api/v1/bom" \
-H "X-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"project": "my-project",
"version": "1.0.0",
"bom": "'"$(base64 -w0 sbom.json)"'"
}'
建议:API Key 不要硬编码在代码里。用 CI 的 Secret 变量或者 HashiCorp Vault 来管理。
4.4 三种方式的对比
我把这三种方式放在一起对比一下,方便你根据实际情况选择:
| 维度 | 本地存储 | Git 版本控制 | Dependency-Track |
|---|---|---|---|
| 部署难度 | 无 | 低 | 中 |
| 版本追溯 | 差 | 好 | 好 |
| 跨项目分析 | 不支持 | 不支持 | 支持 |
| 漏洞自动匹配 | 不支持 | 不支持 | 支持 |
| 策略引擎 | 无 | 无 | 有 |
| 通知机制 | 无 | 无 | 有 |
| 适合规模 | 个人/小团队 | 中小团队 | 中大型团队 |
4.5 我的建议
嗯,这里要注意。这三种方式不是互斥的,可以组合使用:
- 小团队、项目少:Git 版本控制就够了。把 SBOM 和代码放在一起,简单直接。
- 中大型团队、多项目:上 Dependency-Track。虽然多了一个要维护的服务,但带来的自动化能力值得。
- 混合方案:Git 存原始 SBOM,Dependency-Track 做集中分析和漏洞管理。这样既有版本追溯,又有自动化能力。
避坑指南:我曾经在一个项目里只用了 Dependency-Track,没把 SBOM 纳入 Git。后来 Dependency-Track 的数据库出了问题,所有历史 SBOM 都丢了。从那以后,我坚持「双保险」——Git 存一份原始文件,Dependency-Track 做分析。两者互补,缺一不可。
4.6 本章知识体系
下面这张图展示了 SBOM 存储与管理的整体架构:
从这张图可以看得很清楚:SBOM 生成后,三条路径都能走。但真正能支撑安全闭环的,是 Git 的版本追溯能力和 Dependency-Track 的自动化分析能力。本地存储,嗯,只适合临时过渡。