L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Développement · SKILL.md

implementing-supply-chain-security-with-in-toto

implementing-supply-chain-security-with-in-toto

使用 in-toto 框架为容器构建流程实施软件供应链(Supply Chain)完整性验证,在 CI/CD 流水线各步骤创建经过密码学签名的证明(Attestation)。

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: implementing-supply-chain-security-with-in-toto description: 使用 in-toto 框架为容器构建流程实施软件供应链(Supply Chain)完整性验证,在 CI/CD 流水线各步骤创建经过密码学签名的证明(Attestation)。 domain: cybersecurity subdomain: container-security tags: [in-toto, supply-chain-security, attestation, slsa, sigstore, container-security, cncf, provenance, sbom] version: "1.0" author: mahipal license: Apache-2.0

使用 in-toto 实施供应链安全

概述

in-toto 是 CNCF 的一个毕业项目,用于确保软件供应链(Software Supply Chain)从启动到最终用户安装的完整性。它通过在每个步骤生成经过密码学签名的证明(attestation,也称"链接元数据"),创建整个软件开发生命周期的可验证记录,以证明发生了什么、由谁执行以及产生了哪些工件。在容器环境中,in-toto 可验证部署到 Kubernetes 的镜像是否遵循了已批准的构建流程且未被篡改。

前置条件

  • Python 3.8+ 或 Go 运行时(用于 in-toto 客户端库)
  • GPG 或 Ed25519 密钥(用于签署证明)
  • 容器构建流水线(Docker、Buildah 或 Kaniko)
  • 容器镜像仓库(Docker Hub、ECR、GCR 或 Harbor)
  • Kubernetes 集群(用于部署验证)

核心概念

供应链布局(Layout)

布局是核心策略文档,定义以下内容:

  • 步骤(Steps):供应链中的有序操作(克隆、构建、测试、打包、推送)
  • 执行者(Functionaries):执行每个步骤的授权实体(人员或 CI 系统)
  • 检查(Inspections):验证时在客户端执行的验证检查
  • 预期工件(Expected artifacts):步骤之间的输入/输出关系
from in_toto.models.layout import Layout, Step, Inspection
from securesystemslib.interface import import_ed25519_privatekey_from_file

# 创建供应链布局
layout = Layout()
layout.set_relative_expiration(months=3)

# 定义代码克隆步骤
step_clone = Step(name="clone")
step_clone.expected_materials = []
step_clone.expected_products = [["CREATE", "src/*"]]
step_clone.pubkeys = [clone_functionary_keyid]
step_clone.expected_command = ["git", "clone"]
step_clone.threshold = 1

# 定义构建步骤
step_build = Step(name="build")
step_build.expected_materials = [["MATCH", "src/*", "WITH", "PRODUCTS", "FROM", "clone"]]
step_build.expected_products = [["CREATE", "image.tar"]]
step_build.pubkeys = [build_functionary_keyid]
step_build.expected_command = ["docker", "build"]
step_build.threshold = 1

# 定义扫描步骤
step_scan = Step(name="scan")
step_scan.expected_materials = [["MATCH", "image.tar", "WITH", "PRODUCTS", "FROM", "build"]]
step_scan.expected_products = [["CREATE", "scan-report.json"]]
step_scan.pubkeys = [scan_functionary_keyid]
step_scan.threshold = 1

layout.steps = [step_clone, step_build, step_scan]

链接元数据(Link Metadata)

每个步骤执行都会生成包含以下内容的链接文件:

  • 消耗的材料(带哈希的输入工件)
  • 创建的产品(带哈希的输出工件)
  • 执行的命令
  • 执行者的密码学签名

验证流程

在部署时,验证器会检查:

  1. 所有必需步骤已执行
  2. 每个步骤均由授权执行者签署
  3. 步骤间的工件哈希正确链接
  4. 步骤间未发生未授权修改

实现步骤

步骤 1:生成签名密钥

# 为每个执行者生成 Ed25519 密钥对
mkdir -p keys

# 项目所有者密钥(用于签署布局)
in-toto-keygen --type ed25519 keys/owner

# CI 构建器密钥
in-toto-keygen --type ed25519 keys/builder

# 安全扫描器密钥
in-toto-keygen --type ed25519 keys/scanner

步骤 2:创建供应链布局

#!/usr/bin/env python3
"""生成容器构建的 in-toto 供应链布局。"""

from in_toto.models.layout import Layout, Step, Inspection
from in_toto.models.metadata import Envelope
from securesystemslib.signer import CryptoSigner
from securesystemslib.interface import import_ed25519_publickey_from_file

def create_container_build_layout():
    layout = Layout()
    layout.set_relative_expiration(months=6)

    # 加载执行者公钥
    builder_key = import_ed25519_publickey_from_file("keys/builder.pub")
    scanner_key = import_ed25519_publickey_from_file("keys/scanner.pub")

    layout.keys = {
        builder_key["keyid"]: builder_key,
        scanner_key["keyid"]: scanner_key,
    }

    # 步骤 1:源码检出
    checkout = Step(name="checkout")
    checkout.expected_materials = []
    checkout.expected_products = [
        ["CREATE", "Dockerfile"],
        ["CREATE", "src/*"],
        ["CREATE", "requirements.txt"],
    ]
    checkout.pubkeys = [builder_key["keyid"]]
    checkout.threshold = 1

    # 步骤 2:构建容器镜像
    build = Step(name="build")
    build.expected_materials = [
        ["MATCH", "Dockerfile", "WITH", "PRODUCTS", "FROM", "checkout"],
        ["MATCH", "src/*", "WITH", "PRODUCTS", "FROM", "checkout"],
    ]
    build.expected_products = [["CREATE", "image-digest.txt"]]
    build.pubkeys = [builder_key["keyid"]]
    build.threshold = 1

    # 步骤 3:安全扫描
    scan = Step(name="scan")
    scan.expected_materials = [
        ["MATCH", "image-digest.txt", "WITH", "PRODUCTS", "FROM", "build"]
    ]
    scan.expected_products = [
        ["CREATE", "vulnerability-report.json"],
        ["CREATE", "sbom.json"],
    ]
    scan.pubkeys = [scanner_key["keyid"]]
    scan.threshold = 1

    # 检查:验证无严重漏洞
    inspect_vulns = Inspection(name="verify-no-critical-vulns")
    inspect_vulns.expected_materials = [
        ["MATCH", "vulnerability-report.json", "WITH", "PRODUCTS", "FROM", "scan"]
    ]
    inspect_vulns.run = [
        "python", "-c",
        "import json,sys; r=json.load(open('vulnerability-report.json')); "
        "sys.exit(1) if any(v['severity']=='CRITICAL' for v in r.get('vulnerabilities',[])) else sys.exit(0)"
    ]

    layout.steps = [checkout, build, scan]
    layout.inspect = [inspect_vulns]

    return layout

if __name__ == "__main__":
    layout = create_container_build_layout()
    # 使用所有者密钥签署并保存
    owner_signer = CryptoSigner.from_priv_key_uri("file:keys/owner")
    envelope = Envelope.from_signable(layout)
    envelope.create_signature(owner_signer)
    envelope.dump("root.layout")
    print("布局已创建并签署:root.layout")

步骤 3:记录流水线步骤

# 在 CI/CD 流水线中记录每个步骤

# 步骤 1:检出
in-toto-run --step-name checkout \
  --key keys/builder \
  --products Dockerfile src/* requirements.txt \
  -- git clone https://github.com/org/app.git .

# 步骤 2:构建
in-toto-run --step-name build \
  --key keys/builder \
  --materials Dockerfile src/* \
  --products image-digest.txt \
  -- bash -c "docker build -t app:latest . && docker inspect --format='{{.Id}}' app:latest > image-digest.txt"

# 步骤 3:扫描
in-toto-run --step-name scan \
  --key keys/scanner \
  --materials image-digest.txt \
  --products vulnerability-report.json sbom.json \
  -- bash -c "trivy image --format json app:latest > vulnerability-report.json && syft app:latest -o json > sbom.json"

步骤 4:部署前验证

# 验证整个供应链
in-toto-verify --layout root.layout \
  --layout-key keys/owner.pub \
  --link-dir ./link-metadata/

# 验证通过后继续部署
if [ $? -eq 0 ]; then
  kubectl apply -f deployment.yaml
  echo "供应链验证通过 - 开始部署"
else
  echo "供应链验证失败 - 阻止部署"
  exit 1
fi

步骤 5:Kubernetes 准入控制

将策略引擎集成以在准入时验证证明:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: in-toto-verifier
webhooks:
  - name: verify.in-toto.io
    rules:
      - apiGroups: ["apps"]
        resources: ["deployments"]
        operations: ["CREATE", "UPDATE"]
    clientConfig:
      service:
        name: in-toto-webhook
        namespace: security
        path: /verify
    failurePolicy: Fail
    sideEffects: None
    admissionReviewVersions: ["v1"]

SLSA 集成

in-toto 证明直接映射到 SLSA(Supply chain Levels for Software Artifacts)要求:

SLSA 等级in-toto 要求
等级 1构建流程已记录(布局已存在)
等级 2来自托管构建服务的签名证明
等级 3加固构建平台、不可伪造的来源证明
等级 4双方审查、密封构建

参考资料

Skills enregistrées