BlueBuild项目中的容器镜像签名递归问题解析

BlueBuild项目中的容器镜像签名递归问题解析

在容器镜像构建和部署过程中,签名验证是确保镜像完整性和来源可信性的重要环节。近期在BlueBuild项目中发现了一个与容器镜像签名相关的技术问题,本文将深入分析该问题的成因、影响及解决方案。

问题背景

BlueBuild是一个容器镜像构建工具,它使用cosign对构建的镜像进行签名。然而在实际使用中发现,虽然通过BlueBuild构建并签名的镜像能够被rpm-ostree/bootc验证通过,但在使用Podman拉取镜像时却会出现错误提示:"Error: copying system image from manifest list: Source image rejected: A signature was required, but no signature exists"。

问题分析

经过深入调查,发现问题源于Docker镜像的manifest结构特性。现代容器镜像通常采用多级manifest结构,即使镜像只包含单一架构,也会通过manifest list进行引用。具体表现为:

  1. 镜像标签(如:20240328)指向一个manifest list
  2. 该manifest list再引用实际的镜像manifest
  3. BlueBuild默认只对顶层manifest进行签名
  4. Podman在拉取镜像时会递归检查所有层级的签名

这种不一致导致了验证失败,因为Podman期望在manifest list引用的每个子manifest上都能找到签名,而实际上只有顶层manifest被签名。

技术细节

问题的核心在于cosign的默认行为。默认情况下,cosign sign命令只会对指定的manifest进行签名,而不会递归地对所有引用的manifest进行签名。这与Podman的严格验证策略产生了冲突。

在Docker/OCI镜像规范中,manifest list(也称为image index)是一个包含多个平台特定manifest的清单。即使镜像只支持单一平台,构建系统也可能会生成这种结构,特别是当使用构建证明(attestations)等高级功能时。

解决方案

解决此问题的方法是在使用cosign签名时添加--recursive参数。该参数会使cosign递归地对manifest list引用的所有子manifest进行签名,确保整个镜像层次结构都得到签名。

在BlueBuild项目中,这一修改需要应用于两个关键函数:

  1. sign_images()
  2. sign_priv_public_pair()

这两个函数位于src/commands/build.rs文件中,负责处理镜像签名逻辑。

验证与效果

实施该解决方案后,可以观察到:

  1. 镜像构建过程中cosign会对所有层级的manifest进行签名
  2. Podman能够成功拉取并验证镜像
  3. 原有的rpm-ostree/bootc验证流程不受影响
  4. 整个签名验证链条变得完整

最佳实践建议

基于此问题的解决经验,建议在容器镜像相关开发中注意以下几点:

  1. 理解容器镜像的层次结构,特别是manifest list的作用
  2. 明确不同工具(如Podman、cosign等)的验证策略差异
  3. 在签名镜像时考虑使用--recursive参数以确保完整签名
  4. 测试镜像时不仅要验证构建成功,还要测试不同工具下的拉取和验证流程

总结

容器镜像签名是云原生安全的重要环节,理解签名验证的完整链条对于构建可靠的容器化系统至关重要。BlueBuild项目通过添加递归签名支持,解决了与Podman的兼容性问题,提升了工具的实用性和可靠性。这一改进也为其他容器工具开发者提供了有价值的参考。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值