4. Cosign 简介:工具概述与签名验证核心能力

Cosign 是 Sigstore 项目下的开源签名工具,专为容器镜像和软件制品提供免密钥(或无密钥)的代码签名与验证。它解决了传统 PGP 签名在密钥管理、轮换和分发上的痛点,使签名操作可以无缝集成到 CI/CD 流水线中。在策略即代码(Policy-as-Code)回滚护栏场景下,Cosign 的版本差异校验能力是判断镜像是否被篡改、是否应被允许部署的关键技术基础。

4.1 Cosign 工具概述

Cosign 由 Google、Red Hat、Linux Foundation 等组织联合推动,核心设计目标包括:

  • 免密钥签名:通过 Sigstore 公钥基础设施(PKI)和 OIDC 身份认证,开发者无需自行管理私钥。
  • 容器原生支持:直接操作 OCI 镜像仓库,签名作为镜像标签或 OCI 制品存储。
  • 策略集成:支持与 Kyverno、OPA、Kubernetes 准入控制器等策略引擎配合。
  • 多格式支持:除容器镜像外,还可对 blob、文本文件、SBOM、 attestation 等制品签名。
特性 传统 PGP 签名 Cosign (Sigstore)
密钥管理 开发者自行生成、保护、轮换私钥 临时密钥 + OIDC 身份绑定,无需长期私钥
验证依赖 需要预先分发公钥 通过 Sigstore 透明日志或公钥发现服务
CI/CD 集成 手动步骤多,易出错 一行命令完成签名,原生支持 GitHub Actions、GitLab CI
回滚校验 无法直接关联版本差异 支持签名负载内嵌版本元数据,便于差异比对
关键概念: Cosign 的签名本质上是一个加密签名对象,它被附加到制品上(通常作为 OCI 仓库中的独立标签或 referrers API 对象)。签名本身包含制品的哈希值、签名者身份、时间戳以及可选的附加声明(如版本号、构建元数据)。

4.2 签名与验证的核心能力

Cosign 提供两组核心操作:cosign sign 和 cosign verify。在回滚护栏场景中,这两组操作分别对应“锁定版本”和“校验版本差异”两个阶段。

4.2.1 签名流程

  1. 身份认证:通过 OIDC 获取身份令牌(如 GitHub OAuth、Google、Microsoft)。
  2. 临时密钥生成:Cosign 生成一对短期密钥对,私钥仅用于本次签名。
  3. 签名计算:对制品内容(镜像 manifest 或文件)计算 SHA256 哈希,并用私钥签名。
  4. 上传签名:签名、公钥、身份证书上传至 Sigstore 透明日志(Rekor),同时签名对象写入 OCI 仓库。
# 使用 Cosign 对容器镜像签名(免密钥模式)
cosign sign --key "" ghcr.io/myorg/myapp:v1.0.0

# 使用本地密钥对签名(适用于离线环境)
cosign generate-key-pair
cosign sign --key cosign.key ghcr.io/myorg/myapp:v1.0.0

4.2.2 验证流程

  1. 获取签名:从 OCI 仓库或 Rekor 日志拉取与制品关联的签名对象。
  2. 身份验证:验证签名者的 OIDC 身份是否属于受信任的颁发者(如 https://github.com/login/oauth)。
  3. 哈希比对:重新计算当前制品的哈希值,与签名中存储的哈希值比对。
  4. 透明日志校验:确认签名已记录在 Rekor 中,防止签名被私下替换。
# 验证镜像签名
cosign verify --key cosign.pub ghcr.io/myorg/myapp:v1.0.0

# 验证并输出签名负载中的自定义声明
cosign verify --key cosign.pub --output json ghcr.io/myorg/myapp:v1.0.0 | jq .
版本差异校验的关键: 在签名负载(payload)中,可以嵌入 version、build-id、git-commit 等自定义字段。回滚护栏策略通过比对当前部署版本的签名负载与目标版本的签名负载,即可判断版本是否回退、是否跳版本、是否被篡改。
Cosign 签名与验证核心流程 签名阶段 (cosign sign) OIDC 身份认证 生成临时密钥对 计算制品哈希 私钥签名 + 上传 制品 + 签名 验证阶段 (cosign verify) 拉取签名对象 验证 OIDC 身份 哈希比对 透明日志校验 验证通过 / 拒绝 回滚护栏扩展:版本差异校验 比对签名负载中的 version / build-id 字段 身份/密钥 签名操作 验证操作 校验步骤

4.3 签名负载结构

Cosign 签名负载(payload)是一个 JSON 对象,其中包含验证所需的核心字段。在回滚护栏中,critical 和 optional 字段是版本差异校验的切入点。

{
  "critical": {
    "identity": {
      "docker-reference": "ghcr.io/myorg/myapp"
    },
    "image": {
      "docker-manifest-digest": "sha256:a1b2c3d4e5f6..."
    },
    "type": "cosign container image signature"
  },
  "optional": {
    "version": "v1.0.0",
    "build-id": "20240315-01",
    "git-commit": "abc123def456",
    "environment": "production"
  }
}
字段路径 说明 回滚校验用途
critical.image.docker-manifest-digest 制品内容的 SHA256 哈希 检测镜像内容是否被篡改
critical.identity.docker-reference 镜像仓库地址 确认制品来源是否受信任
optional.version 语义化版本号(自定义) 判断版本是否回退或跳版本
optional.build-id 构建流水线唯一标识 关联 CI/CD 构建上下文
optional.git-commit Git 提交哈希 精确追溯代码变更
注意: optional 字段并非 Cosign 强制要求,需要开发者在签名时通过 --annotations 参数注入。回滚护栏策略必须约定统一的 annotation key 命名规范,否则不同团队注入的字段名不一致会导致校验失败。

4.4 在回滚护栏中的角色定位

Cosign 在策略即代码回滚护栏中承担以下职责:

  • 完整性保障:确保回滚目标镜像未被篡改,哈希校验是版本差异校验的第一道防线。
  • 身份绑定:确认回滚操作仅允许由受信任的 CI/CD 系统或授权人员执行。
  • 版本元数据载体:签名负载中的 optional 字段为策略引擎提供版本比对依据。
  • 不可抵赖性:透明日志记录所有签名事件,回滚操作可审计、可追溯。