4. 签名技术选型:GPG、Sigstore/Cosign、JWT签名对比与适用场景
在CI/CD流水线中,构建产物的签名技术直接决定了完整性验证与来源可信度的根基。当前主流方案包括GPG、Sigstore/Cosign以及JWT签名,三者分别代表了传统PKI、现代无密钥基础设施和令牌化签名的不同路径。本章从技术原理、密钥管理、验证效率、合规阻断能力四个维度进行系统对比,并给出明确的场景选型建议。
核心观点:没有“最好”的签名技术,只有“最适配”流水线合规策略的选型。GPG适合遗留系统与离线环境,Sigstore/Cosign是云原生与供应链安全的首选,JWT签名则适用于短生命周期、高频率的微服务产物。
4.1 技术原理与密钥管理对比
| 维度 | GPG | Sigstore / Cosign | JWT 签名 |
|---|---|---|---|
| 密钥模型 | 非对称密钥对(公钥/私钥),用户自行生成与管理 | 基于OIDC身份 + 临时密钥对,密钥由Fulcio CA签发 | 对称密钥(HMAC)或非对称密钥(RS/ES系列) |
| 密钥生命周期 | 长期有效,需手动轮换与吊销 | 临时密钥(通常数分钟),自动轮换 | 由签发方控制,可短时效(如5分钟) |
| 公钥分发 | 需独立部署公钥服务器或手动导入 | 公钥通过Rekor透明日志自动记录,无需手动分发 | 公钥/密钥需通过安全通道预先共享 |
| 签名内容 | 对文件哈希或文件本身签名 | 对容器镜像、blob或附件签名 | 对JSON Payload签名,常用于API令牌 |
| 验证依赖 | 本地GPG密钥环 + 公钥 | Cosign CLI + Sigstore公共/私有实例 | JWT库 + 预共享密钥或公钥 |
选型提示:GPG的密钥管理成本最高,尤其在多团队、多流水线场景下,公钥分发与吊销极易出现“孤儿密钥”。Sigstore通过透明日志解决了这一痛点,但需要依赖外部CA服务。
4.2 签名验证流程与性能特征
三种技术在流水线中的验证流程差异显著,直接影响OPA策略的阻断点设计。
- GPG验证流程:下载产物 → 获取签名文件(.asc) → 导入公钥 →
gpg --verify→ 输出状态码。验证耗时约50-200ms,公钥缺失时需回退到密钥服务器查询。 - Cosign验证流程:拉取镜像 →
cosign verify→ 自动查询Rekor日志 → 验证证书链 → 输出Payload。验证耗时约200-500ms,依赖网络与透明日志可用性。 - JWT签名验证流程:解析JWT → 获取kid → 查找公钥 → 验签 → 校验exp/nbf/iss。验证耗时约1-10ms,性能最优,但需要预先缓存公钥。
性能陷阱:在流水线中,如果每批次构建产物超过1000个,GPG和Cosign的串行验证可能成为瓶颈。建议使用OPA的
data.artifacts.verify_batch规则进行批量验证,而非逐个调用外部命令。
4.3 适用场景矩阵
| 场景特征 | 推荐方案 | 理由 |
|---|---|---|
| 遗留Java JAR/WAR签名 | GPG | 与现有Maven/Gradle插件兼容,离线验证成熟 |
| 容器镜像签名(Kubernetes部署) | Sigstore / Cosign | 原生支持OCI镜像,与Kyverno/OPA Gatekeeper集成 |
| 微服务间API令牌签名 | JWT | 轻量、无状态、支持短时效,适合服务网格 |
| 多团队、多仓库的供应链安全 | Sigstore / Cosign | 透明日志提供全局可审计性,无需逐团队分发公钥 |
| 离线/内网环境(无互联网) | GPG | 完全自包含,不依赖外部CA或透明日志 |
| CI/CD流水线产物(通用二进制) | Cosign(blob签名) | 支持任意文件类型,验证命令统一 |
4.4 OPA策略中的签名验证集成模式
无论选择哪种签名技术,OPA策略的验证逻辑都应遵循统一的“验证-断言-阻断”模式。以下展示三种技术对应的Rego规则片段。
4.4.1 GPG验证的Rego规则
package artifacts.signature
# 输入:构建产物元数据,包含签名指纹与公钥ID
default allow = false
allow {
input.signature.type == "gpg"
input.signature.key_id == "0xABCDEF1234567890"
input.signature.verification_status == "success"
# 可选:检查签名时间是否在证书有效期内
input.signature.timestamp >= input.signature.key_valid_from
input.signature.timestamp <= input.signature.key_valid_to
}
4.4.2 Cosign验证的Rego规则
package artifacts.signature
# 输入:Cosign验证输出的JSON结果
default allow = false
allow {
input.signature.type == "cosign"
input.signature.verified == true
input.signature.identity.issuer == "https://.actions.githubusercontent.com"
input.signature.identity.subject == "repo:my-org/my-repo:.github/workflows/release.yml"
# 强制要求透明日志条目存在
input.signature.rekor_entry != null
input.signature.rekor_entry.inclusion_proof == true
}
4.4.3 JWT签名验证的Rego规则
package artifacts.signature
# 输入:JWT解码后的Payload与签名元数据
default allow = false
allow {
input.signature.type == "jwt"
input.signature.algorithm == "RS256"
input.signature.payload.iss == "pipeline-runner@my-corp"
input.signature.payload.exp >= time.now_ns() / 1000000000
input.signature.payload.nbf <= time.now_ns() / 1000000000
# 验证签名公钥指纹是否在白名单中
input.signature.kid in data.allowed_signing_keys
}
合规阻断要点:OPA策略不应仅验证签名是否存在,还应强制检查签名身份、时效性、透明日志记录(如适用)。对于Cosign,建议将
rekor_entry.inclusion_proof设为必须条件,防止签名被绕过透明日志直接验证。
4.5 选型总结与迁移建议
| 评估维度 | GPG | Sigstore / Cosign | JWT 签名 |
|---|---|---|---|
| 安全等级 | 高(依赖密钥管理成熟度) | 高(透明日志提供不可否认性) | 中(依赖密钥安全存储) |
| 运维复杂度 | 高 | 低(托管服务) | 中 |
| OPA集成难度 | 中(需解析gpg输出) | 低(原生JSON输出) | 低(JWT库直接解析) |
| 供应链审计能力 | 弱(无全局日志) | 强(Rekor透明日志) | 弱(需自行审计) |
| 推荐迁移路径 | → 逐步替换为Cosign | → 作为长期标准 | → 保留用于API令牌场景 |
迁移建议:如果当前流水线已大规模使用GPG,建议采用“双签名过渡期”——在同一个构建产物上同时附加GPG签名和Cosign签名,待所有验证方完成Cosign适配后再移除GPG。OPA策略在此期间可配置为“任一签名有效即通过”,降低迁移风险。