云原生供应链安全:SBOM、SLSA 与 Sigstore 实战

SolarWinds、Log4Shell、XZ Utils 后门……供应链攻击的破坏力已经有目共睹。2025 年,软件供应链安全从”最佳实践”变成了合规刚需。

威胁模型

供应链攻击的常见入口:

开发者机器 → 源代码仓库 → CI/CD 系统 → 制品仓库 → 生产环境
     ↑              ↑           ↑            ↑
  凭证泄露      恶意 PR      构建注入      镜像篡改

防御思路:每个环节都要验证,不信任任何中间节点。

SBOM:软件物料清单

SBOM 记录软件的所有依赖,是供应链安全的基础。

生成 SBOM

# 使用 Syft 生成容器镜像的 SBOM
syft my-app:latest -o spdx-json > sbom.spdx.json

# 生成 CycloneDX 格式(更多工具支持)
syft my-app:latest -o cyclonedx-json > sbom.cdx.json

# 扫描 SBOM 中的漏洞
grype sbom:sbom.spdx.json

在 GitLab CI 中自动生成

generate-sbom:
  stage: build
  image: anchore/syft:latest
  script:
    - syft $IMAGE_TAG -o spdx-json > sbom.spdx.json
    - syft $IMAGE_TAG -o cyclonedx-json > sbom.cdx.json
  artifacts:
    paths:
      - sbom.spdx.json
      - sbom.cdx.json
    expire_in: 1 year   # SBOM 需要长期保存

Sigstore/Cosign:镜像签名

Cosign 是 Sigstore 项目的核心工具,用于容器镜像的签名和验证。

签名镜像

# 生成密钥对
cosign generate-key-pair

# 签名镜像(推送到 registry 旁边)
cosign sign --key cosign.key my-registry/my-app:v1.0.0

# 验证签名
cosign verify --key cosign.pub my-registry/my-app:v1.0.0

无密钥签名(Keyless,推荐)

利用 OIDC 身份(GitHub Actions、GitLab CI)签名,无需管理私钥:

# GitHub Actions 示例
- name: Sign container image
  uses: sigstore/cosign-installer@v3

- name: Sign the image
  run: |
    cosign sign --yes \
      --rekor-url https://rekor.sigstore.dev \
      ${{ env.IMAGE_TAG }}
  env:
    COSIGN_EXPERIMENTAL: 1

在 K8s 中强制验证签名

使用 Kyverno 策略,拒绝未签名的镜像:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  rules:
  - name: check-image-signature
    match:
      any:
      - resources:
          kinds: [Pod]
          namespaces: [production]
    verifyImages:
    - imageReferences:
      - "my-registry/*"
      attestors:
      - count: 1
        entries:
        - keyless:
            subject: "https://github.com/my-org/my-repo/.github/workflows/*"
            issuer: "https://token.actions.githubusercontent.com"

SLSA:构建可信度框架

SLSA(Supply chain Levels for Software Artifacts)定义了四个安全级别:

级别要求防御
L1有构建记录基本溯源
L2托管构建服务防止开发者篡改
L3强化构建平台防止构建系统被攻击
L4两人审查 + 密封构建最高级别保护

生成 SLSA Provenance

# GitHub Actions:使用官方 SLSA generator
jobs:
  build:
    outputs:
      image: ${{ steps.build.outputs.image }}
      digest: ${{ steps.build.outputs.digest }}
    steps:
    - name: Build and push
      id: build
      uses: docker/build-push-action@v5
      with:
        push: true
        tags: ${{ env.IMAGE_TAG }}

  provenance:
    needs: build
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2
    with:
      image: ${{ needs.build.outputs.image }}
      digest: ${{ needs.build.outputs.digest }}
    secrets:
      registry-username: ${{ secrets.REGISTRY_USER }}
      registry-password: ${{ secrets.REGISTRY_PASSWORD }}

验证 Provenance

# 验证镜像的 SLSA provenance
slsa-verifier verify-image my-registry/my-app:v1.0.0 \
  --source-uri github.com/my-org/my-repo \
  --source-tag v1.0.0

完整的安全流水线

# .gitlab-ci.yml 安全增强版
stages:
  - build
  - sign
  - attest
  - verify

build-image:
  stage: build
  script:
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG
    - syft $IMAGE_TAG -o cyclonedx-json > sbom.cdx.json
  artifacts:
    paths: [sbom.cdx.json]

sign-image:
  stage: sign
  script:
    # 签名镜像
    - cosign sign --key $COSIGN_KEY $IMAGE_TAG
    # 将 SBOM 附加到镜像
    - cosign attest --key $COSIGN_KEY \
        --predicate sbom.cdx.json \
        --type cyclonedx \
        $IMAGE_TAG

verify-before-deploy:
  stage: verify
  script:
    # 部署前验证签名
    - cosign verify --key $COSIGN_PUB $IMAGE_TAG
    # 验证 SBOM 中无高危漏洞
    - grype sbom:sbom.cdx.json --fail-on high

供应链安全不是一次性工作,而是需要嵌入到每个开发和部署环节的持续实践。从 SBOM 开始,逐步推进到签名验证和 SLSA 合规,是最务实的路径。

← 返回文章列表