跳转到主要内容

自动安装 Pigsty 仓库公钥

尽最大努力准备 Pigsty 公钥,复用已有文件;失败时告警并降级,元数据显式指定密钥时保持严格要求。
尽最大努力准备 Pigsty 公钥,复用已有文件;失败时告警并降级,元数据显式指定密钥时保持严格要求。

决策日期: 2026-10-04
状态: Released(已发布),随 v1.9.0 交付。
当前参考: pig repo
范围: 配置仓库时安装已有的内嵌 Pigsty 公钥。

决策

当所选模块包含当前平台可用的 pigsty-infra 或 pigsty-pgsql 仓库时,先准备内嵌 Pigsty 公钥,再修改仓库定义。该逻辑放在共享配置流程中,使 repo add、repo set 以及复用此流程的调用方保持一致。已有公钥文件直接复用,自动安装尽最大努力; 所选仓库元数据显式引用签名密钥时,安装失败才必须终止。

背景

基线实现 只在调用方指定 GPGCheck 时安装公钥,原生 sty boot 使用了这一选项。 因此,普通 repo add/set 没有安装 PIG 已经内嵌的公钥。

两个 Pigsty 仓库都使用此公钥,而它们分布在 pigsty、infra、pgsql 和默认的 all 选择中。只检查命令参数是否包含字面量 pigsty 会遗漏正常用法。

APT 不会自动发现 /etc/apt/keyrings 中的文件,仓库必须通过 signed-by 引用准备好的 公钥,否则即使文件写入成功,刷新缓存时仍会出现 NO_PUBKEY 警告。

降级时删除 signed-by,可能与保留的同源 APT 定义冲突,因此成功和失败时都保持默认引用一致。 显式元数据指定的是它实际需要的密钥,准备一个无关的默认文件不能满足要求。

备选方案

  • 运行时下载默认公钥。 现有内嵌发布输入已经提供公钥,支持离线使用,无须增加网络或外部工具依赖。
  • 每次仓库操作都安装公钥。 无关仓库不应触发 Pigsty 公钥写入,应先解析模块成员与平台可用性。
  • 自动安装公钥失败就阻止仓库操作。 可选的公钥准备不应阻止已有兼容模式工作,因此拒绝这种处理。 显式签名密钥元数据仍是严格边界。
  • 同时开启所有签名校验。 发布者身份、RPM 包签名和 APT 元数据认证是不同的契约。 自动安装公钥不能证明所有软件包或镜像都具备对应签名。

契约

  • 安装前校验请求的模块。被拒绝的仓库替换请求不会安装公钥或移动仓库文件。
  • 检查展开后模块中的两个 Pigsty 仓库标识符,包括自定义模块;不凭 URL 主机名选择签名身份。
  • EL 写入 /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty,Debian/Ubuntu 写入 /etc/apt/keyrings/pigsty.asc;仅在需要安装时写入内嵌公钥,权限为 0644。
  • 先检查公钥普通文件是否存在,包括能解析到普通文件的符号链接;存在时复用,不修改内容或权限。 存在性检查失败时仍尝试安装。
  • 父目录缺失时使用已有 sudo 回退机制创建,并通过原子文件写入逻辑安装。 检查目标时遇到权限不足,仍应进入提权安装并再次检查目标。目标被目录或悬空符号链接占用属于安装错误。
  • 未显式指定密钥时,安装失败只告警并继续;仅所选 Pigsty 定义降级为 APT trusted=yes, 或 RPM gpgcheck=0 与 repo_gpgcheck=0。成功和失败时均补齐默认的 gpgkey 或 signed-by 引用,不通过改写已保留的仓库文件实现降级。
  • 显式密钥准备针对实际引用。APT 的 signed-by 接受已有普通密钥文件的绝对路径,多个路径以 逗号分隔;显式引用默认路径时可安装内嵌公钥。EL 按需准备显式引用的默认公钥文件,再把 gpgkey 中的路径或不含变量的 URL 交给原生 rpm --import。
  • 显式密钥准备失败会在备份、写入仓库、刷新缓存之前终止。保留其引用,绝不降级该定义。 有效自定义密钥不依赖默认路径;其他所选仓库的默认密钥失败只使对应的默认定义降级。
  • 普通操作成功准备公钥后保留签名校验设置。sty boot 在公钥准备成功时请求启用校验, 默认公钥失败时采用同样的降级规则。
  • 降级警告同时写入 stderr 和 repo add/set 的 data.warnings,sty boot 也保留在自身告警中。 默认安装不导入 RPM 数据库,EL 显式密钥配置会导入;两种情况都不修改 APT 全局信任库。
  • 仓库回滚恢复仓库定义,已经安装或导入的公钥保留。

影响

添加 Pigsty 仓库时会一并尝试准备公钥文件,离线主机也适用。默认公钥失败不再阻止仓库配置。 降级会关闭这些 Pigsty 定义的签名校验,并明确报告。存在性检查成功后保留管理员已有文件, 不校验其内容;第三方仓库的信任策略保持不变。 密钥不可用时,APT 可能告警并沿用此前认证过的索引,因此仓库配置成功不能证明每个索引都刚刚下载。 当前默认行为和路径以仓库参考页为准。

验证与演进

自动公钥准备实现 与仓库回归测试 已记录在源代码提交 56f7353 中。本地回归测试覆盖 EL、Debian、Ubuntu 及两种支持的架构,并检查默认选择、组合模块、已有公钥复用、存在性检查被拒、自定义模块、 不可用仓库、默认公钥降级,以及显式密钥安装失败时不修改仓库。已有仓库替换测试继续验证回滚行为。

本地 EL9、EL10、Debian 12 和 Ubuntu 24 ARM64 虚拟机中的实际 CLI 测试使用独立挂载命名空间,验证普通用户通过 sudo 创建缺失的密钥目录、内嵌公钥字节与权限一致、重复执行、组合模块、可解析的结构化输出, 以及默认公钥失败时告警并继续、显式密钥失败时在替换仓库之前停止。测试使用真实 DNF/APT, 使用隔离缓存,并查询生成索引中的可用包。APT 还验证成功安装后的密钥引用 消除了 NO_PUBKEY 警告,以及显式配置 signed-by 与 trusted=no 时能完成元数据认证。 这些检查不安装软件包,也不验证 RPM 包签名。虚拟机原有仓库定义、公钥与缓存保持不变。

后续回归补充了保留旧 APT 源与已认证缓存、自定义密钥缺失时阻止添加和替换、默认路径不可用时 有效自定义密钥仍能工作,以及显式与默认密钥混合配置的场景。权限测试禁止普通用户遍历密钥目录, 验证提权安装和隐藏符号链接拒绝行为。RPM 导入测试使用虚拟机 RPM 数据库的隔离副本。

当前状态

该实现已进入经过验证的 v1.9.0 标签 与正式发布制品。上述实现与本地验证的证据范围保持不变。 软件仓库发布、公开文档部署与既有系统升级仍是独立交付阶段。