4. 镜像签名与验证:Cosign工具的使用、镜像签名策略与验证流程
在云原生安全体系中,镜像签名与验证是保障供应链安全的关键防线。本章将深入讲解如何使用 Cosign 工具对容器镜像进行签名,并构建从开发到生产的端到端验证策略,确保只有经过授权和完整性校验的镜像才能被部署到 Kubernetes 集群中。
4.1 镜像签名核心概念与价值
镜像签名并非简单的“打标签”,而是通过非对称加密技术为镜像内容生成数字签名,实现以下安全目标:
- 完整性校验:确保镜像从构建到部署的传输过程中未被篡改。
- 来源认证:验证镜像确实来自可信的发布者(如 CI/CD 流水线或安全团队)。
- 不可否认性:签名者无法否认其签发的镜像版本。
关键区别:镜像摘要(Digest)仅保证内容唯一性,而签名在摘要基础上附加了身份与信任链。没有签名的镜像,即使使用 digest 拉取,也无法确认其来源是否可信。
4.2 Cosign 工具概述与安装
Cosign 是 Sigstore 项目下的开源工具,专为容器镜像签名与验证设计。它支持密钥对、硬件安全模块(HSM)以及无密钥(Keyless)签名模式,极大降低了签名门槛。
| 特性 | 说明 |
|---|---|
| 签名存储 | 签名数据存储在 OCI 仓库中(与镜像同仓库或独立仓库),不修改原始镜像层。 |
| 密钥管理 | 支持本地密钥对、KMS(如 AWS KMS、GCP KMS)、以及 Sigstore 公钥基础设施(Keyless)。 |
| 验证方式 | 支持公钥验证、Keyless 验证(基于 OIDC 身份)、以及 Kubernetes 准入控制器集成。 |
| 平台兼容 | 原生支持 Docker、containerd、Podman 等主流容器运行时。 |
安装 Cosign(Linux/macOS):
# 使用官方脚本安装最新版本
curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64"
sudo mv cosign-linux-amd64 /usr/local/bin/cosign
sudo chmod +x /usr/local/bin/cosign
# 验证安装
cosign version
4.3 镜像签名策略与流程
一个完整的镜像签名策略应覆盖镜像生命周期中的三个关键阶段:构建阶段签名、仓库阶段存储、部署阶段验证。
4.4 使用 Cosign 进行镜像签名
以下演示使用密钥对模式对镜像进行签名。生产环境中建议使用 KMS 或 Keyless 模式以增强密钥安全性。
步骤1:生成密钥对
# 生成 cosign 密钥对(私钥加密存储)
cosign generate-key-pair
# 输出文件:
# cosign.key - 私钥(需妥善保管,建议使用密码保护)
# cosign.pub - 公钥(分发给验证方)
步骤2:对镜像进行签名
# 使用私钥对镜像签名(支持 digest 或 tag)
cosign sign --key cosign.key registry.example.com/my-app:v1.0.0
# 推荐使用 digest 进行签名,避免 tag 可变性
cosign sign --key cosign.key registry.example.com/my-app@sha256:abc123...
# 签名成功后,仓库中会生成一个 .sig 的 OCI artifact
安全警告:私钥文件(cosign.key)应仅存在于签名环境(如 CI/CD 构建节点)中,切勿将其提交到代码仓库或暴露在开发人员本地环境中。建议使用短期证书或 Keyless 模式减少私钥泄露风险。
步骤3:验证镜像签名
# 使用公钥验证镜像签名
cosign verify --key cosign.pub registry.example.com/my-app:v1.0.0
# 验证通过时输出签名信息,包括:
# - 签名者身份
# - 签名时间
# - 证书链信息(如使用 Keyless 模式)
4.5 验证策略与准入控制
在 Kubernetes 集群中,通过 Cosign 与 Kyverno / OPA Gatekeeper 集成,可以实现部署阶段的自动验证。
| 策略类型 | 描述 | 示例约束 |
|---|---|---|
| 身份约束 | 只允许特定身份(如 CI 系统)签名的镜像 | issuer: https://.actions.githubusercontent.com |
| 仓库约束 | 只允许来自受信任仓库的镜像 | registry: trusted-registry.io/* |
| 时间戳约束 | 签名时间必须在指定时间窗口内 | not-after: 24h |
| 证书链约束 | 签名证书必须由受信任的 CA 签发 | fulcio: true |
Kyverno 策略示例:强制镜像签名验证
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-image-signature
spec:
validationFailureAction: Enforce
rules:
- name: check-cosign-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "registry.example.com/*"
attestors:
- count: 1
entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
required: true
最佳实践:在 Helm Chart 中集成签名验证时,建议在 values.yaml 中声明预期的公钥指纹或 OIDC issuer,并通过 Helm 模板动态生成 Kyverno 策略,实现策略即代码(Policy as Code)。
4.6 Keyless 签名模式
Keyless 模式是 Sigstore 的独特优势,它消除了私钥管理的负担。签名者通过 OIDC 身份(如 GitHub Actions、GitLab CI)向 Fulcio(证书颁发机构)申请短期证书,签名后证书与签名一同存储。
Keyless 签名与验证命令:
# Keyless 签名(无需本地密钥)
cosign sign registry.example.com/my-app:v1.0.0
# Keyless 验证(自动查询 Rekor 透明日志)
cosign verify registry.example.com/my-app:v1.0.0
适用场景:Keyless 模式特别适合 CI/CD 自动化流水线,无需管理长期密钥,且所有签名记录都存储在 Rekor 透明日志中,提供可审计的签名历史。对于需要离线验证或严格密钥控制的环境,仍推荐使用密钥对模式。
4.7 镜像签名性能调优要点
在冷启动削峰场景下,镜像签名验证不应成为部署瓶颈。以下调优策略可显著降低验证延迟:
- 缓存公钥与证书:在准入控制器中缓存已验证的公钥和证书链,避免每次验证都进行网络请求。
- 并行验证:对于多容器 Pod,使用并发验证机制,减少串行等待时间。
- 预拉取签名数据:在节点预热阶段,提前拉取镜像的签名数据(.sig artifact),减少部署时的仓库请求。
- 选择轻量级验证策略:避免在验证策略中引入过多的外部依赖(如每次验证都查询 Rekor 日志),使用本地策略缓存。
通过合理配置签名策略与验证流程,可以在不牺牲安全性的前提下,将镜像验证延迟控制在毫秒级,满足冷启动削峰场景下的性能要求。