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 都上传上去,它帮你做几件事:

  1. 集中存储:所有 SBOM 统一管理,按项目、版本、时间检索。
  2. 自动漏洞匹配:它会从 NVD、GitHub Advisory 等源拉取漏洞数据,自动匹配你的组件。
  3. 策略引擎:可以设置规则,比如「禁止使用 GPL 协议的组件」或「CVSS 评分超过 7 的组件必须修复」。
  4. 通知机制:发现新漏洞时,自动发邮件、Slack 或 Webhook 通知。
  5. 审计追踪:谁在什么时候修复了哪个漏洞,都有记录。

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 存储与管理架构图 SBOM 存储与管理架构 SBOM 生成 本地存储 Git 版本控制 Dependency-Track 文件归档 版本追溯 漏洞分析 安全闭环:漏洞发现 → 修复 → 验证 建议:Git 存原始 SBOM + Dependency-Track 做分析,形成双保险

从这张图可以看得很清楚:SBOM 生成后,三条路径都能走。但真正能支撑安全闭环的,是 Git 的版本追溯能力和 Dependency-Track 的自动化分析能力。本地存储,嗯,只适合临时过渡。