第67章|安全 2:软件供应链(SSDF/SLSA)与可信交付链

传统安全关注“代码写得对不对”;供应链安全关注“这条从源码到运行的链条是否可信”。 SSDF(NIST 安全软件开发框架)回答“组织该怎么建流程”;SLSA 回答“制品与构建过程该达到什么可验证等级”。 本章把 provenance(来源证明)、signing(签名)、policy(策略验证)串成一条可信交付链,让“能构建”升级为“能证明、能拒绝、能审计”。

SSDF

Process maturity

  • prepare · protect · produce
  • respond to vulnerabilities
  • organize roles
SLSA

Build assurance

  • levels 1–4 (concept)
  • hermetic builds
  • provenance attestation
Chain

Verify & deploy

  • sigstore / cosign
  • admission policy
  • immutable audit

1. 软件供应链攻击面:一条链上的任意一环都可能被攻破

攻击者不必直接攻生产:可以污染依赖、窃取 CI 凭据、篡改构建缓存、替换镜像仓库中的 tag。 因此“可信交付”必须覆盖:源码依赖构建环境制品部署通道。 你的目标不是零风险,而是可检测、可阻断、可追责

Supply chain surface: every hop is a trust decision Source git · PR · branch Deps npm · maven · go mod CI / Build runner · cache · secrets Registry OCI · tags · mirrors Runtime / Cluster admission must verify provenance + signatures before admit policy engine is the last honest gate
图 1:供应链不是“镜像安全”单点问题,而是整条链上的信任传递。

2. SSDF:把安全开发变成可审计的组织能力

NIST SSDF(SP 800-218)把实践分成若干类:准备(Prepare)、保护软件(Protect the Software)、 生产安全软件(Produce Well-Secured Software)、响应漏洞(Respond to Vulnerabilities)等。 落地时不必一次吃透全部条目,可按成熟度分阶段:先建立依赖清单与漏洞响应 SLA,再引入构建加固与 SBOM。

要点:SSDF 是“流程地图”,不是某个单一工具;它帮助安全与工程对齐语言和优先级。

3. SLSA:用分级描述“构建有多可信”

SLSA(Supply-chain Levels for Software Artifacts)用等级描述构建过程与来源信息的完整性。 高层理解:低等级强调自动化与可追溯元数据;高等级强调隔离的构建环境、不可伪造的来源证明、以及可验证的依赖。 具体级别定义以官方文档为准,本章侧重工程语义:你要能向团队解释“为什么我们卡在 L2、要升到 L3 需要改什么”。

Level (conceptual) What it roughly implies Typical engineering step
L1 build is automated; basic provenance exists CI produces artifact + metadata
L2 signed provenance; service-generated builder identity + attestation
L3+ hermetic / isolated builds; stronger tamper resistance dedicated build platform, pinned toolchains
SLSA maturity staircase (conceptual) L1 automation L2 signed provenance L3+ hermetic / isolated
图 2:升级 SLSA 等级通常意味着改造构建平台与证明链,而不是多跑一个扫描按钮。

4. Provenance(来源证明):回答“这个制品怎么来的”

Provenance 是一份可验证的声明:谁(builder)、在什么环境、从哪些输入(源码 commit、依赖 digest)构建出了哪个产物 digest。 它与镜像签名不同:签名证明“这个 blob 没被改”,provenance 证明“这个 blob 来自一次可描述的构建过程”。 在 Kubernetes 准入或 GitOps 同步前验证 provenance,可以把“信任构建”从口号变成策略。

# Conceptual fields in a SLSA-style provenance attestation (illustrative)
{
  "builder": { "id": "https://ci.example.com/builder/v1" },
  "buildType": "https://example.com/Build@v1",
  "invocation": { "configSource": { "uri": "git+https://github.com/org/repo", "digest": { "sha256": "abc..." } } },
  "materials": [ { "uri": "pkg:npm/lodash@4.17.21", "digest": { "sha256": "def..." } } ],
  "subject": [ { "name": "payments-api", "digest": { "sha256": "012..." } } ]
}

5. Sigstore 生态:cosign、Fulcio、Rekor 的协作

cosign 用于签名与验证 OCI 镜像;Fulcio 提供短期证书(常与 OIDC 身份绑定);Rekor 提供透明度日志(tamper-evident)。 工程上你要定义:哪些身份允许签名、验证时要求哪些 issuer、以及失败时 admission 的 deny reason。

Sign → log → verify → admit cosign sign image digest Fulcio short-lived cert Rekor transparency log Admission policy: identity + digest
图 3:签名与日志让“抵赖”和“静默篡改”更难,但最终守门仍在 admission。
# Illustrative cosign verify (adjust keys / identity policy)
cosign verify \
  --certificate-identity-regexp ".*@company.com" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  registry.example.com/payments-api:v1.4.2

6. 策略验证:把 provenance + 签名变成可执行的 deny

验证逻辑应落在准入控制GitOps 控制器之前:无有效 provenance、digest 不在 allowlist、或 builder identity 不匹配则拒绝。 与第 56 章的 OPA/Gatekeeper 思路一致:策略要返回可读原因,便于排障与例外审批。

底线:只签名不验证,等于把门锁装反——攻击者照样能进。

7. 落地路线:从 SBOM 到 SLSA 的渐进路径

  1. 生成并存储 SBOM(CycloneDX/SPDX),与每个 release 关联。
  2. 为 CI 构建接入来源证明(provenance attestation),并固定 builder 身份。
  3. 对关键镜像启用 cosign 签名 + Rekor 记录。
  4. 在集群准入层验证:镜像 digest、签名身份、可选 SLSA 级别。
  5. 将例外(emergency bypass)纳入审计与限时撤销。

8. 本章清单

  1. 能解释 SSDF 与 SLSA 的分工:流程成熟度 vs 构建与制品可验证性。
  2. 能描述 provenance 与镜像签名的区别及组合使用场景。
  3. 了解 Sigstore 组件(cosign / Fulcio / Rekor)在链中的角色。
  4. 能设计准入策略:验证签名、身份、digest 与可选 SLSA 级别。
  5. 规划渐进落地:SBOM → provenance → signing → policy enforcement。
  6. 预告下一章:FinOps——把 CI/CD 与云成本变成可治理的工程指标。
← 上一章:安全 1 下一章:FinOps →