3. 制品类型与签名需求:容器镜像、Helm Chart、JAR/WAR包、NPM包等不同制品的签名场景与安全要求
在平台工程 IDP 中,CI/CD 流水线会产出多种类型的制品。不同制品的打包方式、分发机制和运行时环境差异巨大,其签名需求和安全要求也各不相同。本章将系统梳理容器镜像、Helm Chart、JAR/WAR 包、NPM 包等主流制品的签名场景,并给出对应的安全策略建议。
3.1 制品签名核心目标与通用流程
无论哪种制品类型,签名的核心目标是一致的:
- 完整性验证:确保制品在构建、传输、存储过程中未被篡改。
- 来源认证:确认制品确实来自受信任的构建系统或发布者。
- 不可否认性:发布者无法否认其签发的制品。
- 策略执行:在部署或安装环节,根据签名状态执行准入控制。
通用签名流程:构建 → 计算摘要 → 使用私钥签名 → 附加签名或生成独立签名文件 → 分发签名与制品 → 验证方使用公钥验证摘要 → 比对摘要。
3.2 容器镜像签名
容器镜像是云原生环境中最核心的制品。其签名需求源于镜像的多层结构、仓库分发机制以及 Kubernetes 等运行时的安全准入要求。
3.2.1 签名场景与工具
| 场景 | 说明 | 推荐工具/标准 |
|---|---|---|
| 镜像仓库签名 | 在推送镜像到仓库时,对镜像 Manifest 进行签名 | Notation、Cosign |
| 构建时签名 | 在 CI 流水线构建完成后立即签名 | Cosign (Keyless 模式)、Kaniko |
| 运行时验证 | Kubernetes 准入控制器在拉取镜像前验证签名 | Ratify、Kyverno、OPA Gatekeeper |
| 镜像层签名 | 对每一层内容进行签名,粒度更细 | OCI Artifact Manifest + Notation |
3.2.2 安全要求
- 签名不可剥离:签名应作为 OCI Artifact 与镜像关联,而非仅存于仓库元数据。
- 支持 Keyless 模式:利用 OIDC 和临时证书,避免长期私钥管理风险。
- 准入策略绑定:签名验证结果必须与部署策略联动,拒绝未签名或签名无效的镜像。
- 镜像摘要锁定:签名应绑定镜像的 digest(sha256),而非 tag。
实践要点:在 GitOps 工作流中,建议将签名验证作为 ArgoCD 或 Flux 的 pre-sync hook,确保只有经过签名的镜像才能被部署到生产环境。
3.3 Helm Chart 签名
Helm Chart 是 Kubernetes 应用的打包格式。Chart 签名主要保护 Chart 包(.tgz)的完整性和来源,确保用户在安装或升级时使用的是未被篡改的 Chart。
3.3.1 签名机制
Helm 原生支持使用 GPG 对 Chart 进行签名。签名过程生成一个 .prov 文件(provenance file),包含 Chart 包的哈希值和签名。
# 使用 GPG 密钥对 Chart 签名
helm package --sign --key 'your-key-name' --keyring ~/.gnupg/secring.gpg ./mychart
# 验证 Chart 签名
helm verify ./mychart-0.1.0.tgz --keyring ~/.gnupg/pubring.gpg
3.3.2 安全要求
| 要求 | 说明 |
|---|---|
| GPG 密钥管理 | 使用专用签名密钥,与开发者个人密钥分离;密钥过期策略需明确 |
| Chart 仓库集成 | ChartMuseum 或 OCI 仓库应支持存储和分发 .prov 文件 |
| 依赖验证 | 子 Chart 和依赖库也需签名,形成信任链 |
| CI/CD 自动化 | 在流水线中集成 helm package --sign,私钥存储在 HSM 或密钥管理服务中 |
注意:Helm 3 默认使用 OCI 仓库时,签名机制仍在演进中。建议结合 Notation 或 Cosign 对 OCI 制品进行统一签名,而非仅依赖 GPG。
3.4 JAR/WAR 包签名
JAR/WAR 包是 Java 生态的标准制品。签名通常使用 jarsigner 工具,基于数字证书对包内所有文件进行签名。
3.4.1 签名场景
- 企业级应用部署:确保部署到应用服务器的 JAR/WAR 未被篡改。
- Maven/Gradle 仓库:对发布的构件进行签名,防止依赖混淆攻击。
- 安全审计:签名信息可追溯至构建者或 CI 系统。
3.4.2 安全要求
| 要求 | 说明 |
|---|---|
| 证书链完整 | 签名证书需由受信任的 CA 签发,或使用内部 PKI 并分发根证书 |
| 时间戳 | 使用 TSA(时间戳权威)为签名添加时间戳,确保证书过期后签名仍有效 |
| 签名算法 | 推荐使用 SHA-256 或更高强度的摘要算法,避免使用 SHA-1 |
| CI/CD 集成 | 在 Maven/Gradle 构建插件中配置 jarsigner,私钥不得出现在构建脚本中 |
# 使用 jarsigner 签名 JAR 包
jarsigner -keystore mykeystore.jks -storepass:env KEYSTORE_PASS \
-tsa http://timestamp.digicert.com \
myapp.jar mykey-alias
# 验证 JAR 包签名
jarsigner -verify -verbose -certs myapp.jar
3.5 NPM 包签名
NPM 生态的签名机制相对较新。npm CLI 从 v8.0.0 开始支持包签名验证,使用 ECDSA 密钥对。
3.5.1 签名场景
- 发布签名:在
npm publish时对包内容进行签名。 - 安装验证:在
npm install时验证包的签名。 - 供应链安全:结合 npm audit 和签名验证,防止恶意包注入。
3.5.2 安全要求
| 要求 | 说明 |
|---|---|
| 密钥对生成 | 使用 npm sign 命令生成 ECDSA 密钥对,公钥上传至 npm registry |
| CI/CD 集成 | 私钥存储在 CI 系统的 secrets 中,发布流水线自动执行签名 |
| 验证策略 | 在安装时通过 --signature 标志或配置 audit-signatures 强制验证 |
| 作用域包 | 企业应要求所有 @scope 包必须签名,未签名的包禁止安装 |
实践要点:对于私有 npm registry(如 Verdaccio、Artifactory),建议启用签名验证插件,在代理层拦截未签名的包。
3.6 制品签名需求对比总览
| 制品类型 | 签名工具/标准 | 签名对象 | 验证时机 | 密钥管理复杂度 | CI/CD 集成难度 |
|---|---|---|---|---|---|
| 容器镜像 | Cosign, Notation | 镜像 Manifest | 拉取时(准入控制) | 中(支持 Keyless) | 低 |
| Helm Chart | GPG, Cosign (OCI) | Chart 包 (.tgz) | 安装/升级时 | 中 | 中 |
| JAR/WAR | jarsigner | 包内所有文件 | 部署时 | 高(需 CA 证书) | 中 |
| NPM 包 | npm sign (ECDSA) | 包内容 | 安装时 | 低 | 低 |
3.7 跨制品签名策略建议
在平台工程实践中,建议采用以下策略统一管理多制品签名:
- 统一签名层:使用 OCI Artifact 规范,将签名作为独立 Artifact 存储,与制品类型解耦。
- 密钥集中管理:所有签名私钥统一托管在 KMS(如 AWS KMS、HashiCorp Vault)中,CI/CD 流水线通过临时令牌获取签名权限。
- 策略即代码:将签名验证策略(如“必须签名”、“签名者必须在白名单内”)定义为代码,与部署流水线集成。
- 审计与可观测性:所有签名和验证操作记录到审计日志,便于事后追溯。
推荐路径:从容器镜像签名开始(Cosign + Keyless),逐步扩展到 Helm Chart 和 NPM 包,最后覆盖 JAR/WAR 等传统制品。优先选择支持 OCI 标准的工具,降低集成成本。