2020 年 SolarWinds 攻击的感染链:攻击者篡改了 SolarWinds Orion 的软件构建管道→签名的更新包被推送给客户→18000+ 组织在”信任 SolarWinds”的基础上被植入后门。这个攻击的逻辑不是”攻击者攻破了一个合法用户的账户”——而是”攻击者攻破了代码从源码到产物的生成过程”。
前置阅读:mTLS 大规模部署的工程现实。
一、SLSA:软件供应链安全的等级体系
SLSA(Supply-chain Levels for Software Artifacts,读作”salsa”)是 Google 在 2021 年发布、2023 年发布 v1.0 的框架。它为软件供应链定义了四个安全等级。
| 等级 | 核心要求 | 防御什么 |
|---|---|---|
| SLSA 1(Build L1) | 构建过程有记录(provenance) | 事后分析”这个二进制是怎么生成的” |
| SLSA 2(Build L2) | 构建使用托管服务 + 签名 provenance | 篡改构建记录 |
| SLSA 3(Build L3) | 构建环境有安全控制 + 非伪造的来源 | 构建平台被攻破 |
| SLSA 4(Build L4) | 密封构建(hermetic)+ 可复现构建 + 双人审核 | 构建过程中的任何单点被攻破 |
SLSA 的核心理念是零信任的延伸:不信任构建环境,不信任构建工具,不信任构建者。 每一个从源码到产物的步骤都需要独立的身份和加密证明。
SLSA v1.0 只定义了 Build Track(构建追溯)。另外两个轨道——Source Track(源码完整性)和 Dependencies Track(依赖管理)——仍在草案阶段。
二、Sigstore:无密钥的签名和验证
Sigstore 解决了软件供应链中的一个实际问题:开发者不想管理私钥。
传统模型要求每个开发者持有用于签名 artifact 的私钥——但私钥的管理(生成、存储、轮换、吊销)对非安全专业的开发者太高了。Sigstore 把这个模型变成了由 OIDC 身份驱动的短暂签名。
2.1 三种核心服务
| 服务 | 职责 | 类比 |
|---|---|---|
| Fulcio | 短期证书 CA——验证 OIDC 身份后签发 10 分钟有效期的代码签名证书 | Let’s Encrypt for Code Signing |
| Rekor | 不可篡改的透明度日志——所有签名记录公开存储 | Certificate Transparency for Software |
| Cosign | 客户端工具——签名、验证容器镜像和其他 artifact | gpg --sign 的替代品 |
2.2 签名流程
开发者执行: cosign sign ghcr.io/myorg/myapp:v1.0
Cosign 内部:
1. 重定向开发者到 OIDC Provider(如 GitHub / Google)
2. 开发者登录后,OIDC Provider 返回 ID Token(含 email + OIDC claims)
3. Cosign 将 ID Token 发送给 Fulcio
4. Fulcio 验证 ID Token → 签发 10 分钟有效期的 X.509 证书
(证书中包含开发者的 email / OIDC subject 作为身份标识)
5. Cosign 用该证书签名容器镜像
6. Cosign 将签名记录上传到 Rekor(透明度日志)
开发者不需要持有长期私钥——每次签名自动从 OIDC 获取短有效期证书。这是零信任”短有效期凭据”原则在代码签名中的应用。
2.3 验证流程
# 验证镜像的签名
cosign verify ghcr.io/myorg/myapp:v1.0 \
--certificate-identity "developer@example.com" \
--certificate-oidc-issuer "https://accounts.google.com"
# 检查和验证: 签名证书链 → Fulcio Root CA → OIDC Identity → Rekor 日志验证方不需要信任开发者的长期公钥——只需要信任 Fulcio 的根证书和 OIDC Provider 的 identity。这极大简化了验证方的密钥管理——从一个 O(n) 的问题(为每个开发者管理公钥)变成了 O(1)(只信任 Fulcio 根证书)。
三、SPIFFE/SPIRE 在 CI/CD 管道中的应用
Sigstore 解决了”谁签的名”的问题,但”谁构建的”这个问题仍然没有被完整回答。当你的 CI/CD 系统(GitHub Actions、Jenkins、Tekton)在构建镜像时,构建步骤本身的身份需要一个独立于开发者身份的凭据。
3.1 CI/CD 管道的 SPIFFE 化
每个构建步骤作为一个工作负载(Workload),通过 SPIRE 获得短有效期 SVID:
GitHub Actions Pipeline:
Step 1: checkout → SPIRE 签发 SVID: spiffe://build.example.com/pipeline/acme/web/checkout
Step 2: test → SPIRE 签发 SVID: spiffe://build.example.com/pipeline/acme/web/test
Step 3: build → SPIRE 签发 SVID: spiffe://build.example.com/pipeline/acme/web/build
Step 4: push → SPIRE 签发 SVID: spiffe://build.example.com/pipeline/acme/web/push
每个步骤有独立的身份——步骤之间不能互相冒充。如果攻击者攻破了
test 步骤,它的证书只能验证 test
的身份,不能伪装成 push 去推送镜像。
3.2 in-toto 证明链
in-toto 是 CNCF 的一个项目,为软件供应链的每一步生成不可伪造的证明(attestation),链接成一个完整的证明链:
[Source Commit] → attestation → [Build Step 1] → attestation → [Build Step 2]
↑ ↑
signed by signed by
developer's CI/CD step's
Sigstore cert SPIFFE SVID
in-toto 的布局(layout)文件指定了每一步应该由谁(哪个公钥/身份)执行:
{
"steps": [
{
"name": "clone",
"expected_command": "git clone https://github.com/myorg/myapp",
"pubkeys": ["sha256:abc123..."]
},
{
"name": "build",
"expected_command": "make build",
"pubkeys": ["sha256:def456..."]
}
]
}验证方通过重放整个布局来确认:每一步都遵循了规定的命令,每一步的产出都指向下一步的输入,每一步都是由正确的身份执行的。
四、SBOM 在授权决策中的应用
SBOM(Software Bill of Materials,软件物料清单)列出了软件中包含的所有组件和依赖。SLSA 的要求之一是在构建时生成签名的 SBOM。
零信任的延伸想法:SBOM 用于部署时的授权决策。
部署 Pod "payment-service v2.3":
→ 策略引擎检查 SBOM: 依赖项中是否包含 CVE-2024-xxxxx 漏洞的组件?
→ 如果包含: 策略引擎阻止部署(即使该 Pod 的 SPIFFE ID 有权限)
→ 如果不包含: 继续正常的授权检查
这不是零信任的标准做法,但它是零信任精神的自然延伸——不信任组件本身,只信任经过验证的组件依赖链。 当前 Kubernetes 环境中,Kyverno 和 OPA Gatekeeper 的策略可以读取容器镜像的 SBOM(以 attestation 形式附加到镜像上)并在准入控制中做出允许/拒绝决定。
五、总结
软件供应链的零信任化有三层:
- 签名层(Sigstore):不信任”谁上传的”,用 OIDC 驱动的短有效期证书签名每一个 artifact
- 步骤层(SPIFFE + in-toto):不信任”整个构建管道”,管道中的每个步骤有独立身份和限制
- 验证层(SLSA + SBOM):不信任”已知的 artifact”——每个 artifact 必须在不可篡改的日志(Rekor)中有记录,且其 SBOM 在部署时被验证
下一篇:CISA 零信任成熟度模型。
参考资料
- SLSA. SLSA v1.0 Specification. https://slsa.dev/spec/v1.0/
- Sigstore. Architecture Overview. https://docs.sigstore.dev/architecture/
- in-toto. Specification. https://github.com/in-toto/docs/blob/master/in-toto-spec.md
- Google. (2021). SLSA: A Practical Guide to Supply Chain Integrity. https://security.googleblog.com/2021/06/introducing-slsa-end-to-end-framework.html
- NIST SP 800-218. Secure Software Development Framework (SSDF).
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【身份与访问控制工程】服务身份:mTLS、SPIFFE/SPIRE 与 Workload Identity
前 9 篇讨论的都是'人'的身份——用户怎么登录、怎么验证。但微服务世界中,80% 的 API 调用是服务之间的。服务身份(Workload Identity)是整个 IAM 体系的另一半:mTLS 解决'传输层你是谁',SPIFFE/SPIRE 解决'在平台层你是谁且怎么证明',JWT Profile for OAuth 解决'我怎么拿到一个服务身份的 Token'。本文从这三条线拆解服务身份的工程实现。
【零信任安全架构】mTLS 大规模部署的工程现实:联邦、故障排查与根 CA 轮换
mTLS 是零信任服务间通信的基石,但从'单集群内启用 mTLS'到'全公司多集群、混合云的 mTLS',中间隔着 SPIRE 联邦、跨信任域证书验证、mTLS 握手并发瓶颈、连接池协议兼容性和故障排查等工程问题。本文不重复 SPIFFE/SPIRE 基础,而是聚焦大规模部署中才暴露的问题。
零信任安全架构深度系列
零信任是 IAM 的自然延伸——当身份变成新边界,VPN 的'拨入即信任'模型必须被'永不信任、始终验证'取代。本系列从 NIST SP 800-207 规范、Google BeyondCorp 六篇论文、SPIFFE/SPIRE 联邦到微分段、持续验证、ZTNA 和零信任迁移的工程策略,系统拆解零信任的每一种组件和每一步实施。
【身份与访问控制工程】SCIM 与账号生命周期:开通、变更、离职自动化
SSO 只解决认证,SCIM 解决账号的生命周期管理。但 SCIM 2.0 的实现远不是调几个 REST API 那么简单:User/Group schema 的映射、Delta vs Full sync 的同步策略、Patch 操作语义,每个环节都有坑。本文从账号生命周期的四个关键事件出发,拆解 SCIM 2.0 的核心协议、同步模式、Schema 扩展,以及与企业 IdP(Azure AD、Okta)对接的实际工程经验。