4、SLSA框架实战:SLSA Level 1-4详解,如何提升你的构建流水线等级

SLSA(Supply-chain Levels for Software Artifacts)这套框架,说白了就是给软件供应链安全定了个“段位”。从 Level 1 到 Level 4,每一级都对应着更严格的构建流水线要求。我刚开始接触时也觉得这玩意儿有点抽象,但真正在项目里跑过一遍之后才发现——它其实就是把“怎么证明你的软件没被人动过手脚”这件事,变成了可执行的标准。

这一章,咱们就一层一层拆开看。每个 Level 到底要做什么?怎么从低往高爬?我会结合自己踩过的坑,给你讲清楚。

SLSA Level 1 → 4 核心能力演进 Level 1 构建过程可追溯 Level 2 防篡改 + 来源验证 Level 3 硬化构建 + 审计 Level 4 全链路可复现 每一级都建立在前一级的基础上,不能跳级。Level 4 是理想态,大部分团队先冲到 Level 2 就算及格。 核心要求 • 构建脚本版本化 • 构建参数可审计 • 产出物有唯一ID • 无额外安全要求 • 适合快速验证 核心要求 • 构建源托管 • 签名验证 • 防篡改元数据 • 构建日志留存 • 依赖来源可查 核心要求 • 隔离构建环境 • 无网络依赖 • 构建参数固定 • 审计日志不可改 • 第三方依赖锁定 核心要求 • 完全可复现构建 • 双人审计 • 全链路签名链 • 构建环境快照 • 零信任部署

4.1 SLSA Level 1:构建过程可追溯

Level 1 是最低门槛。它不要求你有多强的安全防护,只要求一件事:构建过程是可追溯的。说白了,就是别人能查出来你这个软件是怎么构建出来的。

具体要做什么?

  • 构建脚本必须版本化:不能有人在服务器上手动敲命令编译。所有构建步骤都要写在脚本里,并且放在 Git 仓库中。
  • 构建参数可审计:用了哪个分支?哪个 commit?环境变量是什么?这些信息要能记录下来。
  • 产出物有唯一标识:每个构建产物都要有一个唯一的 ID(比如 commit SHA + 构建序号),方便追溯。
我的经验: 我见过不少团队,构建脚本倒是放在 Git 里了,但构建参数全靠 Jenkins 页面上手动填。结果出问题后根本查不到当时填了什么。我的建议是——把所有参数都写进构建脚本,或者至少通过环境变量文件统一管理,别留手动操作的余地。

Level 1 其实不难达到。大部分 CI/CD 工具(GitHub Actions、GitLab CI、Jenkins)默认就能满足。你只需要确保:构建入口是代码,而不是人。

4.2 SLSA Level 2:防篡改 + 来源验证

到了 Level 2,就要开始考虑“防篡改”了。你想想看,就算构建过程可追溯,但如果有人偷偷改了构建脚本或者替换了依赖包,你怎么办?

Level 2 的核心要求:

  • 构建源托管:源代码必须托管在受控的版本管理系统中(比如 GitHub、GitLab 内部实例),不能是个人电脑上的文件夹。
  • 签名验证:构建产物需要签名,并且签名密钥要妥善保管。这样别人拿到你的软件包,可以验证它确实是你构建的。
  • 防篡改元数据:构建的元数据(比如构建时间、构建者、依赖列表)也要签名,防止事后被篡改。
  • 构建日志留存:构建日志要保存下来,并且不能被随意删除或修改。
避坑指南: 我曾经在一个项目里,签名密钥直接放在了 CI 的环境变量里,结果 CI 配置泄露,密钥被人拿去签名了恶意软件。后来我们改用短时效的临时密钥 + 硬件安全模块(HSM)来管理,才算真正安全。记住:密钥管理是 Level 2 最容易翻车的地方。

Level 2 还有一个关键点:依赖来源可查。你不能从随便一个 URL 下载依赖包,必须从受信任的源(比如官方仓库、内部镜像)获取,并且记录下每个依赖的版本和哈希值。

4.3 SLSA Level 3:硬化构建 + 审计

Level 3 开始上强度了。它要求构建环境本身是“硬化”的——说白了,就是不能让构建过程受到外部干扰。

核心要求:

  • 隔离构建环境:每次构建必须在独立的、干净的容器或虚拟机中执行。构建结束后,环境要销毁。不能复用上次构建留下的缓存(除非缓存本身也是受控的)。
  • 无网络依赖:构建过程中,除了必要的依赖下载(且这些依赖必须提前锁定),不允许访问外部网络。这样可以防止构建时被注入恶意代码。
  • 构建参数固定:所有构建参数(包括环境变量、编译选项)必须由构建脚本定义,不能由外部传入。这样可以避免“参数注入”攻击。
  • 审计日志不可篡改:日志不仅要留存,还要保证没人能改。通常的做法是把日志写入不可变存储(比如 AWS S3 的 Object Lock 或区块链式日志系统)。
  • 第三方依赖锁定:所有依赖必须锁定版本和哈希值(比如使用 package-lock.json、go.sum、requirements.txt 的哈希锁定)。
关键点: Level 3 的“无网络依赖”听起来很严格,但实际做起来并不难。你可以在构建前把所有依赖都下载到内部镜像仓库,构建时只允许访问这个镜像。这样既保证了安全,又不影响构建速度。

我个人觉得,Level 3 是性价比最高的一个等级。它堵住了大部分常见的供应链攻击路径,而且实现成本并不算高。很多云原生 CI/CD 工具(比如 Tekton、GitHub Actions 的 self-hosted runner)天然支持隔离构建环境。

4.4 SLSA Level 4:全链路可复现

Level 4 是最高等级,也是终极目标。它要求:给定相同的源代码和构建环境,任何人都能构建出完全相同的产物。

这听起来简单,做起来极难。为什么?

  • 时间戳:很多构建工具会在产物里嵌入时间戳,导致每次构建结果不同。
  • 随机数:有些编译过程会引入随机数(比如加密库的密钥生成),导致产物不一致。
  • 文件顺序:文件系统的遍历顺序不同,可能导致打包后的文件顺序不同,进而影响哈希值。
  • 构建工具版本:编译器、链接器、打包工具的版本差异,都会导致产物不同。

Level 4 的要求:

  • 完全可复现构建:使用相同的源代码、相同的构建环境、相同的依赖版本,必须产生完全相同的二进制产物。
  • 双人审计:任何对构建流程的修改,必须经过至少两个人的审核。不能一个人偷偷改构建脚本。
  • 全链路签名链:从源代码 commit 到构建产物,每一步都要签名,并且签名链要完整可验证。
  • 构建环境快照:构建环境的操作系统、工具链、依赖库的版本都要被快照保存,并且可以随时重建。
  • 零信任部署:部署时不再信任任何外部输入,所有依赖和配置都必须从受控源获取。
我的建议: 除非你的项目对安全性有极端要求(比如金融、医疗、国防),否则不建议一开始就冲 Level 4。我见过一个团队为了追求可复现构建,花了三个月时间调整构建脚本,最后发现业务价值并不大。先冲到 Level 2 或 Level 3,把基础打牢,比什么都强。

4.5 如何评估你当前的流水线等级?

你可以对照下面这个表格,快速评估自己团队的流水线处于哪个 Level:

检查项 Level 1 Level 2 Level 3 Level 4
构建脚本版本化 ✅ ✅ ✅ ✅
构建参数可审计 ✅ ✅ ✅ ✅
构建源托管 ❌ ✅ ✅ ✅
签名验证 ❌ ✅ ✅ ✅
防篡改元数据 ❌ ✅ ✅ ✅
隔离构建环境 ❌ ❌ ✅ ✅
无网络依赖 ❌ ❌ ✅ ✅
第三方依赖锁定 ❌ ❌ ✅ ✅
完全可复现构建 ❌ ❌ ❌ ✅
双人审计 ❌ ❌ ❌ ✅

怎么用这个表?很简单:从 Level 1 开始,逐项检查。如果某一项不满足,你的流水线就还没达到这个 Level。比如,你满足了 Level 1 的所有项,但签名验证没做,那你就还在 Level 1。

4.6 实战:从 Level 1 提升到 Level 2

我拿一个实际项目举例。假设你现在的流水线是这样的:

  • 构建脚本在 Git 里(✅ Level 1)
  • 构建参数写在 Jenkinsfile 里(✅ Level 1)
  • 构建产物有版本号(✅ Level 1)
  • 没有签名(❌ Level 2)
  • 依赖从公共仓库直接下载(❌ Level 2)

要提升到 Level 2,你需要做两件事:

  1. 给构建产物签名:用 GPG 或 Sigstore(推荐)给每个构建产物签名。Sigstore 的好处是不用自己管理密钥,它使用短时效的临时证书。
  2. 锁定依赖源:把所有依赖的下载地址改为内部镜像仓库,并且在构建脚本里记录每个依赖的哈希值。

代码示例(使用 Sigstore 签名):

# 安装 cosign(Sigstore 的 CLI 工具)
# 在构建脚本中执行签名
cosign sign-blob --key /path/to/key.pem output.bin > output.bin.sig

# 验证签名
cosign verify-blob --key /path/to/key.pem --signature output.bin.sig output.bin
注意: 如果你用 Sigstore,记得把公钥也一起发布。不然别人拿到签名文件也没法验证。我见过有人把公钥放在 Git 仓库里,结果仓库是公开的,这其实没问题——公钥本来就是公开的。但千万别把私钥也放进去!

做完这两步,你的流水线就达到 Level 2 了。是不是没那么难?

4.7 小结

SLSA 框架不是让你一步登天的。它给了你一个清晰的路线图:

  • Level 1:先让构建过程可追溯,这是基础。
  • Level 2:加上签名和依赖锁定,防止篡改。
  • Level 3:硬化构建环境,隔离外部干扰。
  • Level 4:追求可复现构建,实现全链路信任。

我个人建议,大部分团队先冲到 Level 2 或 Level 3。Level 4 可以作为长期目标,但不要为了追求完美而耽误了业务交付。记住:安全是持续改进的过程,不是一蹴而就的结果。