6.5. 供应链安全:SBOM、签名与准入

供应链安全要回答三个问题:这个镜像从哪来、里面有什么、能不能证明它没被篡改。答案分别是 provenance(来源)、SBOM(物料清单) 和 签名(Sigstore/Cosign),最后由准入控制器验证。

层级:

L4 · 实战

难度:

进阶

预计:

45 分钟

前置:

CI/CD、镜像仓库、Kubernetes 准入

6.5.1. 一条可验证的链路

源码 commit → CI 构建 → SBOM → 扫描 → 签名 → 推送 → 准入校验 → 部署

每一步都要留下可追溯的证据:

证据

工具

作用

commit

Git

代码来源

SBOM

Syft/Trivy

依赖与版本

漏洞报告

Trivy/Grype

已知风险

签名

Cosign/Sigstore

完整性与发布者

证明

SLSA provenance

构建过程可信

准入

Kyverno/Gatekeeper

拒绝不合规镜像

6.5.2. SBOM 与扫描

syft ghcr.io/example/demoapp:v1.0 -o spdx-json > sbom.spdx.json
trivy image --format cyclonedx --output sbom.cdx.json ghcr.io/example/demoapp:v1.0
trivy image --severity HIGH,CRITICAL --exit-code 1 ghcr.io/example/demoapp:v1.0

SBOM 要归档到制品仓库或 OCI Artifact,并与 digest 绑定。扫描策略要明确:哪些漏洞阻断、哪些可豁免、豁免多久复审。

6.5.3. 签名与验证

cosign generate-key-pair
cosign sign --key cosign.key ghcr.io/example/demoapp@sha256:<digest>
cosign verify --key cosign.pub ghcr.io/example/demoapp@sha256:<digest>

生产建议用 keyless(OIDC + Fulcio + Rekor)或 KMS 托管密钥;私钥不要放在 CI 变量里。签名对象是 digest,不是 tag;tag 可变,digest 不可变。

6.5.4. 准入校验

kyverno-verify-image.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  rules:
    - name: verify-cosign
      match:
        any:
          - resources:
              kinds: [Pod]
      verifyImages:
        - imageReferences:
            - "ghcr.io/example/*"
          attestors:
            - entries:
                - keys:
                    publicKeys: |-
                      -----BEGIN PUBLIC KEY-----
                      ...
                      -----END PUBLIC KEY-----

准入控制器要能访问 Rekor/Fulcio 或公钥;离线环境要提前同步。策略先 Audit,确认镜像覆盖率后再 Enforce,避免把存量应用全部拒绝。

6.5.5. SLSA 与 provenance

SLSA 等级描述构建过程的防篡改能力:

  • L1:构建脚本有文档,产出 provenance。

  • L2:托管构建服务,签名 provenance。

  • L3:隔离、不可变构建环境,强 provenance。

多数团队先做到 L2:CI 生成 provenance,Cosign 签名,准入验证。不要为了等级而等级;先保证「能追溯、能验证、能阻断」。

6.5.6. 镜像仓库与保留

  • 使用 Harbor/云仓库,开启不可变 tag、漏洞扫描、复制策略。

  • 只保留可部署的 digest 与 SBOM,定期清理旧 tag。

  • 生产部署用 digest;回滚用旧 digest,不重新构建。

  • 仓库凭证用 robot account/短期 token,最小权限。

6.5.7. 实验:从构建到准入

  1. 构建镜像,生成 SBOM 并扫描。

  2. 用 Cosign 签名 digest。

  3. 在 kind 集群安装 Kyverno,配置验签策略。

  4. 部署已签名镜像 → 通过;部署未签名镜像 → 拒绝。

  5. 查看拒绝事件与策略报告。

6.5.8. 验证清单

  • 每个生产镜像有 digest、SBOM、扫描报告、签名。

  • CI 对 HIGH/CRITICAL 漏洞有明确阻断/豁免策略。

  • 准入控制器验证签名,未签名镜像被拒绝。

  • 私钥不在 Git/CI 明文变量中。

  • 镜像仓库开启不可变 tag 与漏洞扫描。

  • 回滚使用旧 digest,不重新构建。

6.5.9. 排错表

现象

原因

处理

验签失败

签的是 tag/digest 不一致

用 digest 重新签/部署

准入拒绝所有 Pod

策略范围过宽

先 Audit,限定镜像前缀/命名空间

Kyverno 无法访问 Rekor

网络/证书

配置代理或离线公钥

扫描结果差异大

数据库未更新/扫描器不同

固定 DB 更新时间与工具版本

镜像被覆盖

tag 可变

开启 immutable tag,使用 digest

6.5.10. 进阶挑战

  1. 用 Cosign keyless 签名并在 Kyverno 验签。

  2. 生成 SLSA provenance 并归档到 OCI Artifact。

  3. 给漏洞豁免加过期时间与审批。

  4. 把「未签名镜像」加入 CI 门禁。

6.5.11. 小结

  • 供应链安全的核心是「来源可追溯、内容可验证、部署可阻断」。

  • SBOM、签名、provenance 要与 digest 绑定。

  • 准入策略先 Audit 后 Enforce,避免误伤存量。

  • 没有签名的镜像不应该进入生产。

6.5.12. 延伸阅读