4. 密钥管理基础:生成密钥对(公钥/私钥)、安全存储私钥、导出与分发公钥的最佳实践
在 Cosign 签名体系中,密钥对是信任链的根。私钥用于对容器镜像进行签名,公钥则分发给验证方用于校验签名完整性。本章将系统讲解密钥对的生成、私钥的安全存储以及公钥的导出与分发策略,确保签名流程的机密性、完整性与可用性。
4.1 密钥对生成:使用 Cosign 生成密钥对
Cosign 支持两种密钥生成方式:本地生成(基于 OpenSSL / PGP)和 KMS / 硬件安全模块。生产环境推荐使用 KMS 或 HSM 托管私钥,开发测试阶段可使用本地生成。
核心命令:
# 生成密钥对(默认使用 ECDSA P-256 曲线)
cosign generate-key-pair
# 指定输出文件名前缀
cosign generate-key-pair --output-key-prefix myapp
执行后会在当前目录生成两个文件:cosign.key(私钥)和 cosign.pub(公钥)。
| 参数 | 说明 | 推荐值 |
|---|---|---|
--output-key-prefix |
密钥文件前缀 | 按应用名命名,如 production-app |
--kms |
指定 KMS 提供商 | awskms:// / gcpkms:// / azurekms:// |
--key |
指定已有私钥路径(用于导入) | 仅迁移场景使用 |
最佳实践:始终使用
--output-key-prefix 为密钥文件添加应用和环境标识,避免多项目密钥混淆。
4.2 私钥安全存储:保护签名根密钥
私钥一旦泄露,攻击者可伪造任意镜像签名。因此私钥存储必须遵循最小权限、加密存储、访问审计三大原则。
- 文件系统权限:私钥文件权限设为
0400(仅属主可读),属主应为专用服务账户。 - 加密存储:使用 Cosign 内置加密功能对私钥进行密码保护:
cosign generate-key-pair # 系统会提示输入加密密码(至少 16 位,含大小写字母和数字) - KMS / HSM 托管:私钥永不离开硬件安全模块,签名操作通过 API 调用完成:
cosign sign --key gcpkms://projects/my-project/locations/global/keyRings/my-ring/cryptoKeys/my-key my-image:tag - 访问审计:所有私钥访问操作应记录到安全审计系统(如 AWS CloudTrail、GCP Audit Logs)。
安全警告:切勿将私钥文件提交到 Git 仓库、存储在 CI/CD 环境变量中或通过不安全的通道传输。私钥密码应使用密钥管理服务(如 HashiCorp Vault、AWS Secrets Manager)管理。
4.3 公钥导出与分发:建立信任基础
公钥需要安全地分发给所有需要验证镜像签名的消费者(如 CI/CD 流水线、Kubernetes 集群、镜像仓库)。
4.3.1 公钥导出格式
| 格式 | 命令 | 适用场景 |
|---|---|---|
| PEM 文本 | cat cosign.pub |
手动配置、文档记录 |
| Base64 编码 | cat cosign.pub | base64 |
Kubernetes Secret、环境变量 |
| KMS 引用 | cosign public-key --key gcpkms://... |
KMS 托管公钥的导出 |
4.3.2 公钥分发最佳实践
- Kubernetes Secret:将公钥存储为 Opaque Secret,挂载到验证 Pod:
kubectl create secret generic cosign-public-keys \ --from-file=cosign.pub=./cosign.pub \ --namespace cosign-system - OCI 仓库注解:将公钥作为镜像仓库的注解存储,方便自动拉取:
cosign copy --key cosign.pub my-image:tag my-image:tag-signed - 公开密钥服务器:对于开源项目,可将公钥上传到 Sigstore 公共实例或项目官网。
- CI/CD 变量:在 CI/CD 平台(如 GitHub Actions、GitLab CI)中设置受保护的变量存储公钥。
推荐做法:使用
cosign public-key --key 命令从 KMS 导出公钥,确保公钥与私钥始终来自同一密钥对,避免手动复制错误。
4.4 密钥生命周期管理流程
4.5 密钥轮换与撤销策略
密钥轮换是安全基线要求。Cosign 支持多密钥验证,允许新旧密钥共存,确保轮换期间不中断验证流程。
- 轮换周期:生产环境建议每 90 天轮换一次签名密钥。
- 轮换步骤:
- 生成新密钥对,使用新私钥对新镜像进行签名。
- 将新公钥添加到验证方的信任列表中(旧公钥保留)。
- 使用旧私钥对旧镜像重新签名(可选,用于保持签名连续性)。
- 30 天后移除旧公钥,完成轮换。
- 密钥撤销:当私钥泄露或员工离职时,立即撤销对应公钥,并通过安全通道通知所有验证方更新信任列表。
多密钥验证配置示例(Kubernetes):
apiVersion: v1
kind: ConfigMap
metadata:
name: cosign-policy
namespace: cosign-system
data:
cosign.pub: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
cosign.pub.old: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
4.6 密钥管理常见错误与避坑指南
| 错误做法 | 风险 | 正确做法 |
|---|---|---|
| 私钥文件权限设为 0644 | 其他用户可读取私钥 | 设为 0400,属主为专用账户 |
| 使用弱密码加密私钥 | 密码可被暴力破解 | 使用 16 位以上随机密码 |
| 公钥通过 HTTP 明文传输 | 中间人攻击替换公钥 | 使用 HTTPS 或带签名的分发通道 |
| 所有环境使用同一密钥对 | 开发环境泄露影响生产 | 开发/测试/生产使用独立密钥对 |
| 密钥轮换后立即删除旧公钥 | 历史镜像验证失败 | 保留旧公钥至少一个轮换周期 |
关键提醒:密钥管理是容器安全供应链的基石。一个被攻破的私钥可以瓦解整个签名信任体系。请将密钥管理纳入组织的安全策略和审计范围,定期进行密钥安全审查。