这是本节的多页打印视图。 .
发布注记
- 1: SILO 20261026:Server、mcli 与 KES 联合发布
- 2: SILO 20261018 发布说明
- 3: silo-pkg 3.14.3 发布
- 4: PGSTY KES 20261018 发布
- 5: SILO Console 2.4.2 发布
- 6: mcli 20261018 发布
- 7: silo-pkg 3.14.2 发布
- 8: SILO 20261015:已替代草稿记录
- 9: SILO Console 2.4.1 发布
- 10: silo-pkg 3.14.1 发布
- 11: SILO 20260916 发布注记
- 12: mcli 20260916 发布
- 13: mcli 20260913 发布
- 14: silo-pkg 3.14.0 发布
- 15: SILO Console 2.4.0 发布
- 16: Silo Console 2.2.0 发布说明
- 17: SILO Console 2.5:界面与管理功能更新
- 18: silo-pkg 3.15:Go 1.27.3 与 S3 SDK 修复
- 19: Silo Console 2.1.0 发布
- 20: Silo Console 2.0.0 发布
- 21: silo-pkg 3.13.0 正式发布
- 22: silo-pkg 3.12.0 正式发布
- 23: Silo Pkg 3.11.0 发布
- 24: Silo 20260903 正式发布
- 25: 显式版本删除现在要求 DeleteObjectVersion
- 26: mcli 20260903 正式发布
- 27: mcli 20260806 发布
- 28: Silo 20260806 发布
- 29: Silo 20260804 发布
- 30: mcli 20260804 发布
- 31: Silo 20260618 发布
- 32: Silo 20260417 发布
- 33: Silo 20260325 发布
- 34: Silo 20260321 发布
- 35: Silo 20260314 发布
- 36: Silo 20260214 发布
- 37: Silo 20251203 发布
发布日志记录各版本的功能演进、安全修复、依赖更新、兼容性要求与交付制品。
最新的 20261026 联合发布 汇总了 SILO Server、mcli 与 KES 自 20261018 正式版以来的全部更新,并配套发布 Console 2.5.1 与 silo-pkg 3.15.2(10 月 24—25 日的阶段性维护记录已并入正式发布日志,原链接自动重定向至新页面)。
1 - SILO 20261026:Server、mcli 与 KES 联合发布
SILO、mcli 与 PGSTY KES 20261026 现已联合发布,配套 SILO Console 2.5.1 与 silo-pkg 3.15.2。本文整合了 10 月 24—25 日的维护记录,完整说明自 20261018 正式版以来的所有变更。三个可执行组件采用统一的发布日期与包版本号;KES 仍作为可选的外部密钥服务独立部署。
发布组件
| 组件 | 版本 | 源码 | 交付形式 |
|---|---|---|---|
| SILO Server | 20261026000000.0.0 |
c3ad836aed0d |
平台归档、Linux 软件包、Docker Hub 镜像 |
| mcli | 20261026000000.0.0 |
0ceb298cdcd0 |
平台归档、Linux 软件包、Docker Hub 镜像 |
| PGSTY KES | 20261026000000.0.0 |
e9b4f1acebc1 |
平台归档、Linux 软件包、Docker Hub 镜像 |
| SILO Console | 2.5.1 |
fff1618d9abb |
Server 内嵌;独立二进制、软件包与镜像 |
| silo-pkg | 3.15.2 |
0416eb1f4505 |
Go 源码模块 |
五个项目统一使用 Go 1.27.3 构建。Server、Console 与 mcli 选用 silo-pkg v3.15.2 以及固定的上游提交 minio-go v7.4.2-0.20261025165926-320af050c445(伪版本,上游尚未打 v7.4.2 标签)。Server 显式集成已发布的 Console 与 mcli 源码;单独升级独立部署的 Console 不会替换旧版 Server 内嵌的控制台界面。详见组件矩阵与下载页。
Server:自 20261018 以来的修改
- LDAP 与 IAM(#250): 修复规范化 LDAP DN 过长导致无法登录的问题。当合法 IAM 键的单个 ASCII 路径分量超过 255 字节时,可选 IAM 记录读取将其视为“记录不存在”并继续按组策略登录;但无法读取的吊销记录与底层存储故障仍严格按 Fail-Closed 拒绝,且对象后端仍不支持直接写入超长路径记录。此外,策略重载在访问底层存储期间不再持有认证缓存锁,仅在完整加载成功后原子替换缓存并保持 IAM 写入顺序;请求取消信号会传递至 KMS 与 SSE-S3 解密路径,同时不缩短调用方的策略查询超时。
- 内置策略 Reset 与实时桶清单: 对内置策略执行 Reset 后,首次读取即可立即恢复原生策略定义;延迟到达的 peer/etcd 通知会重新加载已提交状态,不会覆盖后续新修改。策略在用检查、删除修订号与自定义策略删除行为保持不变。Console 的
account-info接口改为读取实时存储桶清单,创建或删除桶后刷新页面即可看到最新结果(对象用量统计仍由后台扫描器异步更新)。 - 多池删除保护(#257、#256): 普通删除与批量删除改为先清理非权威池中的旧副本,再删除权威池副本,从而在部分失败时保住最新权威副本;同时为新建删除标记选择可用存储池,并保护仍被其他存活副本引用的远端分层对象。
- 版本桶生命周期过期(#253、#252): 当生命周期过期规则只是追加删除标记时,完整保留上一版本的远端分层数据(包括暂停版本控制桶中的非
null版本);只有当历史版本被真正永久清除、且没有任何存活引用依赖其底层载荷时,才回收远端分层数据。 - 分片上传复制(#255、#254): 为复合 CRC 分片对象复制透传
FULL_OBJECT校验和类型,避免目标站点因按分片复合模式重算校验和而返回BadDigest。 - 存储 RPC 与超时语义: 转发存储 RPC 删除选项(包括覆盖写回滚所需的旧数据目录),并保持既有的磁盘/RPC 超时、请求取消、对象锁、读仲裁与自愈策略。正式版在
dcc2f20ba中撤回了 20261025 草稿里的已接纳 I/O 排空等待与逐对象变更锁方案(含 #258),详见多池对象一致性设计记录。 - 依赖、打包与交付: 更新 SFTP、etcd、NATS 及云厂商 SDK 等 Go 依赖;保留 Kafka 2.1 默认协议版本、CLI 输出格式与 NetBSD 兼容版本;修复旧版 DARE v1 解封逻辑(新写入继续使用 v2)。容器镜像、校验安装脚本与 Helm 客户端任务统一内置 mcli 20261026。Windows 归档改用 ZIP 格式,静态构建
curl升级至8.23.0并附带下文的证书信任配置说明;同时修复了最终刷新 SBOM 与构建溯源时的 RPM 签名校验。 - 文档与迁移: 合入单节点 MinIO 迁移指南(#228),校准运维默认参数说明,并将升级流程统一收敛至迁移指南。
本版完整保留 20261018 已交付的 Object Lock、IAM 授权、持久 STS 吊销、跨池迁移与 LIST 恢复修复。文末的依赖安全清单将本轮新合入的修复、历史修复与未使用代码中的扫描告警分别列出。
mcli:自 20261018 以来的修改
- 客户端身份缓存隔离(#50、#55): S3 与管理客户端缓存按凭据、证书信任、代理、DNS 解析器及自定义请求头隔离,同时保留凭据自动刷新与 Web Identity token 文件轮换。
- 复制 Resync 状态与速率计算(#48、#49、#52):
admin replicate resync status --json会持续消费状态流直至到达Completed、Failed或Canceled终态,完整保留已完成任务的状态输出;当桶未启用复制时明确输出结果,TTY 模式在遇到Failed或Canceled时立即结束等待;同时修复了累计传输超过约 8.6 GiB 后吞吐量计算的整数溢出。 - 诚实的退出码(#51):
resync start与resync cancel在部分桶操作失败时保留逐桶错误详情并返回非零退出码;用resync status成功查询到一个已处于Failed或Canceled状态的任务仍正常退出0。admin info --json在请求失败时同样返回非零退出码,并保留 JSON 错误输出。 - 批处理状态观察(#53、#54):
batch status在实时指标暂缺时继续观察并输出新增的pending状态(不再把排队中或缺样本的任务误判为已完成),在指标流中断时通过带超时边界的持久化状态查询兜底,并修复了超大对象计数下的 IOPs 整数溢出。 - 别名区域配置(#44): 支持按
MC_REGION、AWS_REGION、持久别名配置中的region字段、自动发现的优先级解析区域,并在客户端缓存中隔离签名区域(未新增alias set --region命令行参数)。 - 底层 SDK 修复: 拒绝被截短的顺序或并行分片读取流;修复
ReadAt的 EOF 处理、负偏移校验及Stat之后的读取/Seek 边界;对批量删除回退路径中的重复错误去重;移除桶复制配置时同时接受 HTTP200与204(403等真实鉴权或请求错误仍正常报错)。 - 打包与帮助信息(#45): 升级至 Go 1.27.3 与 GoReleaser 2.19.0,Windows 归档改用 ZIP 格式;更新命令行帮助链接以及已停用的服务端自更新/SUBNET 命令提示,保留全部既有 CLI 配置与
MC_*环境变量兼容。
自动化脚本请适配 batch status 新增的 pending 状态,以及 resync start/cancel 部分失败时的非零退出码。本次客户端升级无需变更服务端协议。下载流中途断开仍会立即报错;分片上传被 SIGINT 中断时以退出码 130 退出,未完成的分片可能需显式清理。详见完整客户端提交历史。
KES:自 20261018 以来的修改
KES 20261026 汇总了 Go 1.27.3 与云厂商 SDK 依赖维护,将二进制、Linux 软件包与容器镜像统一对齐到 20261026 批次。HTTP API、配置文件格式与后端存储密钥格式保持完全兼容。
| 依赖 | 20261018 | 20261026 |
|---|---|---|
| Go | 1.27.2 | 1.27.3 |
| AWS SDK v2 core | 1.47.3 | 1.47.4 |
| AWS config / credentials | 1.33.9 / 1.20.9 | 1.33.10 / 1.20.10 |
| AWS Secrets Manager | 1.50.4 | 1.50.6 |
| Google Secret Manager | 1.22.0 | 1.23.0 |
| Google API / IAM | 0.304.0 / 1.14.0 | 0.308.0 / 1.15.0 |
| Google certificate proxy / GAX | 0.3.23 / 2.26.2 | 0.3.24 / 2.27.0 |
| go-rootcerts / procfs | 1.0.2 / 0.22.0 | 1.1.0 / 0.23.0 |
全套 25 项模块更新还包含 AWS 配套模块与 Google 生成的 API 库;终端输出与 YAML 解析继续固定在 Lip Gloss v1 与 gopkg.in/yaml.v3。构建工具升级至 GoReleaser 2.19.0(nFPM 保持 2.48.0);Linux 软件包仅安装 /usr/local/bin/kes 可执行文件,不会自动启动未配置的服务。
兼容性回归测试覆盖了 OpenBao KV v2 与本地 Moto Secrets Manager 协议夹具,验证了升级前后写入的加密对象读取、版本回滚以及 Server 冷重启解密。生产环境升级时请保留持久化根密钥、证书与配置,并在重启 Server 后实际执行读取解密验证。详见 KES 完整提交历史。
Console 2.5 与 silo-pkg 3.15
Console 2.5.1 包含了 2.5 系列的整体界面重构、按权限裁剪导航、Overview 集群概览、对象预览、Tasks 任务中心、身份管理以及高延迟网络下的诊断流修复;2.5.1 补丁版进一步修复了启停用户组时保留既有成员、OIDC 字符串数组组权限、反向代理后的安全会话 Cookie、准确的凭据 JSON 导出、流式 ZIP 错误状态码以及键盘焦点与无障碍标签。Server 20261026 已直接内嵌此版本。
silo-pkg 3.15.2 汇总了 3.15.0 的 Go 1.27.3 与依赖升级、3.15.1 的上游 SDK 修复,以及 3.15.2 移除复制配置时的 HTTP 204 状态码兼容,同时完整保留既有策略语义与 3.14.3 的策略匹配性能优化。silo-pkg 仅作为 Go 源码模块发布,嵌入方需重新编译以纳入更新。
升级与故障边界
- 协调升级: 升级前请备份 IAM 状态、配置文件与加密密钥,并按 IAM 升级指南同步升级集群内的所有 Server 节点与跨站复制站点。不支持新旧版本进程长期共用同一 IAM 后端或执行滚动降级。
- 升级后核验: 逐一验证 LDAP/OIDC 登录、内置策略 Reset、存储桶清单刷新、多版本读取、跨站复制与加密对象解密。分片对象
FULL_OBJECT校验和复制修复需要先升级发送端 Server,再检查待复制队列。 - 归档格式与脚本适配: Windows 平台归档已改为
.zip(Linux 与 macOS 保持.tar.gz);自动化脚本请适配mcli batch status的pending状态与resync start/cancel部分失败时的非零退出码。既有环境变量、配置文件名与磁盘存储格式保持不变。 - 已知功能边界: 公开的
ListMultipartUploads仍使用节点本地内存缓存与精确对象键查找,已退役的strict开关会被忽略并打印警告;#79 与 #217 尚未关闭,Webhook 热重载 PR #249 未纳入本版,更大范围的性能问题仍在 #251 中跟踪。
存储超时与一致性边界: 客户端收到请求超时并不代表底层磁盘或 RPC I/O 已经停止,也不代表该次写入一定没有提交。在部分磁盘故障、锁租约过期或网络分区下,仍可能出现迟到提交、延迟回滚或短暂读到旧值与旧标签。本版未引入分布式锁 fencing,也不会自动恢复升级前已经损坏或丢失的对象、远端分层数据与元数据。
下载与验证
各平台的二进制文件名、SHA-256 校验和、Linux 软件包与验证说明见下载页面。版本化容器镜像可直接拉取:
- Server 标准镜像(Linux
amd64/arm64多架构 manifest):sha256:7bb2aff6b89efe1cb1303c10fc21d579447434ed06649ac9ec05a5e2dbf30ad7(与latest一致) - Server distroless 镜像(Linux
amd64/arm64多架构 manifest):sha256:e6544a902f426f2b4e775b89f3c1cd78310dbffc262d1ed82e9800c1cb1b5885(与distroless标签一致,两个架构均保留silo healthcheck ready原生健康检查,见 Server 镜像构建流水线)
各组件的发布制品均通过固定源码提交、归档校验和、软件包签名与构建溯源(Provenance)独立标识:
- Server 制品验收: 核验了对应源码
c3ad836aed0d的 36 项发布资产与 34 项构建溯源证明(含 6 个平台归档与 6 个 Linux 软件包),两个架构的 RPM 包均已完成 GPG 签名,校验清单、SBOM 与溯源证明同最终软件包完全一致(见 Go CI、VulnCheck、Release 与 Finalize 流水线)。 - 本地多节点与故障注入验收: 在 Linux
arm64环境下完成了基线四节点 88 项、升级后四节点 88 项与八节点多池 136 项 S3 兼容性检查;历史对象、标签、加密对象及跨升级周期的分片上传均完整保留。在滚动重启、SIGKILL强杀与 75 秒进程挂起恢复测试中,408 个已确认写入的对象全部完整读回,哈希与列表校验全部通过;原生可信 TLS 下的mcli测试套件与 16 项持久化检查同样全部通过。注意集群健康检查端点仅反映节点上报的磁盘仲裁状态,在滚动重启或升级后恢复流量前,请按启动就绪窗口指南验证实际数据面读写。 - KES 制品与集成验收: 核验了 19 项公开资产、11 项构建溯源证明及两个签名 RPM 包。使用实际构建的 Darwin
arm64KES 二进制,先后搭配 SILO 20261018 与最终版 Server/mcli 20261026 Linuxarm64二进制完成了 OpenBao KV v2 与 Moto 升级、回滚及 Server 冷重启测试。两个架构的 KES 容器镜像内置二进制与发布归档一致,多架构镜像摘要为sha256:ea36fcdd260c606eb89e693b0949aea73b149359605273a98fcf13c8433049cd(见 KES 制品流水线与镜像流水线)。
贡献者与完整历史
感谢 Denis Babchuk / @botdeniska 贡献生命周期、复制与多池删除修复,@910patin 修复长 DN LDAP 登录,Azat / @azataiot 定位并复现高延迟健康报告截断问题,@MikeVL 报告 resync 速率溢出与 JSON 状态输出问题,@mrjavadseydi 贡献别名区域配置支持并提出 Webhook 热重载方案,Gerald Combs / @geraldcombs 提出 Windows ZIP 归档建议,@yupoet 贡献单节点迁移指南,以及 @GhaziTriki、@devTeam-AiReg 与 @sargarass 报告的问题与反馈。
下表汇总了本发布周期内五个组件仓库中合并、采纳或跟踪的社区 Issue 与 PR:
| 项目 | 贡献者 | Issue / PR 记录 | 说明 |
|---|---|---|---|
| SILO | @botdeniska | #252、#253;#254、#255;#256、#257;#245、#248 | 修复分层对象生命周期过期、分片 FULL_OBJECT 复制校验和与多池删除安全性;#248 的跨池迁移修复已由 60c7179dd 采纳并保留原作者署名。 |
| SILO | @910patin | #250 | 修复长 DN LDAP 用户登录失败问题。 |
| SILO | @yupoet | #228 | 贡献经过生产验证的单节点迁移指南。 |
| SILO | @mrjavadseydi | #249 | Webhook 热重载提案(评审中,未合入本版)。 |
| SILO | @sargarass | #79 | 分片上传列表语义反馈(待后续版本处理)。 |
| SILO | @GhaziTriki | #251 | 性能问题反馈(排查跟踪中)。 |
| SILO | @devTeam-AiReg | #247 | 发行版可用性反馈。 |
| SILO | @Vonng | #217、#258 | 跨站复制边界说明(#217)与候选锁隔离实验(#258,最终版本已回退该变更)。 |
| mcli | @mrjavadseydi | #44 | 支持在 alias 配置中持久化自定义 S3 区域。 |
| mcli | @MikeVL | #48、#49 | 报告复制 resync 速率溢出与 --json 空输出问题(已在本版修复)。 |
| mcli | @geraldcombs | #45 | 提出 Windows 发行归档采用 .zip 打包的建议(已采纳)。 |
| mcli | @Vonng | #50–#55 | 客户端身份切换隔离与复制 resync 状态修复。 |
| Console | @azataiot | #63 | 报告并协助复现高延迟健康报告截断问题(已在 Console 2.5.1 修复)。 |
| Console | @Vonng | #64–#69 | Console 2.5.1 的依赖升级、界面改进、端到端验收与发版维护。 |
| silo-pkg | @botdeniska | #11 | 策略求值快速路径优化。 |
| KES | @Vonng | 20261018–20261026 发布周期维护 | 依赖刷新、打包构建与 OpenBao / Moto 兼容性验收。 |
社区贡献者名册收录了所有参与过 Issue 或 PR 的社区成员。各仓库的完整提交对比:Server、mcli、KES、Console、pkg。
以下为 10 月 22—25 日的依赖与安全审计记录(多个组件共用的依赖按对应软件包合并列出):
10 月 24 日追加的 Go 依赖更新
Go 工具链维持 1.27.3。相对 10 月 22 日的候选依赖,本轮纳入 26 个新发布的第三方模块版本,并同步升级 Arrow 与 codescan,共更新 28 个模块:
| 依赖 | 本轮版本变化 | 涉及组件 |
|---|---|---|
| pkg/sftp | 1.13.11 → 1.13.12 | SILO |
| etcd 的 api/v3、client/pkg/v3、client/v3 | 3.7.2 → 3.7.3 | silo-pkg、mcli、Console、SILO |
| JWX | 3.3.0 → 3.4.0 | silo-pkg、mcli、Console、SILO |
| nats.go | 1.54.0 → 1.55.0 | SILO |
| procfs | 0.22.0 → 0.23.0 | mcli、Console、SILO、KES |
| AWS SDK v2,共 14 个模块 | core 1.47.3 → 1.47.4;config 1.33.9 → 1.33.10;credentials 1.20.9 → 1.20.10;Secrets Manager 1.50.5 → 1.50.6,以及对应配套模块 | KES |
| GCP IAM / Monitoring / Secret Manager / Google API | IAM 1.14.0 → 1.15.0;Monitoring 1.31.0 → 1.32.0;Secret Manager 1.22.0 → 1.23.0;Google API 0.307.0 → 0.308.0 | IAM 与 Google API:SILO、KES;Monitoring:SILO;Secret Manager:KES |
| go-rootcerts | 1.0.2 → 1.1.0 | KES |
| Arrow | 18.7.0 → 18.8.0 | SILO 的 Azure SDK 间接依赖 |
| codescan | 0.36.4 → 0.36.6 | Console 生成工具链 |
本轮更新保持既有公共 API 与输出格式不变;各组件最终锁定的模块版本见上文组件清单。
已纳入的运行时安全修复
Go 与证书信任
CVE-2026-111943 / GO-2026-6809:Go 1.27.3 在 crypto/x509 证书链校验中直接拒绝已知失信的中间证书,在操作系统信任库尚未更新时也能提供兜底拦截。五个主项目及全部独立调试工具均统一使用 Go 1.27.3 编译。
此外,SILO、mcli 与 KES 的 UBI 容器信任库已应用 Red Hat RHSB-2026-012 的根证书封禁列表。由于根级封禁会一并拒绝挂靠在这些根证书之下的所有证书链,其拦截范围比 Go 1.27.3 的中间证书黑名单更广;若外部服务仍使用受影响根证书签发的证书链,需先行更换证书。发行版 CA 软件包的跟进状态见下文本地缓解。
SFTP 依赖安全加固
pkg/sftp 1.13.12 修复了 10 月 23 日公布的三项安全问题。截至本次核对,它们均没有 CVE 编号,以下按 GHSA 单独记录,不计作新增 CVE:
| 公告 | 上游问题 | SILO 适用性 |
|---|---|---|
| GHSA-xgcg-wgmj-5rw3,Medium | Client.RemoveAll 跟随顶层符号链接,可能删除目标目录内容 |
SILO 服务端未调用该客户端 API |
| GHSA-47hq-m6q9-3rm6,Medium | sftp.Server 的 ReadOnly 模式允许创建硬链接 |
SILO 使用 NewRequestServer 与自有 driver,未使用该只读 Server API |
| GHSA-h959-g3h6-w76c,High | ReadOnly 模式允许截断或新建文件 | 同上 |
上游后两条公告的受影响版本区间(affected range)与修复版本字段存在矛盾,本次直接升级至包含实际代码修复的 1.13.12 并通过回归测试验证(当前 Go 漏洞库快照停留在 10 月 21 日,尚未收录这三条 10 月 23 日发布的公告)。
静态 curl 及其链接库
SILO 容器镜像内置的静态 curl 从 8.22.0 升级至 8.23.0(启用 HTTP/2、SSH 与 Brotli,TLS 后端采用 OpenSSL)。下表完整列出 curl 8.22.0 官方漏洞汇总中的 21 个 CVE 及其在当前静态构建中的适用情况:
| CVE | 问题 / 适用性 |
|---|---|
| CVE-2026-92392 | HTTP/2 上传释放后使用(UAF) |
| CVE-2026-107929, CVE-2026-94266, CVE-2026-94265, CVE-2026-86413, CVE-2026-86414, CVE-2026-86415, CVE-2026-87861 | 连接复用、凭据或认证边界处理缺陷 |
| CVE-2026-92386, CVE-2026-86412, CVE-2026-87862, CVE-2026-87863 | Cookie 与 HSTS 状态污染 |
| CVE-2026-92387, CVE-2026-92388, CVE-2026-92389, CVE-2026-92390, CVE-2026-92391 | 循环处理、FTP/TFTP、下载文件名及 MIME 递归解析 |
| CVE-2026-86410, CVE-2026-87865 | SSH 主机校验及 known_hosts 回调 |
| CVE-2026-107928, CVE-2026-87866 | 仅影响 GnuTLS / wolfSSL 后端;当前 OpenSSL 构建不使用这两类后端 |
静态链接的 Alpine 底层库同步升级至以下回补版本(-rN 代表含安全回补的 Alpine 修订号):
| 库 | 本次版本变化 | CVE |
|---|---|---|
| Brotli | 1.2.0-r1 → 1.2.1-r0 | CVE-2026-111497 |
| musl | 1.2.6-r2 → 1.2.6-r3 | CVE-2026-107891 |
| libssh2 | 1.11.1-r3 → 1.11.1-r4 | CVE-2025-15661, CVE-2026-58050, CVE-2026-58051, CVE-2026-66032, CVE-2026-66033, CVE-2026-66034, CVE-2026-66035 |
此前发布的 SILO arm64 镜像静态库清单已包含 OpenSSL 3.5.9-r0、nghttp2 1.70.0-r0(CVE-2026-58055)与 zlib 1.3.2-r1(CVE-2026-85091);本次在构建脚本中显式锁定上述最低安全版本并完成双架构验证。Alpine 修复修订详见官方安全元数据。
构建与开发工具安全修复
本节记录 SILO Console 前端资源构建、代码生成与测试环境(生产环境运行的是编译后的 Go 服务端二进制),以及仓库内独立的 Go 调试模块。
Node 24.22.1
构建环境的 Node.js 从 24.22.0 升级至 24.22.1。下表列出 Node.js 2026 年 10 月安全公告中适用于 Node 24.x 的 8 个 CVE(不含仅影响 Node 26 的条目):
| CVE | 修复内容 |
|---|---|
| CVE-2026-105482 | DNS 名称中的 NUL 字节截断 |
| CVE-2026-105483, CVE-2026-106069, CVE-2026-106072 | 非规范 IP 地址导致 TLS 主机名校验绕过 |
| CVE-2026-111497 | Brotli 解码越界写(Node 已回补修复,内置版本字符串仍显示 1.2.0) |
| CVE-2026-105481 | HTTP keep-alive 接受请求前的响应数据 |
| CVE-2026-106074 | 启动快照重复使用随机数缓存 |
| CVE-2026-106073 | fs.realpathSync 权限模型绕过 |
Node 24.22.1 内置的 Undici 从 7.29.1 升至 7.30.1,包含以下 8 项修复(详见 Undici v7.30.1 发布说明):
| CVE | 修复内容 |
|---|---|
| CVE-2026-87018, CVE-2026-109383 | TLS 重协商崩溃、Agent 丢失自定义验证回调 |
| CVE-2026-109829, CVE-2026-109841 | 跨源缓存污染 / 数据泄露及 SRI 校验绕过 |
| CVE-2026-109869, CVE-2026-87029, CVE-2026-109924, CVE-2026-109932 | 内容解码、EventSource 和 WebSocket 的拒绝服务 |
Node 24.22.1 内置的 OpenSSL 从 3.5.8 升至 3.5.9(旧 Node 24.22.0 仍停留在 3.5.8),涵盖 DTLS、QUIC、CRL、CMP、EC / SM2 与握手内存安全方面的 13 项修复:CVE-2026-84782, CVE-2026-35189, CVE-2026-35191, CVE-2026-42772, CVE-2026-54872, CVE-2026-54873, CVE-2026-54875, CVE-2026-72897, CVE-2026-75804, CVE-2026-75805, CVE-2026-75806, CVE-2026-77696, CVE-2026-84784。
Node 24.22.1 内置的 c-ares 从 1.34.8 升至 1.34.9,修复了 11 条尚未分配独立 CVE 编号的上游 GHSA 公告(其中 GHSA-wpr3-8q3r-4q8c 补齐了此前 CVE-2026-33630 修复遗漏的连接关闭路径,上游仍标为 No known CVE):
| 公告 | 修复内容 |
|---|---|
| GHSA-wpr3-8q3r-4q8c | 连接失败后取消查询时的内存破坏 |
| GHSA-fqh5-3x7m-wp44 | 接受来自错误 DNS 服务器的响应 |
| GHSA-97vq-4mxv-7vhm | 关闭失败连接后查询对象的释放后使用 |
| GHSA-rf6g-ww74-97qh | 取消 / 关闭回调中的释放后使用 |
| GHSA-mw23-pfg6-2x9r | socket 状态回调后的释放后使用 |
| GHSA-v33j-65h4-4ch8 | 服务器状态回调取消查询时的释放后使用 |
| GHSA-pj7p-v3cw-hq66 | 回调更换 DNS 服务器时的释放后使用 |
| GHSA-grv7-fq5q-9vfc | 读取缓存响应时的释放后使用 |
| GHSA-ph6c-3cvx-mq6v | 并发复制选项 / 修改服务器时的缓冲区溢出 |
| GHSA-cfcv-8v2j-qj6r | 带前缀长度的 IPv6 地址暴露未初始化内存 |
| GHSA-wrgc-prmw-27xh | 缓存错误复用不同 EDNS 选项的响应 |
前端依赖与代码生成器
| 依赖 | CVE / GHSA | 修复内容 |
|---|---|---|
| fast-uri 3.1.7 → 3.1.9 | CVE-2026-86472 | 编码主机名大小写规范化不一致 |
| ip-address 10.4.0 → 10.7.4 | CVE-2026-101913 | 链路本地 IPv6 分类错误 |
| ip-address 10.4.0 → 10.7.4 | CVE-2026-101910 | 遗漏 NAT64 本地使用网段 |
| ip-address 10.4.0 → 10.7.4 | CVE-2026-101912 | 混合地址族的子网检查绕过 |
| ip-address 10.4.0 → 10.7.4 | CVE-2026-101911 | 超长地址错误诊断导致资源耗尽 |
| moment 2.30.1 → 2.31.0 | CVE-2026-17495 | 非字符串 locale 参数路径穿越 |
| smol-toml 1.8.0 → 1.9.1 | GHSA-r4xh-jqrq-34v2 | TOML 解析二次复杂度 |
| vite 8.0.16 → 8.3.5 | CVE-2026-112945 | 开发中间件跨源脚本执行 |
| vite 8.0.16 → 8.3.5 | CVE-2026-112946 | 开发服务器文件允许列表绕过 |
| vite 8.0.16 → 8.3.5 | CVE-2026-112943 | Windows 编辑器参数转义不足 |
| vite 8.0.16 → 8.3.5 | CVE-2026-112944 | 编辑器参数被解释为命令选项 |
| vite 8.0.16 → 8.3.5 | CVE-2026-112942 | Windows 编辑器路径检查绕过 |
此外,代码生成工具 go-swagger 从 0.33.2 升级至 0.36.6,修复 GHSA-8gmg-wf5j-hvf7 与 GHSA-rg22-m539-jwvf(不可信 OpenAPI 规范中的内容类型或枚举值在代码生成阶段可能触发代码注入,上游首次修复版本为 0.35.3,无独立 CVE 编号)。生成文件已与新版工具同步;生成流程显式保留经过审查的配置导入绑定器与 multipart 处理方式,并通过回归测试保留原有文件大小、文件名和表单编码行为。
独立 Go 调试模块
服务端仓库下的 inspect、s3-verify 与 xattr 三个独立调试模块此前落后于根模块版本。本次同步消除了 37 个带 CVE 编号的依赖版本告警及 1 个无 CVE 的 S2 公告:
| 依赖 | 受影响独立模块 | 最终版本 |
|---|---|---|
| golang.org/x/crypto | inspect、s3-verify | 0.58.0 |
| golang.org/x/net | s3-verify | 0.61.0 |
| golang.org/x/text | s3-verify | 0.43.0 |
| golang.org/x/sys | inspect、xattr | 0.49.0 |
| klauspost/compress | inspect、s3-verify | 1.20.3 |
下表列出对应的 Go 官方漏洞库条目与上游首次修复版本(OpenPGP 的无修复公告单列于下文其他残留项):
| CVE / 公告 | 依赖 | 首次修复 | 问题 |
|---|---|---|---|
| GO-2026-5841 | klauspost/compress | v1.18.7 | S2 越界读取(无 CVE 编号) |
| CVE-2026-39824 | x/sys | v0.44.0 | Windows Unicode 字符串整数溢出 |
| CVE-2025-47913 | x/crypto | v0.43.0 | SSH agent 拒绝服务 |
| CVE-2025-58181 | x/crypto | v0.45.0 | SSH 无界内存消耗 |
| CVE-2025-47914 | x/crypto | v0.45.0 | SSH agent 畸形约束拒绝服务 |
| CVE-2026-39833 | x/crypto | v0.52.0 | SSH agent 密钥约束未执行 |
| CVE-2026-39832 | x/crypto | v0.52.0 | SSH 密钥转发丢失约束 |
| CVE-2026-46597 | x/crypto | v0.52.0 | SSH 字节运算下溢及 panic |
| CVE-2026-39828 | x/crypto | v0.52.0 | SSH 证书限制绕过 |
| CVE-2026-39835 | x/crypto | v0.52.0 | SSH 主机密钥 / 认证回调 panic |
| CVE-2026-39827 | x/crypto | v0.52.0 | 拒绝 SSH channel 时内存泄漏 |
| CVE-2026-39830 | x/crypto | v0.52.0 | SSH 非预期响应导致死锁 |
| CVE-2026-39829 | x/crypto | v0.52.0 | 畸形 RSA / DSA 参数导致拒绝服务 |
| CVE-2026-39831 | x/crypto | v0.52.0 | FIDO / U2F 物理交互要求绕过 |
| CVE-2026-39834 | x/crypto | v0.52.0 | SSH 大 channel 写入无限循环 |
| CVE-2026-42508 | x/crypto | v0.52.0 | known_hosts 的 @revoked 未执行 |
| CVE-2026-46595 | x/crypto | v0.52.0 | VerifiedPublicKeyCallback 权限未执行 |
| CVE-2026-46598 | x/crypto | v0.52.0 | SSH agent 畸形输入导致 panic |
| CVE-2026-56854 | x/crypto | v0.55.0 | SSH 非公钥认证遗漏 source-address 约束 |
| CVE-2026-78662 | x/crypto | v0.56.0 | 未决 SSH channel 死锁 |
| CVE-2026-56855 | x/crypto | v0.56.0 | 已建立 SSH channel 死锁 |
| CVE-2025-47911 | x/net | v0.45.0 | HTML 解析二次复杂度 |
| CVE-2025-58190 | x/net | v0.45.0 | HTML 解析无限循环 |
| CVE-2026-33814 | x/net | v0.53.0 | HTTP/2 非法帧大小导致循环 |
| CVE-2026-42506 | x/net | v0.55.0 | HTML foreign content 命名空间处理错误 |
| CVE-2026-39821 | x/net | v0.55.0 | 未拒绝纯 ASCII 的 Punycode 标签 |
| CVE-2026-42502 | x/net | v0.55.0 | HTML foreign content 元素处理错误 |
| CVE-2026-25680 | x/net | v0.55.0 | 畸形 HTML 解析拒绝服务 |
| CVE-2026-25681 | x/net | v0.55.0 | DOCTYPE 字符引用处理错误 |
| CVE-2026-27136 | x/net | v0.55.0 | 重复 HTML 属性导致 XSS |
| CVE-2026-46600 | x/net | v0.56.0 | 畸形 SVCB / HTTPS DNS 记录导致 panic |
| CVE-2026-78659 | x/net | v0.60.0 | HTTP/2 Trailer 导致内存耗尽 |
| CVE-2026-78660 | x/net | v0.60.0 | HTTP/2 接受畸形帧相关头 |
| CVE-2026-78669 | x/net | v0.60.0 | HTTP/2 窗口反复变化导致 CPU 耗尽 |
| CVE-2026-78663 | x/net | v0.60.0 | HTTP/2 流控额度重复返还 |
| CVE-2026-97032 | x/net | v0.60.0 | HTTP/2 HPACK 编码器竞争导致崩溃 |
| CVE-2026-56852 | x/text | v0.39.0 | 非法文本输入导致无限循环 |
| CVE-2026-56851 | x/text | v0.41.0 | PRECIS 解析畸形输入导致 panic |
上游或发行版仍未解决的条目
截至 2026-10-23,以下条目在上游或所选操作系统发行版中尚无可用修复版本。我们保留原始扫描记录,并逐项说明已采取的本地缓解措施或运行时可达性边界。
已做本地缓解,等待上游发布
| 条目 | 上游 / 发行版状态 | 本次处理及剩余边界 |
|---|---|---|
| CVE-2026-93687 / braces | 最新 npm 版本仍为 3.0.3,上游尚未发布修复版本 | 对 [email protected] 应用本地 Yarn 补丁,将解析与 AST 遍历深度限制为 100(13 项回归测试通过)。该包仅位于前端构建/测试依赖图;纯版本号比对的扫描器仍会提示告警。待上游发布官方修复版并通过验证后移除本地补丁。 |
| CVE-2026-111943 / UBI CA | 验收时 UBI 9 仍提供 ca-certificates 2025.2.80_v9.0.305-91.el9,尚未包含最新信任变更 |
已在构建阶段执行 Red Hat 官方根证书封禁并校验生成的 PEM 文件;Go 1.27.3 与 Node 24.22.1 也各自内置了证书信任拦截。后续继续跟踪 UBI ca-certificates 包更新。 |
UBI 9.8 尚无适用发行版补丁的扫描记录
2026-10-22 对 SILO、mcli 与 KES 在 amd64 和 arm64 上的系统组件验收镜像(包含最终静态 curl 与 CA 证书库)进行了扫描:每个镜像均保留 24 条 RPM 记录,对应同一组 12 个唯一 CVE(15 条 Medium、9 条 Low,无 High / Critical,所有记录的 FixedVersion 均为空)。2026-10-23 复查 Red Hat 安全数据时,以下 RHEL 9 源包状态仍为 Affected 或 Fix deferred。
由于 RPM 扫描器按源包(SRPM)映射漏洞,部分仅存在于未安装命令行工具或其他 CPU 架构中的缺陷也会挂靠到基础运行库(如 libgcc、glibc)名下;下表逐一列出各条目的实际适用范围:
| CVE | 源包 | Red Hat 级别 | RHEL 9 状态 | 适用性 |
|---|---|---|---|---|
| CVE-2026-56391 | coreutils | Moderate | Fix deferred | uniq 多字节输入越界读,需特定命令行参数与输入触发 |
| CVE-2026-8674 | glibc | Moderate | Fix deferred | DNS resolver 处理超长搜索域时触发进程中止 |
| CVE-2026-86805 | glibc | Moderate | Affected | 动态加载器本地竞争,需满足本地 setuid、路径与硬链接前提 |
| CVE-2026-89092 | glibc | Moderate | Affected | nscd DNS 缓存守护进程缺陷;容器镜像未安装 nscd 包 |
| CVE-2026-95818 | glibc | Moderate | Affected | 动态加载器栈越界,需特定本地 setuid 与路径条件 |
| CVE-2026-97399 | glibc | Low | Affected | Power8 架构专用优化路径;发布镜像仅针对 amd64 / arm64 |
| CVE-2021-46195 | gcc | Low | Fix deferred | libiberty 符号解码器递归耗尽(Red Hat 公告中的 mingw-gcc 修复不适用于 libgcc 运行库) |
| CVE-2022-27943 | gcc | Low | Fix deferred | libiberty 缺陷;Red Hat 明确说明 libgcc / libstdc++ 不含受影响代码 |
| CVE-2026-95619 | gcc | Moderate | Affected | libstdc++ 对齐分配溢出,因源包归属映射为 libgcc 告警 |
| CVE-2026-102010 | gcc | Moderate | Affected | libstdc++ 可选 pb_ds 容器缺陷,因源包归属映射为 libgcc 告警 |
| CVE-2023-50495 | ncurses | Low | Fix deferred | tic 终端编译工具缺陷,不在 libncurses 运行库中 |
| CVE-2022-41409 | pcre2 | Low | Fix deferred | 仅影响 pcre2-tools 命令行工具;UBI 未安装该工具包 |
构建阶段与无 CVE 公告
- Alpine 构建阶段宿主包的
curl/libcurl仍为8.22.0-r0:截至 2026-10-23,Alpine 双架构包索引尚未推送8.23.0。该包仅在容器构建阶段用于下载固定 SHA-256 校验和的源码包,最终打入运行镜像的是从源码编译的静态curl 8.23.0。 - GO-2026-5932:
golang.org/x/crypto/openpgp已废弃且无上游修复版本(无 CVE 编号)。虽然golang.org/x/crypto仍在模块图中,但已核查的构建目标均未导入受影响的openpgp子包。
已有历史修复,不属于本次新增漏洞
按模块路径匹配的二进制扫描器仍会对 SILO 报告 CVE-2025-27414、CVE-2026-33322、CVE-2026-33419、CVE-2026-34204、CVE-2026-39414、CVE-2026-40344、CVE-2026-41145、CVE-2026-42600(因为 SILO 保留了 github.com/minio/minio 模块路径,而上游通告使用开放版本区间)。这八项缺陷在此前版本中均已修复并通过回归测试,详见 SFTP 公告、OIDC、LDAP、复制元数据、CSV、Snowball、签名校验 与 ReadMultiple。
兼容性与依赖回归证据
为避免已复现的终端表格输出变化、字符宽度计算差异及 NetBSD 交叉编译回归,本次固定保留 tablewriter 0.0.5、go-humanize 1.0.1、根模块 go-runewidth 0.0.29 及 go-systemd/v22 22.6.0(xattr 模块保留其既有宽度库组合)。此外:
- Kafka 通知目标在应用用户配置前显式保留协议版本默认值
2.1; - DARE 加密继续使用 32 字节密钥与 v2 写入格式,并修复旧 v1 解封缓冲区处理;
pgzip保留对缺失校验尾部返回unexpected EOF的完整性检查。
10 月 22 日至 23 日的候选构建(与回退基线均基于 Go 1.27.3,持久化验收在单节点四盘 Linux arm64 环境执行)已完成以下验证:
- 全量编译、适用的
-race与 lint 检查; - 加密对象在新旧依赖栈之间的互读与回滚验证;
- 服务重启、缺失分片自愈恢复与 CLI 格式化输出校验;
- Console 真实对象上传下载、ZIP 归档预览、WebSocket 会话及监控指标图表验证。
10 月 24 日追加升级后的候选源码另行完成以下验证:
- silo-pkg、mcli、KES 的全量 race 测试,Console 的 API / pkg / cmd race 测试,以及 SILO 的全量测试和 SFTP、IAM、Parquet 专项 race 测试;五个项目的 lint、模块校验与依赖整洁性检查通过。
- SFTP 自有驱动在 HTTP / HTTPS S3 后端上的对象读写、列表、删除、Unicode 文件名、传输块边界和只读权限保护;上游只读服务与符号链接删除回归测试通过。旧、新依赖均通过新增的对象操作测试。
- JWX 签名与时间声明边界对照通过;68 项 CLI 输出对照无新增差异,仅对既有元数据映射顺序做归一化。
- 本地 etcd 服务的 mTLS、账户认证、事务、watch、lease 和旧→新→旧客户端跨服务重启读取;NATS / STAN 的消息持久化、ACK、持久订阅游标及断线重连通过。
- Azure / GCS 本地协议夹具、KES GCP Secret Manager 操作与分页、Azure SDK 的 Arrow 解码测试、procfs 完整上游解析夹具测试通过。procfs 更新包含 bcache 单位及 NVMe 大小的解析修正,相关指标数值可能随之纠正。
- mcli、Console、SILO、KES 的 Darwin arm64 原生构建与 Linux amd64 交叉构建,以及 mcli、SILO 的 NetBSD amd64 交叉构建通过。
本轮五个项目的 Linux amd64 包级 Go 漏洞扫描未发现受影响的已导入包(仅余未导入受影响子包的模块级 GO-2026-5932 记录)。
2 - SILO 20261018 发布说明
Server 20261018 已正式发布,提供 amd64 与 arm64 版本化归档、原生软件包及 Docker Hub 标准/distroless 镜像。本版本接替 Server 20260916(20261015 保留为已撤回的历史草稿记录)。
| 身份 | 值 |
|---|---|
| 发行标签 | RELEASE.2026-10-18T00-00-00Z |
| 软件包版本 | 20261018000000.0.0 |
| 发行源码 | 0cd388c666f8211f552604ae73448a066e9c25ce |
| 上一正式版源码 | 2a4d51406b7ed87af5fe6fe0f801f3290f96eb3c(Server 20260916) |
| 完整变更对比 | 20260916 → 20261018 |
版本化归档、原生软件包及固定标签的容器拉取命令见下载页。
Object Lock 与 IAM 安全修复
SN-2026-015 / SN-2026-016 — Object Lock 保留期授权与原位覆写防护。 #234 与 #235 修复了保留期修改鉴权与原位覆写漏洞:
- 每次
PutObjectRetention请求在读取目标对象前,都会携带请求中的 Object Lock 条件键校验s3:PutObjectRetention。缩短、清空未到期的GOVERNANCE保留期或切换其模式时,调用方必须同时提供x-amz-bypass-governance-retention: true请求头并具备s3:BypassGovernanceRetention权限(不能替代基础s3:PutObjectRetention权限)。清空保留期时剩余天数按0计算;未到期的COMPLIANCE保留期不允许缩短或更改模式。 - 调用方显式指定写入
versionId时必须具备可信复制身份(s3:ReplicateObject)。目录对象的null版本和已持久化的分片上传目标会在对象写锁内重新校验锁状态;锁状态读取失败时按 fail-closed 拒绝写入,既有 Legal Hold 继续生效。请同步升级集群中所有写入节点及接收 S3 请求的复制站点。详见安全公告与修复设计。
SN-2026-017 — 管理凭据自助授权边界。 #242 使凭据自查询与清理严格遵守显式 Deny、会话策略收窄(sessionPolicy)及外部授权插件判定。在内置授权下,受限会话凭据无法创建或更新权限超出自身范围的服务账号,非 root 管理员也无法修改 root 派生的凭据;无限制空策略继承与损坏的非 root 密钥清理保持支持。后续提交 995439260 将批量自查询别名归一到父身份,并保留无附加策略普通用户的自查询能力,无需新增 Admin action 或迁移 IAM 存储。详见安全笔记与授权契约。
按范围撤销 STS 令牌
0cd388c66 让 RevokeTokens 同时枚举持久化 STS 身份记录与节点内存缓存,即使某个节点此前漏掉了令牌签发通知,也能完整撤销目标令牌。即便批次中个别令牌写入墓碑失败,已提交的删除记录仍会广播给同集群节点与站点复制对端;离线站点在恢复后通过既有 IAM 删除自愈补齐。基于对象存储和 etcd 的缓存刷新也会在通知或 watch 遗漏后自动剔除已撤销令牌。
撤销范围仍为请求指定的父身份及可选令牌类型(覆盖请求集群在操作截点前的快照,不影响新签发的令牌、无关用户或父身份策略)。持久枚举仅增加管理端撤销命令的开销,不为日常请求鉴权增加网络查询。详见 STS 撤销设计与成本。
重平衡与池下线一致性
60c7179dd(含 #248)与 1748f62c7 防止 rebalance 或池下线(decommission)搬迁旧副本时覆盖其他存储池中的最新副本。搬迁流程会在共享对象锁内复核源版本(包含分片完成与分层对象元数据),保留 null 与 UUID 删除标记,并仅清理已确认搬迁完成的版本,不再粗暴删除整个源前缀。若期间发生并发写入、删除或目标池变化,清理会安全中止并留待重试。
退役旧存储池前,请按多池对象一致性设计核验对象版本、标签和删除标记状态(跨站点删除标记的独立边界仍由 #217 跟踪)。
普通对象列表恢复
#239(含原 #221 工作,关闭 #218)修复了在符合恢复条件的元数据分歧下,ListObjects / ListObjectsV2 成功返回却遗漏可读对象 key 的问题。多池合并层会在对象读锁内复核存在分歧的同名条目组:返回当前可读元数据、略过已确认不存在的对象,或在无法确认时返回 503 SlowDownRead 等明确错误。分页生产者出错会终止整次扫描;客户端应消费所有分页并将任一分页错误视为不完整列表。
常规无分歧条目继续走原有的无锁快速路径。锁内复核仅针对符合条件的最新对象组,不降低读仲裁要求,也不新增持久化元数据;请求取消可随时中断锁重试等待,遇到恢复锁冲突时仅执行一次有界短等待。后续提交 3dd53eb81 与 2080b3d03 确保当同名碰撞对象被确认为不存在时,同名目录或公共前缀(CommonPrefixes)仍被完整保留。实测延迟与锁开销见列表恢复锁成本记录。
分片上传列举与清理
回退默认磁盘扫描,恢复 Legacy 内存列举。 #243 在 10 月 17 日引入的默认磁盘扫描已由 4733e1423 撤回。公开 ListMultipartUploads 在空 prefix 时查询节点本地内存缓存,在非空 prefix 时按精确对象 key 查找;进程重启或请求落到其他节点可能遗漏未完成上传(跨池持久化列举仍在 #79 中跟踪)。
与 20260916 相比,环境变量 MINIO_API_MULTIPART_LISTING=strict 已停用:设置该变量会在启动时输出警告并被忽略(旧共享配置键 api multipart_listing 同样被容忍忽略)。但 20260916 引入的上传创建身份元数据、UploadID 路径校验、取消目标匹配检查以及成功取消后的缓存/对端清理通知均得以保留。只读管理诊断接口 multipart-preflight 仍要求 admin:StorageInfo 权限并返回 mode=legacy,其扫描条目数、超时与并发上限仅作用于显式管理诊断。详见分片列举设计、回退原因与容量基准及配置参考。
后台过期分片清理(默认 24 小时过期、每 6 小时巡检一次)包含两项修复:
- #236:优先解析原生上传目录名中的时间戳,再回退尝试 Base64 兼容路径,消除无谓的磁盘元数据读取。
0f9199e0c:删除过期上传子目录后,立即清理变空的父目录,不再因删除子目录刷新了父目录mtime而多等一轮 24 小时过期周期(非空父目录与活跃上传不受影响)。
错误分类、元数据复用与其他修复
| 改动 | 用户可见效果 |
|---|---|
| #232:提交暂存元数据丢失分类 | 当 PUT 或分片合并在最终提交阶段找不到暂存元数据时,返回可重试的 503 SlowDownWrite,不再误报为 IncompleteBody 或 NoSuchKey;存储 RPC 与 healing 同步保留该错误分类。 |
| #233:元数据与扫描消息结构体复用 | 解码旧格式 xl.meta 时清空未携带的 EcM / Signature 残留值,并在构建扫描响应时清理互斥的 update/final 字段(见结构体复用修复设计)。 |
| #225、#229、#238:校验和错误文案 | 对齐 AWS S3 的 Content-MD5 大小写与算法名错误文案;PUT / UploadPart 已知算法不匹配时指明具体算法名,未知算法保留通用提示。 |
| #238:内嵌 Console 错误解包 | 保留被多层包装的底层 S3 错误码;当 Object Lock 阻止暂停桶版本控制时,准确向前端返回 InvalidBucketState。 |
| #220:Lambda 目标集合判空 | 修正写反的 TargetIDSet.IsEmpty 布尔返回值。 |
| 纠删码文档修正 | 按单个纠删集合(Erasure Set)和对象实际布局说明校验块与容错盘数(见存储类参考)。 |
配套组件与依赖
| 组件 | 选定版本 |
|---|---|
| 内嵌 Console | v2.4.2(v0.0.0-20261017112417-ef2dd2c41d21) |
| MC 模块/镜像内置 mcli | 20261018(v0.0.0-20261017101407-fa3b8bf72458) |
| Server 共享包 | github.com/pgsty/silo-pkg/v3 v3.14.3 |
| 上游 S3 SDK | github.com/minio/minio-go/v7 v7.4.1 |
| Go 工具链 | 1.27.2 |
| 可选外部密钥服务 | PGSTY KES 20261018(独立服务,源码 2f7e741db905) |
独立发布的 Console v2.4.2 与 mcli 20261018 依赖 silo-pkg v3.14.2;Server 主模块升级至 v3.14.3(优化管理 action 分类性能,授权语义不变),并显式 require 上述 Console 与 MC 版本。
minio-go v7.4.1 包含上传失败时的取消清理、UTC 保留期时间戳及 STS 时长透传。核心依赖更新包括 go-jose v4.1.6、ldap v3.4.15、compress v1.20.3、msgp v1.6.5、etcd v3.7.2 与 golang.org/x/*。注意:升级后的 go-jose v4.1.6 会拒绝超过 4096 位的 OIDC/JWK RSA 密钥,使用超长 RSA 密钥的部署在升级前须先核验 OIDC discovery、JWKS 与登录链路(详见依赖安全说明)。
发行流水线固定使用 GoReleaser v2.18.3、nFPM v2.48.0、golangci-lint v2.15.0 与 govulncheck v1.9.0,并将 Object Lock 竞态回归设为发版前置门禁。make rebrand-guard 改用 git grep 扫描源码并显式报告读取错误,不再依赖外部 ripgrep(7007c164a)。注意仓库内置的 Helm Chart 默认镜像标签仍为 20260916,通过 Helm 部署本版本时请显式覆盖为 RELEASE.2026-10-18T00-00-00Z。
升级与回滚要点
- 备份状态与固定制品:记录当前运行版本并固定目标二进制或镜像 digest;按迁移指南与 IAM 恢复流程完整备份 IAM 存储、配置与加密材料(常规在线 IAM 导出不包含撤销墓碑历史)。
- 全集群同步切换:协调升级所有 Server 节点与接收写入的复制站点,切勿在同一 IAM 后端混跑新旧二进制或执行跨版本滚动降级。
- 核对 Object Lock 与服务账号权限:使用业务实际凭据验证保留期修改、Legal Hold、服务账号创建/更新、自助操作显式
Deny以及 root 凭据管理。此前因策略格式受损而无法使用的到期密钥,应由授权父身份重新签发。 - 移除
strict分片列举依赖:若此前在 20260916 上启用了MINIO_API_MULTIPART_LISTING=strict,升级前请确保客户端自行维护待完成或待取消的bucket/key/UploadID,不要依赖公开列表进行全量发现或空间回收判断。 - 检查列表、重试与 OIDC/TLS 链路:验证普通与分页
LIST、PUT/分片完成对503 SlowDownWrite的重试、OIDC/JWKS 密钥长度及经过 TLS 检查设备的出站连接(参见 Go 1.27 TLS 与 OIDC 指南)。 - 回滚风险:降级回 20260916 会重新暴露本版修复的 Object Lock 与管理凭据授权缺陷,且升级本身不会自动恢复升级前已被覆写的对象版本或丢失的标签。
制品核验与验收记录
签名标签 RELEASE.2026-10-18T00-00-00Z 及全部 36 个发行制品均对应源码 0cd388c666f8211f552604ae73448a066e9c25ce,并通过了 Go CI、VulnCheck、Release 构建与软件包定稿工作流。
- 静态制品核验:核验全部下载摘要、6 个平台归档版本戳、6 个系统软件包(RPM/DEB/APK)载荷、34 份构建来源证明(attestation)、2 份 Sigstore 校验清单签名、2 份 RPM 签名与 12 份 SBOM。
- 本机功能与故障验收:在原生 Darwin 与 Linux 环境下完成 S3/IAM/STS/Object Lock、LDAP/OIDC、20260916 原地升级、桶复制与站点复制、含内嵌 Console 的三站点恢复、三站点及四进程共享集群 STS 撤销,以及 4 组真实多池迁移(2/3 池 × rebalance/decommission)。在 8 进程 2 池拓扑下,滚动重启负载完成 2,896 次全量扫描,故障恢复负载完成 1,270 次全量扫描,零漏项、零重复、零读取损坏;另有 3 组 Linux 软件包生命周期与 8 种容器运行变体全部通过(注:Windows 与 Darwin amd64 为静态核验,容器 amd64 运行于跨架构模拟环境)。
- Docker Hub 公开摘要:
- 标准镜像(及发布时的
latest):sha256:2636fc4155d9a7e41ff58cdb65ddd13ba9304e67184e13c25bc5cb34016269d7 - Distroless 镜像:
sha256:472f59c7be537571f0f9a2ee6b8fe033a220939d521255bd4bf5339e53db7218
- 标准镜像(及发布时的
感谢 szopi00 报告 Object Lock 问题;mr javad seydi(@mrjavadseydi)贡献原始 LIST 与分片工作;Julien Laurenceau(@julienlau)修复提交元数据分类与结构体复用问题;clown15 修复上传目录清理;cbornet 与 yupoet 改进校验和错误文案;AleksaMCode 修复 Lambda 目标集合判空;以及 Denis Babchuk(@botdeniska)贡献 #248 迁移防覆盖修复与 silo-pkg 性能优化。
3 - silo-pkg 3.14.3 发布
发行版: v3.14.3 · 源码: e9d585ba1e7a。依赖基线见 v3.14.2 发布说明。
github.com/pgsty/silo-pkg/v3 v3.14.3 优化了 IAM 策略判定期间识别 admin: 动作的开销,被 Server 20261018 选用。
AdminAction.IsValid 与 HasResource 现在优先执行精确查表,再按需扫描动作集合:不含通配符且未命中的字面量动作直接返回;前缀无法匹配 admin: 命名空间的通配符模式直接跳过合法性扫描,而 adm*、a*d*m*i*n* 等通配模式保持原有匹配语义不变。
性能与验证
在 Apple M5 Max(Go 1.27.2)上进行的 6 轮交替单核基准测试表明:在先遍历 100 条不匹配桶授权、最后命中目标授权的策略场景下,单次策略判定中位耗时从 303.2 µs 降至 54.4 µs(降低约 82%),且零新增堆内存分配。
验证覆盖 Go 1.26 与 1.27 race 测试、lint、LDAP 集成测试、漏洞扫描、60 秒等价性模糊测试(fuzzing),以及针对 50,000 份策略、970,020 次策略判定的新旧版本全量结果比对;使用 mcli 20261018 连接基于新旧包构建的 Server 结果完全一致。
采用方式
公开 API、策略格式、权限判定结果、外部依赖与 go 1.26 最低版本要求均无变化。Server 20261018 采用 v3.14.3,而独立发布的 mcli 20261018 与 Console v2.4.2 继续使用 v3.14.2(各组件依赖版本见组件矩阵)。
感谢 Denis Babchuk(@botdeniska) 提交 PR #11,以及 Klaus Post(@klauspost) 的原始优化工作。
4 - PGSTY KES 20261018 发布
发行版: RELEASE.2026-10-18T00-00-00Z · 软件包: 20261018000000.0.0 · 源码: 2f7e741db905。
这是 PGSTY 维护的密钥加密服务(Key Encryption Service,KES)首个正式发行版。KES 是独立部署的无状态服务,供需要外部 KMS 的 SILO 服务端加密场景使用(参见组件版本矩阵)。
变更内容
- 建立 PGSTY 维护与发布流水线,完整保留上游版权、署名及第三方许可证。可执行文件与系统软件包保持
kes命名,Go 模块路径保持github.com/minio/kes。 - 升级至 Go 1.27.2 并刷新依赖,将 AWS Secrets Manager 后端从已弃用的 AWS SDK for Go v1 迁移至 AWS SDK for Go v2。完整保留 YAML 配置字段、显式凭据优先级、自定义端点与密钥存储格式(继续忽略
~/.aws/config与 SDK 环境变量端点覆盖)。 - 完整兼容既有 KES HTTP API、
MINIO_KMS_KES_*环境变量、存量根密钥及已加密对象;现有 SILO + KES 部署可直接升级,无需迁移密钥。 - 新增 SILO 搭配 OpenBao KV v2 及 Moto Secrets Manager 模拟器的升级、回滚与重启集成测试(每次版本切换均强制重启 SILO 以排除服务端密钥缓存干扰)。
- 提供签名 Git 标签、GitHub 构建来源证明、GPG 签名 RPM 包与非 root 容器镜像;禁用内置
kes update自更新命令。
部署与升级
在服务端加密链路中,SILO 负责加解密对象数据,KES 负责验证客户端 mTLS 身份并封装/解封装数据加密密钥(DEK),OpenBao 负责持久化存储主密钥(KEK)。因此,MINIO_KMS_KES_ENDPOINT 必须指向 KES,而非直接指向 OpenBao(架构边界与故障恢复要求见 KES 与 OpenBao 设计说明)。
生产启动 KES 前须配置 TLS 证书、mTLS 客户端身份策略与持久化密钥后端(开发模式仅将密钥保存在内存中)。官方容器默认以非特权 UID/GID 1000:1000 运行,挂载的配置文件与证书须对该用户可读;Linux RPM/DEB/APK 软件包安装 /usr/local/bin/kes,不会自动拉起未配置的服务。
升级前请先备份底层密钥存储与配置文件;升级后验证存量加密对象解密、新加密对象写入,以及重启 KES 与 SILO 后的冷读能力。
交付与验证
全部 19 个发行附件(Linux/macOS/Windows 的 amd64/arm64 共 6 个平台压缩包、6 个 Linux RPM/DEB/APK 软件包、归档校验清单与 6 份软件包校验文件)均已核验,涵盖下载摘要、二进制源码/平台标记、软件包载荷、2 份 RPM 签名及 11 份 GitHub 构建来源证明(见发布工作流)。
官方多架构容器镜像 docker.io/pgsty/kes:RELEASE.2026-10-18T00-00-00Z(linux/amd64 与 linux/arm64,Docker 发布记录)的索引摘要为:
维护验收矩阵重点覆盖 SILO + PGSTY KES + OpenBao KV v2(含 mTLS 认证、OpenBao AppRole 访问、DEK 加解密、重启持久性、未认证请求拒绝,以及与 SILO 20260903/20260916 和上游 KES 2025-03-12T09-35-18Z 的互操作与回滚测试;AWS Secrets Manager 后端通过本地 Moto 模拟器完成协议与存储回归)。
5 - SILO Console 2.4.2 发布
版本: v2.4.2 · 源码: ef2dd2c41d21。
本版本作为独立 Console 发行版及 Server 20261018 的内嵌 Console 组件发布(参见 silo-pkg v3.14.2 发布说明)。
更新内容
- 升级至 mcli 20261018、silo-pkg v3.14.2 与上游 minio-go v7.4.1。SDK 包含取消后的失败分段上传清理、UTC 保留期时间戳及 STS 时长透传(并行 GET 与 ComposeObject 仍需显式启用)。
- 保留桶版本控制操作中被包装的底层 S3 错误;当 Object Lock 阻止暂停版本控制时,明确向前端返回
InvalidBucketState。 - 使用 Go 1.27.2 与 Node 24.22.0 LTS 构建。更新
golang.org/x/*模块及依赖版本:compress v1.20.3、msgp v1.6.5、etcd v3.7.2、fwd v1.2.1 与 cpuid v2.4.1(保留 go-systemd v22.6.0 以支持 NetBSD,保留 tablewriter v0.0.5 以兼容现有 MC API)。 - 构建工具固定为 GoReleaser v2.18.3、golangci-lint v2.15.0 与 govulncheck v1.9.0,重新生成 2.4.2 内嵌前端资产并更新固定摘要的构建容器。
集成说明
由于模块路径保留无 /v2 后缀的 github.com/pgsty/silo-console,Go 消费方通过伪版本 v0.0.0-20261017112417-ef2dd2c41d21 引用。嵌入 Console 的 Server 需同时显式声明 Console 与 MC 替换:
Console v2.4.2 直接依赖 github.com/pgsty/silo-pkg/v3 v3.14.2(既有密码权限迁移规则见密码权限迁移指南)。注意 go-jose v4.1.6 的 4096 位 RSA JWK 限制仅影响链接了该包的 Server OIDC 路径,独立 Console 二进制未链接 go-jose 与 go-ldap。
发布与验证
全部 44 个发行制品(6 个平台二进制、6 份归档、9 个 Linux 软件包及配套校验清单、SBOM 与签名来源证明)均已核验并与标签源码 ef2dd2c41d21 一致。该提交通过完整 CI 矩阵(权限、SSO、复制、浏览器测试、源码镜像一致性与可复现打包)、漏洞检查、本地 Go race 测试、251 项前端单元测试,以及搭配 Server 20261018 的真实 API 与浏览器分享测试。
公开镜像 docker.io/pgsty/silo-console:v2.4.2(linux/amd64 与 linux/arm64)的多架构索引摘要为:
发布核验约定 · 组件版本矩阵 · 相对 v2.4.1 的源码差异。
6 - mcli 20261018 发布
版本: RELEASE.2026-10-18T00-00-00Z · 软件包版本: 20261018000000.0.0 · 源码: fa3b8bf72458。
本版本作为独立 mcli 客户端及 Server 20261018 与 Console v2.4.2 的配套客户端版本发布(参见 silo-pkg v3.14.2 发布说明)。
更新内容
- 升级至 silo-pkg v3.14.2 与上游 minio-go v7.4.1。SDK 修复取消后的失败分段上传清理、UTC 保留期时间戳格式及 STS 时长透传,并保留既有
CopyObject内嵌错误处理与校验和逻辑(并行 GET 与 ComposeObject 仍需显式启用)。 - 使用 Go 1.27.2 构建,更新
golang.org/x/*模块、compress v1.20.3、msgp v1.6.5 与 etcd 客户端 v3.7.2(其中 fwd v1.2.1 修复同时返回数据与错误时的字节丢失及Skip偏移;cpuid v2.4.1 修复缓存识别)。 - 通过
silo-pkg引入 go-jose v4.1.6(修复 RSA JWK 解析 CPU 消耗问题 GHSA-mgcc-cww5-fp2q)与 LDAP v3.4.15。 - 刷新固定摘要的 UBI 9 基础镜像与发行工具链:GoReleaser v2.18.3(含日志脱敏与归档修复)、nFPM v2.48.0、golangci-lint v2.15.0、govulncheck v1.9.0 与 gofumpt v0.12.0。
升级说明
CLI 命令、别名、MC_* 环境变量与本地配置文件格式保持不变(保留 go-systemd v22.6.0 替换以支持 NetBSD 构建,保留 tablewriter v0.0.5 API)。各组件配套关系见组件版本矩阵。
发布与验证
全部 19 个发行制品(Linux/macOS/Windows 的 amd64/arm64 共 6 个归档、6 个 Linux RPM/DEB/APK 软件包、1 份归档校验清单及 6 份软件包校验文件)均已核验,涵盖下载摘要、6 个二进制源码标记、6 个软件包载荷、PGSTY GPG 签名(9592A7BC7A682E7333376E09E7935D8DB9BD8B20)及 11 份 GitHub 构建来源证明(均绑定至 fa3b8bf72458)。
该提交通过 Go 测试、交叉编译、漏洞扫描(无可达或已导入包漏洞;仅保留未导入 OpenPGP 模块公告 GO-2026-5932)及发布流水线检查,并通过针对 SILO fbcb5119782a 的 Go 与 Shell TLS 功能回归测试(制品构建 · Docker 发布)。
公开镜像 docker.io/pgsty/mc:RELEASE.2026-10-18T00-00-00Z(及发布时的 latest,支持 linux/amd64 与 linux/arm64)的多架构清单摘要为:
下载与安装 · 完整变更记录 · 相对 20260916 的源码差异。
7 - silo-pkg 3.14.2 发布
发行版: v3.14.2 · 源码: c6835145176f。
github.com/pgsty/silo-pkg/v3 v3.14.2 为 mcli 20261018 与 Console v2.4.2 提供十月依赖基线;后续补丁版 v3.14.3 在此基础上优化了策略判定性能,供 Server 20261018 使用。
变更内容
- 上游
minio-go升级至 v7.4.1:在调用方取消上下文后仍确保清理失败的分片上传,以 UTC 序列化 Object Lock 保留期时间,原样透传请求的 STS 时长,并支持 Kubernetes 投射服务账号令牌文件(并行 GET 与 ComposeObject 仍需显式启用)。 go-jose升级至 v4.1.6:修复解析超大恶意 RSA JWK 时的 CPU 消耗问题(GHSA-mgcc-cww5-fp2q);同步升级 LDAP v3.4.15、msgp v1.6.5 与 etcd 客户端 v3.7.2。golang.org/x/*升级:x/cryptov0.58.0、x/netv0.61.0、x/sysv0.49.0、x/textv0.43.0。使用 Go 1.27.2 开发与测试,保持模块go 1.26最低版本要求及 NetBSD 的go-systemd v22.6.0替换。
兼容性与采用方式
公开包签名与密码策略语义保持不变(从 v3.14.0 之前版本升级请参考密码权限迁移说明,各组件依赖对照见组件矩阵)。
行为变更提示:
go-jose v4.1.6拒绝超过 4096 位的 RSA JWK,使用该解析器的 OIDC/JWKS 消费方需确认身份提供方密钥长度不超过 4096 位。- 低于 1 小时的 STS 请求时长现在按原值发送,不再被客户端静默改写,因此超出服务端下限的过短时长会被服务端直接拒绝。
验证
该版本通过 Go 1.27.2 完整 lint 与 race 测试、Go 1.26.9 race 测试、OpenLDAP 集成测试、模块整洁性检查及 govulncheck 扫描(无可达或已导入包漏洞)。
8 - SILO 20261015:已替代草稿记录
状态:已被正式版 Server 20261018 替代。 RELEASE.2026-10-15T00-00-00Z 曾于 2026-10-15 13:52:28(UTC+8)短暂公开,随后撤回为 Draft 并由包含完整十月修复栈的 20261018 接替。本页归档该候选版的源码范围与制品验收记录,新部署与升级请直接使用 20261018。
- 历史标签:
RELEASE.2026-10-15T00-00-00Z - 软件包版本:
20261015000000.0.0 - 候选源码:
7a3ca0f82100cce06289a465f54139da2639f642(相对于 Server 20260916 的完整源码差异)
对象锁修复
- SN-2026-015 — 保留期修改授权(#234):每次
PutObjectRetention请求在读取对象状态前,必须携带请求体中的 Object Lock 条件键通过s3:PutObjectRetention鉴权。缩短、清除未到期GOVERNANCE保留期或改变其模式时,必须同时具备显式 bypass 请求头与s3:BypassGovernanceRetention权限(不能绕过基础s3:PutObjectRetention的Deny)。清除保留期按剩余0天求值,远期日期计算不再溢出饱和。 - SN-2026-016 — 保护已有版本免受原位覆写(#235):客户端指定写入
versionId必须具备可信复制权限(s3:ReplicateObject)。目录null版本与持久化分片上传目标在实际覆写前、持有目标写锁时复查锁状态(覆盖升级前创建或从旧暂存状态恢复的分片上传),确保既有GOVERNANCE、COMPLIANCE与 Legal Hold 保护生效;锁状态读取失败时拒绝写入。 - 发行前置门禁(#237):发行构建流水线新增 Object Lock 竞态回归前置检查,覆盖慢请求体目录覆写、预检读取失败、旧分片完成覆写
COMPLIANCE以及恢复上传 UUID 碰撞。
20260916 以来的其他改动
| 改动 | 用户可见效果 |
|---|---|
| #233 | 解码复用的旧版 xl.meta 头部时清除缺失字段,并使扫描更新与最终响应字段互斥(见结构体复用修复记录)。 |
| #225 | 对齐 S3 校验和错误文案(含 Content-MD5 拼写)。 |
| #220 | 修复 Lambda 目标集合 TargetIDSet.IsEmpty 判空逻辑,并补充空集合与非空集合回归测试。 |
fa565ec9f |
升级至 Go 1.27.2、golangci-lint 与 golang.org/x/net v0.60.0,同步模块要求与固定 digest 的 Docker 构建阶段。 |
组件身份
| 组件 | 选用版本 |
|---|---|
| Server | RELEASE.2026-10-15T00-00-00Z(包版本 20261015000000.0.0) |
| 内嵌 Console | v2.4.1(源码 1360e26d976d) |
| mcli | RELEASE.2026-09-16T00-00-00Z(源码 e952aa78f10a) |
| 共享包 | github.com/pgsty/silo-pkg/v3 v3.14.1 |
| 上游 S3 SDK | github.com/minio/minio-go/v7 v7.3.1-0.20260915093545-32e1f32cb176 |
| Go 工具链 | Go 1.27.2 |
升级要求
- 全节点与复制站点升级:升级全部 Server 进程及所有接受 S3 写入的复制站点,避免未修复节点继续放行未授权的保留期修改或原位覆写。
- 核对策略权限:仅授予
s3:BypassGovernanceRetention而未授予s3:PutObjectRetention、或依赖 bypass 绕过保留期条件键的请求将返回403 AccessDenied。 - 指定
versionId写入限制:普通 S3 客户端写入(含 root 签名请求)不得指定目标versionId;可信复制保留版本 ID,mcli batch replicate写入 SILO 时目标凭据需具备s3:ReplicateObject。 - 锁状态不可读时拒绝覆写:已锁定的目录对象与已有分片目标不可被覆写;若底层锁元数据读取失败,需先恢复存储盘健康再重试。
- 历史数据排查:升级前已发生的异常保留期变更或覆写不会自动回滚,请结合审计日志核查(从 20260916 之前版本升级时请一并参考九月版升级要求)。
候选制品验收记录
针对候选源码 7a3ca0f82100cce06289a465f54139da2639f642 的流水线与本地核验结果如下:
| 检查项 | 结果 | 流水线记录 |
|---|---|---|
| 主分支 Go CI | 通过 | Run 38686240587 |
| 漏洞检查(VulnCheck) | 通过 | Run 38686240625 |
| 发行构建与 Object Lock 前置门禁 | 通过 | Run 38686425467 |
| 发行软件包定稿 | 通过 | Run 38687734395 |
- 静态制品核验:36 个发行制品、34 份制品来源证明、Linux/macOS/Windows 的
amd64/arm64共 6 个平台二进制静态身份、6 个 RPM/DEB/APK 安装包载荷与 2 个 RPM 签名全部核验通过(参考历史归档校验和与安装包校验和)。 - macOS arm64 二进制运行验收(110/110 通过):
| 场景 | 结果 |
|---|---|
| 全新安装完整 Object Lock API 验收 | 49/49 |
| 基于官方 20260916 数据目录原地升级验收 | 12/12 |
| 升级后再次运行完整 Object Lock API 验收 | 49/49 |
(其中 65 次预期拒绝操作均未改变目标对象的任何内容或元数据状态;Windows 与 macOS amd64 为静态身份核验。)
Docker 镜像验收
Docker 发布工作流 38689158028 构建的 linux/amd64 与 linux/arm64 多平台镜像摘要及 OCI 来源证明均核验通过:
| 镜像变体 | 版本标签 | 多平台 Index Digest |
|---|---|---|
| Classic | RELEASE.2026-10-15T00-00-00Z |
sha256:aaac6bce13eb99316b3c88bd20143fc3c38ab607585256a411a095c44ee57f62 |
| Distroless | RELEASE.2026-10-15T00-00-00Z-distroless |
sha256:70cac541c5a928be5cd16d6b8732d85ac06e891a0e3d9956a745381330692fc6 |
四个平台单架构镜像(容器内 /usr/bin/silo 与官方 Linux 归档二进制逐字节一致)均通过 /minio/health/ready 探针与 Object Lock API 套件(196/196 通过,其中 120 次预期拒绝操作均保持对象版本、ETag、保留期、Legal Hold 与版本列表完整不变):
| 镜像 | 运行环境 | API 验收 | 二进制比对 |
|---|---|---|---|
Classic linux/arm64 |
Docker Desktop ARM64 原生 | 49/49 | 与官方 Linux arm64 归档一致 |
Classic linux/amd64 |
Docker Desktop ARM64 仿真 | 49/49 | 与官方 Linux amd64 归档一致 |
Distroless linux/arm64 |
Docker Desktop ARM64 原生 | 49/49 | 与官方 Linux arm64 归档一致 |
Distroless linux/amd64 |
Docker Desktop ARM64 仿真 | 49/49 | 与官方 Linux amd64 归档一致 |
连同 macOS arm64 原生安装与升级测试,候选制品运行验收合计 306/306 通过。
9 - SILO Console 2.4.1 发布
SILO Console v2.4.1
于 2026 年 9 月 16 日发布,源码为
1360e26d976d。
本版接入 pkg v3.14.1 与 mcli 20260916,收紧匿名分享代理,支持多对象流式 ZIP 下载,并提供带签名和构建溯源的发布制品。
共享下载
#52 的修复将匿名代理限制为 配置的 S3 源站上的对象内容 GET 请求,拒绝重定向、系统路径和通过查询参数选择的非下载操作。 公开对象、预签名链接和指定版本下载继续可用。不需要新增一个关闭分享的环境变量。
感谢 Jiri Pejchal(@jiri-pejchal) 报告内部指标暴露问题。 支持的请求形式及反向代理要求见共享下载边界。
密码策略迁移
这个补丁版本包含授权语义变化。 修改密码按钮和会话能力改用 admin:ChangeMyPassword;
创建用户、重置他人密码继续使用 admin:CreateUser。配合对应的 SILO Server,
单独拒绝 CreateUser 不再锁定调用者自己的密码。要保留旧限制,应在升级前于同一个 Deny 语句中拒绝两个动作,保留原资源范围与条件。
更新后的内置 readonly 允许自助修改密码,也不再覆盖另一份策略授予的 CreateUser 权限。
已保存的策略覆盖保留原有语句。请协调升级 Server、Console 与 pkg,并阅读迁移及回滚说明。
下载与浏览器恢复
- 浏览器支持文件写入器时,多选 ZIP 使用背压流式写入,支持取消和重复下载保护;其他浏览器交给原生下载管理器。两条路径都不会在 JavaScript 内存中缓冲整个 ZIP。
- 只有响应提供可靠总长度时才显示百分比。原生下载会明确提示已交接,此后需在浏览器下载管理器中取消。选择超过 5 GiB 或总大小未知时,界面推荐使用 mcli 进行长时间传输。
- 无效路由和渲染异常提供恢复入口,不清空偏好设置;补全中英文字段、图标控件、退出文字和支持键盘操作的提示。
依赖与嵌入
| 组件 | 选择的版本 |
|---|---|
| 共享包 | github.com/pgsty/silo-pkg/v3 v3.14.1 |
| MC 源码 | github.com/pgsty/mc v0.0.0-20260916070421-e952aa78f10a,对应 mcli 20260916 |
| 上游 minio-go | v7.3.1-0.20260915093545-32e1f32cb176 |
| JWX / strfmt | v3.3.0 / v0.27.2 |
| React Router | v7.18.4 |
| 构建工具 | Go 1.27.1、Node 24.21.0、Yarn 4.13.0 |
SDK 正确处理 CopyObject HTTP 200 响应内嵌的 S3 错误;JWX 修复自定义 JSON 字段名转义, strfmt 更新 Go 1.27 主机名校验。嵌入前端和第三方署名已按最终依赖重新生成。 go-systemd v22.6.0 与 tablewriter v0.0.5 是保留的兼容性固定版本。
Go 嵌入方通过历史模块路径 github.com/minio/console 的 replacement 选择
github.com/pgsty/silo-console v0.0.0-20260916075814-1360e26d976d。
Go 不继承依赖模块的 replacement,需同时复制标签 README 中显式的 MC replacement。
正式支持的管理对象是配套 SILO 组件;上游 MinIO/MC 兼容性属于尽最大努力。
软件包与验证
本次 GitHub Release 有 44 个附件:二进制及归档、DEB/RPM/APK 软件包、源码、法律声明、SPDX SBOM、校验清单及 Sigstore 签名包。校验清单使用 Cosign 签名,构建溯源记录对应标签和工作流。
独立部署 v2.4.1 请使用 GitHub Release 二进制或 Linux 软件包;docker.io/pgsty/silo-console 的多架构容器镜像自 Console v2.4.2 起恢复公开拉取。Server 内嵌 Console 不受影响。
Linux 软件包保留 minio-console.service、console-user 和 /etc/default/console。
服务状态目录为 /var/lib/silo-console,证书目录改为 /etc/silo-console/certs,停止服务最多等待 90 秒。
已有安装重启前,请按要求迁移证书和权限,或通过 CONSOLE_OPTS 保留旧证书路径。
安装过程保留旧证书与私钥,不会自动重启服务。具体见软件包升级说明。
精确发布源码通过完整 CI 矩阵、 漏洞检查和 发布验证。 本地还验证了 251 项前端单元测试、51 项浏览器测试、嵌入资源逐字节一致性,以及独立和内嵌部署的分享行为。 实际下载的 Darwin/arm64 二进制经过签名校验清单核验,并连接 SILO 测试服务执行了分享验证。
10 - silo-pkg 3.14.1 发布
v3.14.1 从
fa657ef4 发布。
这是 github.com/pgsty/silo-pkg/v3 的依赖与工具更新;
相对 v3.14.0 的差异没有修改包的 Go 源码或公开 API。
依赖变化
- JWX 从 v3.2.0 升至 v3.3.0。上游发布说明
将自定义 JSON 字段名编码时缺少转义的问题标识为 GHSA-4cf7-xm37-g63h。可利用性取决于是否接受攻击者控制的自定义 claim 名称;
本包
env的 JWT 路径仅使用已注册的 claim 名称。 - 上游 minio-go 升至
v7.3.1-0.20260915093545-32e1f32cb176,包含 minio-go #2306:识别 HTTP 200 响应正文中的 S3CopyObject错误,避免误报复制成功。 - Testify 升至 v1.12.1,lint 配置采用
gomodguard_v2。 保留 Go 1.26 最低版本、Go 1.27.1 工具链及支持 NetBSD 的 go-systemd replacement。
组件与迁移边界
v3.14.0 的密码策略变化继续生效,本补丁没有回退它。
原先意图同时禁止用户管理与修改自身密码的策略,应按迁移指南
保留 admin:CreateUser 与 admin:ChangeMyPassword 的配对 Deny。
SILO 20260916、mcli 20260916 和 Console 2.4.1 均已选用此包,详见组件版本表。
发布验证记录见上述 release 和 PR #9。
11 - SILO 20260916 发布注记
版本日期: 2026-09-16 · 正式发布: 2026-09-17(UTC 2026-09-16) · 标签: RELEASE.2026-09-16T00-00-00Z · 软件包版本: 20260916000000.0.0。安装入口见下载页。
源码范围为已发布提交 9b11dc9469e6 到本版 2a4d51406b7e,共 210 个提交,其中 140 个非合并提交。本文覆盖该范围内的最终行为,包含 #214 之后的列表 quorum、版本 purge 和迁移标签修复。
本版重点
- 更完整的请求认证边界: 关闭普通签名与预签名请求的未签名操作头缺口,校验预签名正文摘要,使签名年龄及载荷哈希策略使用可信输入。
- 可持久恢复的 IAM 撤销: 保留删除版本、父身份撤销边界与成员授权时间,防止延迟事件、重建同名身份和重启恢复重新激活旧授权。
- 多池操作针对同一个逻辑对象: 条件 PUT、分片完成、条件 DELETE、指定版本删除及元数据协调使用一致的对象选择和锁边界。
- 池迁移保留标签: rebalance 和 decommission 的普通对象及分片迁移恢复完整标签写入,保留原修订和有序清空状态。
- 修复加密及联邦复制: 保留 SSE-C 原始副本、明文分段大小、独立 Object Lock/标签修订,以及远端实际写入的校验和、版本和时间。
- 复制和配置最终状态更可靠: 修复标签删除复活、删除标记 purge/MRF、resync 计数与取消、桶配置来源时间和删除状态收敛。
- 可选的严格分片发现: 新增持久化扫描、全局分页和只读预检;默认仍为 legacy,容量和迟到创建写入的限制明确保留。
- 更新整套管理工具: 内嵌 Console 2.4.1,捆绑 mcli 20260916,采用 pkg 3.14.1;补齐浏览分页、流式 ZIP、错误退出码和策略正确性。
- 两项必须提前安排的升级变化: 密码权限拆分会改变已有策略的含义;持久 IAM 撤销要求协调升级和完整后端备份。
版本与组件
| 组件 | Server 20260903 | Server 20260916 |
|---|---|---|
| Server | RELEASE.2026-09-03T13-18-01Z |
RELEASE.2026-09-16T00-00-00Z;源码核对点 2a4d51406b7e |
| 内嵌 Console | 源码 464a59d73ada,版本标识 v2.3.0 |
已发布 v2.4.1,源码 1360e26d976d |
| MC 模块 / 镜像内 mcli | 20260903 | 已发布 20260916,源码 e952aa78f10a |
| 共享包 | github.com/pgsty/silo-pkg/v3 v3.13.2 |
v3.14.1,包含 v3.13.3 和 v3.14.0 的累计修复 |
| 上游 S3 SDK | minio-go/v7,revision 0e78d3f18efe |
v7.3.1-0.20260915093545-32e1f32cb176 |
| Go / madmin-go | Go 1.27.1 / v3.0.110 | 保持 Go 1.27.1 / v3.0.110 |
| Helm | 7.0.2 | tag 源码内 Chart 7.0.3;未单独发布 Chart 包或 Helm 仓库 |
本版的 Console 和 MC replacement 分别为 v0.0.0-20260916075814-1360e26d976d、v0.0.0-20260916070421-e952aa78f10a。Go 不继承依赖模块的 replacement,因此 Server 显式选择两者。pkg 直接使用 PGSTY 模块路径;Server、Console、MC 保留现有历史模块身份和协议名称。minio-go/v7 继续使用经过核验的上游版本。
正式维护和发布验收面向 SILO + Console + mcli + silo-pkg;与未修改的上游 MinIO/MC 保持尽最大努力兼容。
安全与授权
本轮包含四个本地安全编号;SN- 是项目台账编号,不是 CVE。完整说明见签名头边界及九月安全说明。
| 编号 | 修复与实际边界 | 依据 |
|---|---|---|
| SN-2026-011 | 普通 Authorization 与预签名 SigV4 拒绝未签名的 x-amz-* 操作头,防止签名 PUT 被改造成使用签名者权限的 CopyObject;空首值的多值头也不能绕过 |
#173、#177 |
| SN-2026-012 | 通用认证路径验证仅由 header 提供哈希的预签名正文;摘要不符返回 XAmzContentSHA256Mismatch。调用者必须持有相应的签名写入 URL |
#177 |
| SN-2026-013 | 持久 IAM 撤销和父身份边界防止旧事件、旧子凭据及旧授权跨越保留的撤销历史 | #191、#192 |
| SN-2026-014 | Console 匿名分享代理只接受配置 S3 origin 的对象内容 GET,拒绝跳转、系统路径和选择其他操作的 query | Console #56、Server #209 |
签名配套修复还包括:消除重复复制源头的取值歧义;从签名日期计算 s3:signatureAge,移除请求头中的临时缓存值;统一预签名 query/header 的有效载荷哈希优先级;将 PutObjectTagging 的服务端合成头放到验签之后、授权之前。X-Amz-Content-Sha256 仍可不列入 SignedHeaders,但其有效值和正文校验必须一致;明确签入的 UNSIGNED-PAYLOAD 保留原含义。
streaming SigV4 seed 的未签名操作头仍在此检查范围之外。未签名头拒绝继续返回 400 AccessDenied。Console 分享修复未新增全局关闭分享的环境变量,继续执行 S3 授权检查。
密码权限拆分:兼容性变更
Server #175、pkg #6 和 Console #51 将自助修改密码与用户管理分开:
- 内置用户修改自身密码检查
admin:ChangeMyPassword;无显式 Deny 时允许自助操作。 - 创建用户、重置他人密码仍要求
admin:CreateUser;root、STS、服务账号原有身份限制继续生效。 - 单独
Deny admin:CreateUser不再锁住调用者自己的密码;原有Deny admin:ChangeMyPassword开始实际约束这一入口。 - 更新的内置
readonly不再以 CreateUser Deny 覆盖其他策略给予的用户管理权限,并支持独立的consolereadonly能力;已有保存的策略覆盖不会自动重写。
若要保留旧的组合限制,升级前就在同一条 Deny 语句中列出两个 action,保留原 Resource 和 Condition。 回滚旧 Server 时也保留这对 Deny,因为旧实现不能单独执行密码专用 Deny。详见密码权限迁移。
共享策略实现
pkg #4 修复 NotResource 未进入去重哈希、不同字符串条件集合表示碰撞而丢失 Deny 的问题;直接构造的 policy 也能在建立索引前报告 Deny。多星号通配匹配移除指数级递归,保留原有字节匹配与 MatchSimple 边界语义。
因此,过去依赖错误丢弃 Deny 才成功的请求可能开始被拒绝。若错误语句已经从保存的 JSON 中消失,升级无法还原,必须与原策略源比对后重新提交。
IAM 复制、撤销与恢复
删除版本保留在原 IAM 配置路径,覆盖用户、服务账号、组、策略及各类策略映射;普通列表与授权隐藏删除记录。对象存储和 etcd 后端均串行化版本比较和写入,接收端保存来源时间,相同时间删除胜过活记录。
- 延迟的同后端删除通知重新读取已提交状态,避免删除随后重建的身份。
- 同名父身份重建保留
RevokedBefore;新服务账号和内置 STS 携带签名的siloParentRevocation边界。旧子凭据即使被重放或更新,也不能重新获得效力。 - 每个组成员保留自己的授权时间,编辑另一成员或组状态不会顺便给全部成员重新授权。
- 较新的服务账号快照可替换同 key 的旧副本,保留 secret、disabled、绝对过期时间和撤销边界;身份类型冲突报错,过期快照不能延长旧凭据寿命。
- Healing 在失去和重新取得领导权后能恢复;保留已确认版本并以有界批次重试。自然过期的普通 STS 不被无条件转成永久删除记录,服务账号 key 的复用仍保留版本历史。
- 新增 IAM 撤销数量、healing 失败数、耗时和最近成功时间指标,见设计与指标。
跨站点撤销异步传播。父身份删除先于后续清理提交;若后续清理返回 HTTP 500,父身份撤销实际已经生效。墓碑没有 TTL 或自动压缩;存储和启动成本随保留历史增长。删除后组成员的独立增删、同时间活记录冲突、任意时钟偏差和跨站点逐 token 撤销仍有明确边界。
S3 条件操作与多池一致性
跨池协调层先在共享命名空间锁内选择逻辑对象,再判断条件或合并同版本状态。正在退役、排空的池也参与相关状态检查;保留期、legal hold、标签分别按自己的修订排序,不能用对象修改时间代替所有字段的版本。
| 操作 | 本次变化 | 依据 |
|---|---|---|
| 单对象 DELETE | 非空 If-Match 在删除前比较客户端可见 ETag;不匹配返回 412。* 要求选中表示存在且不是删除标记;显式 versionId 比较该版本 |
#145、#178 |
| 普通条件 PUT | If-Match / If-None-Match 针对各池逻辑当前对象判断,避免目标池旧副本接受旧 ETag 或拒绝当前 ETag;当前删除标记视为缺失 |
#207,修复 #199 |
| 条件分片完成 | CompleteMultipartUpload 在同一对象锁下跨池判一次条件,而非仅检查上传所在池 | #190 |
| 普通指定版本 DELETE | 协调所有池的同版本副本,涵盖 UUID、null version、delete marker 和适用的目录标记删除,减少删除后旧副本重新可见 | #188 |
| 对象与元数据修改 | 对象写入、元数据、healing、复制和迁移复用协调锁;保留独立的 Object Lock、标签修订和共享远端 tier 引用 | #178、#189 |
可用性取舍: 任一相关池元数据无法确认时,条件 PUT/分片完成及协调删除可能失败,即使另一池仍可提供 GET/HEAD。读仲裁不足返回 503;恢复可读性后重试。清理失败可能发生在部分磁盘修改之后,没有分布式回滚保证。出站删除复制未完成时会保留等待 purge 的版本。
普通条件 PUT 带目标 versionId 时仍比较当前对象,同时保留指定写入版本。该修复不清理其他池旧副本、不撤销历史错误覆盖,也不新增全局时钟顺序保证。#190 的分片修复与 #207 的普通 PUT 修复是两个独立问题。
未支持的边界: 批量 DeleteObjects 的 XML <ETag> 仍不提供条件保护;空 If-Match 按普通删除处理,内部递归前缀删除不走对象条件。尚无 s3:if-match 策略键,也没有额外的 GetObject 权限检查。需要条件保护时使用支持的单对象路径。详见条件删除与多池一致性。
池迁移保留对象标签
fced8630365f 修复 rebalance/decommission 迁移时丢失对象标签的问题:读取表示把标签放在 ObjectInfo.UserTags,迁移过去直接转交 UserDefined,可能漏掉目标写入所需的规范标签字段。
普通 PUT 与 multipart 初始化四个入口现在从独立的 metadata 副本重建标签字段,保留标签原修订,包括缺失、空值和已有的有序清空状态;迁移不生成新的标签修订,也不修改 reader 的 map。写入与分片完成继续使用现有锁内重读协调,避免旧 reader 越过后来的标签更新或清空。
此补丁不自动恢复历史已丢标签;请单独核对过去迁移过的对象及依赖标签的策略和生命周期规则。
null 版本列表 quorum
8d06424b1 修复新版本少数派掩盖旧版本多数派的列表选择问题。只有原选择未达到 quorum、每条非空磁盘流恰好只有一个普通 null 版本且纠删布局相同时,才按 header 重新计数;不扩大到混合版本历史。
仍有限制: #218 记录并发覆盖期间逐节点重启时,HTTP 200 列表仍可能遗漏可读取对象。不要用该阶段的列表驱动会删除目标多余对象的同步工具;集群稳定后重新列举。
加密对象、校验和与属性
- 原始 SSE-C 副本正确落盘: 已授权复制携带的密文按原样保存,避免目标默认加密或压缩再次变换,造成双重加密或不可读对象(#109、#122)。
- 保存明文分段大小: SSE-C multipart 副本记录逻辑长度,修复 part-number/range 读取、覆盖后对象大小和属性结果(#119、#124)。
- 排除 SSE-C 压缩: 普通 PUT、多段初始化、COPY、Snowball 不再新建压缩 SSE-C 对象,避免解密得到压缩流而非原文;SSE-S3/SSE-KMS 保留相应压缩选项(#118、#126)。
- 支持重传修复: 已存在或不可解码的 SSE-C 副本通过对象重传更新,不误用普通 metadata COPY;保留目标较新的保留期与 legal hold(#120、#134)。
- 密钥轮换遵守显式 checksum: 请求算法时执行必要的完整重写,包含与现有算法相同的请求;多段源可能变为单段目标,ETag 可能变化(#113、#123)。
- 属性返回逻辑结果: GetObjectAttributes 对压缩/加密分段返回明文尺寸,稀疏 part number 的末页正确结束(#114、#115、#128)。
- 不可读对象不冒充成功: 解密或存储完整性失败返回 500,不再以 206 被客户端当作有效读取(#110、#121)。
- 兼容 chunked checksum: 非 trailer 模式的 chunked PUT 即使声明
x-amz-trailer,实际放在普通 header 中的 checksum 仍被采用与验证(#107、#143)。
这些是预防新错误和提供受支持修复路径,不是自动重写历史加密数据。历史压缩 SSE-C、错分段尺寸及不可读副本须保留密钥和精确版本身份,另行读取验证。SSE-C 完整性说明列出恢复边界。
联邦 CopyObject
本节针对旧 etcd 桶联邦的远端转发,区别于桶/站点复制。累计修复来自 #157、#159、#163、#172、#177、#179。
| 过去的问题 | 修复后的行为 |
|---|---|
| 显式 checksum 算法被忽略,空对象或多段源结果错误 | 计算/转发逻辑完整对象 checksum,正确处理空流、trailer、继承摘要;拒绝缺失、畸形或仍带 multipart 后缀的必需远端摘要 |
| inline 源因内部 metadata 被目标拒绝 | 大小写不敏感地移除整类保留内部字段,公共元数据和标签使用正确的公开字段 |
| 加密源的字节或长度错误,可能重复加密 | 读取并转发逻辑明文与长度,由目标按显式 SSE 请求或自己的默认规则加密;SSE-KMS context 作为 JSON 对象传递 |
| 代理的自动加密覆盖目标桶默认值 | 未显式指定 SSE 时保留目标选择 |
| legal hold 被写成用户 metadata 或丢失 | 使用真正的 Object Lock header,保留完整精度的 retention 时间 |
| 返回零 LastModified、缺少目标 version ID,事件对象身份为空 | 响应和事件绑定目标实际提交的写入;不以代理时间或不带版本的后续 HEAD 猜测 |
| 原始 SSE-C replica COPY 的含义不明确 | 在创建目标前明确返回 501 NotImplemented;正常持源密钥的 SSE-C COPY 不受此拒绝规则影响 |
对应问题:#99、#100、#158、#166–#171。远端已提交写入之后仍可能因响应校验失败返回错误;版本化重试前先核对目标实际版本。详见联邦复制契约。
Object Lock、标签和复制恢复
保留与标签独立排序
- 只有 legal hold 的普通写入不再跳过桶默认 retention;ON/OFF 都不能替代保留期选择,显式时间精度保留(#165、#177)。
- 空值与只有时间戳的 retention/legal-hold 删除参与顺序比较,不抹掉更晚的目标状态,也不导致无穷重发(#111、#117、#129、#131)。
- 多池副本写入选择跨池权威 Object Lock 状态,关闭原先只在单个 erasure set 内成立的边界(#133、#178)。
- 副本协调时将标签值与修订一起带回,避免现有标签被空值覆盖;SSE-KMS metadata COPY、SSE-C 轮换保留标签时间;本地 PUT/DELETE tagging 单调推进修订,空标签作为有序删除抵御延迟重放(#189、#193、#196)。
复制双方须更新才能尊重空标签墓碑。带已记录标签修订的对象在显式 resync/heal 时每对象增加一次 metadata COPY;目标按桶默认 KMS 加密时可能重写数据。带标签过滤的复制规则仍按删除后的空标签决定目标资格。历史缺失或畸形修订不会被自动重建。详见Object Lock 排序和复制标签排序。
删除标记、MRF 与 resync
- 单对象删除标记 purge 正确分类,并在 worker、scanner/heal 和持久 MRF 恢复中保留标记身份及重试状态;只在 bucket、key、version、修改时间与任务匹配时接受相应 405 标记响应。审计状态由
COMPLETE统一为COMPLETED(#153、#162、#196)。 - 有界 MRF 队列的丢弃通过管理信息、指标与去重日志可见,并统一对象/删除 worker 分配;这不把有界队列变成永不丢弃的无限队列(#152)。
- resync 在发布 Completed 前应用最后的计数;以实际复制结果而非“目标已存在”判断成功(#136、#139)。
- 按正在同步的目标 ARN 派发;每个 resync ID 使用独立取消上下文,阻塞派发、walker 和 worker 能收尾,旧任务不能覆盖新终态(#141、#137)。
精确版本 purge 与排队创建
eb4f5e5b3 使纯版本 purge 不再向原本没有标记的磁盘创建标记;不存在版本的重试须由写 quorum 多数确认缺失,汇总已删除和可靠缺失的回复。接收端跨池解析指定版本,标记 healing 保留复制和 purge 元数据。
254b19ac0 在复制锁内重新读取排队的标记创建任务:版本已不存在、已非标记或正在 purge 时丢弃旧任务;读结果不能确认时通过 MRF 重试。该检查覆盖 DELETE handler、GET/HEAD/LIST heal、scanner 和 MRF 排队的任务。
358ab38fb 只把实际存储的标记报告为 delete marker,避免将等待 purge 的数据版本错误返回为 x-amz-delete-marker: true 并产生错误事件。
仍有限制: 已发出的创建请求、其他站点的重放,以及多数确认 purge 后崩溃留下的少数磁盘残留,仍由 #217 跟踪。该修复不构成接收端持久删除屏障。
副本元数据正常化
普通元数据提取之后只恢复六项复制专用字段,不再把传输用 aws-chunked 重新持久化为对象 Content-Encoding;可信 Snowball 条目也不继承外层归档的普通对象元数据(#185、#194)。
上述变更不会扫描或重写历史对象,不会自动恢复丢失标签、Object Lock 历史或所有未收敛 purge。请使用只读审计工具与手册处理精确版本、混合 Content-Encoding、歧义分类和受控恢复,不要直接做批量 self-COPY。
桶配置、缓存与启动
PR #180 完成 #77 的来源状态收敛:Policy、Tags、SSE、Quota、Versioning、Object Lock 的读取、比较、修改和保存处于同一 metadata.lock 中。peer 保存来源时间,本地更新在已有时间之后单调推进;同时间删除优先,其余冲突用稳定内容键裁决。
- 专用事件、bulk、import、初次同步和 heal 使用一致规则,省略字段保持既有设置不变;Versioning/Object Lock 的空事件仍不提供删除能力。
- Policy JSON 规范化,已接受的
NotAction/NotResource策略能正确 GET/export;Statement/集合顺序可能变化,授权语义不因此改变。 - 空 Policy 继续按删除处理;零 Quota 保留有值文档,容量不受限制,不能把它悄悄转成不同的删除状态。
- 旧桶缺少 Created 时从物理信息恢复并落盘;接管不把默认空状态误认作删除,未知/无效/不可达来源有有界诊断。
MINIO_SITE_REPLICATION_METADATA_TOMBSTONES默认 off。升级所有参与站点后才统一设为 on 并重启,使 Tags/SSE/Quota 的缺省载荷删除时间对 heal/初次同步可见。关闭期间遗漏删除的收敛仍有边界。
被旧接收时间污染的历史配置不会自动重写,且新增的持久 IAM 状态不支持滚动降级。桶配置收敛说明给出更细的恢复与取舍。
同一版本还修复:桶删除/更新/生命周期读取与缓存发布的剩余竞态;移除把“各字段最大时间”误当整记录版本的 reload guard,使等最大时间下的新字段仍能更新;桶 metadata 导入导出保留 per-bucket CORS(#105、#112、#127、#156、#164)。
#116 补全启动就绪窗口说明及 Linux 重启验证:除检查健康探针外,还应在每个协调节点使用签名 PUT/GET 请求验证数据路径就绪。OIDC 修复见下节。
分片上传发现、分页与取消
PR #198 增加持久化发现,#213 随后恢复保守的默认及回滚兼容性。20260916 的最终默认是 legacy。(SILO 20261018 4733e1423 随后退役了 MINIO_API_MULTIPART_LISTING=strict,仅保留 legacy 缓存/精确 key 列表作为公开模式;参见最新决策。)
| 项目 | 默认 legacy | 显式 strict |
|---|---|---|
| 列表来源 | 已发布行为:精确 key / 节点缓存,原有缺陷仍在 | 跨 pool/set/drive 扫描持久上传状态并验证 quorum |
| S3 列表语义 | 不承诺修复 prefix、delimiter 和跨页发现 | 全局 prefix、delimiter、排序及 marker 分页;原 marker 上传完成/取消后仍可续页 |
| 旧上传 | 保留原有可用行为 | 缺少持久 bucket/key 身份时返回诊断 503,不伪造成功的空页 |
| 取消 | 既有读仲裁、尽力清理和池顺序 | 各相关 set 多数删除确认,支持低于读仲裁的残片重试;已观察残片删除失败不能被空盘掩盖 |
新 writer 在现有 quorum 写入的 xl.meta 中保存保留的 bucket/key 身份,完成上传时删除这些临时字段;没有二级索引或目录格式迁移。两种模式共用的 maxUploadsList 请求上限从 10,000 降至 1,000。它限制传入的页长参数;legacy 缓存路径仍会因忽略分页而返回更多记录。
只通过进程环境 MINIO_API_MULTIPART_LISTING=strict 启用并重启;不支持 mcli admin config set 动态设置。非法值诊断后回落 legacy,不丢弃其他 API 设置。启用前升级所有 writer、排空旧上传、执行需要 admin:StorageInfo 的只读 GET /minio/admin/v3/multipart-preflight,再验证部署容量。旧上传缺失身份可能阻断 strict 下其他桶的列表。
每进程最多两个扫描;每扫描 16 个身份 worker、4 个 metadata worker、30 秒 context,合计目录条目预算 100,000(按跨盘目录条目累计,而非 100,000 个唯一上传)。每页重新扫描持久状态,预算耗尽或不确定覆盖返回 503,而非成功的局部页。临时 10,000 上传、四 APFS 卷试验的一页耗时 18.7 秒,未达到暂定五秒目标。
两种模式都修复错 bucket/key 的 Abort 误清有效缓存,以及解锁后 peer 通知失效的问题。HTTP 层不存在上传仍返回幂等 204。迟到的创建写入仍可能在取消成功后恢复上传,未加入持久创建屏障。 因此 #79 保持开放。详见启用及回滚契约。
Console 2.4.1 的累计改进
除分享代理和密码权限修复,本次内嵌选择还包含从 20260903 之后积累的浏览器、管理 API 和交付改进:
- 对象游标分页: 使用 ListObjectsV2,支持每页 50/100/250/500/1000 项;排序、过滤、选择明确限定当前页,不为总数扫描整个桶;翻页失败保留当前列表,取消后释放列举 worker,rewind 明示行数和时间范围;空或 null versioning 响应不再使列表崩溃。
- 精确操作对象身份: 删除保留 bucket/key/version,目录删除限制在带尾斜线的前缀内;生命周期编辑保留 current/noncurrent、按日期和未展示字段,正确读取旧 prefix 并移除过期 filter 表示;删除复制规则保留共享目标,最后一条规则使用配置删除 API。Governance bypass 对有权用户显式提供、默认关闭,包括仅对象级设置保留期的情况。
- 权限和会话: Create Bucket 按
s3:CreateBucket显示;后台请求传输失败不无条件注销;Watch 参数正确 URL 编码,Inspect 保留结构化错误、不重复读取响应体。 - 嵌入兼容: 修复回环 TLS 登录;只对 Server 明确初始化的 TCP loopback peer 应用嵌入代理信任,独立默认仍为不信任;恢复四个 WebSocket 连接限制配置,避免所有公共浏览被错误压在单源八连接内(Server #108、#147、#148)。
- 流式 ZIP: 有文件 writer 的浏览器以背压写入并支持取消;其余交给原生下载管理器,不在 JavaScript 内存中缓存整个归档。原生交接后的取消由浏览器负责;只在可靠长度可用时显示百分比,大于 5 GiB 或未知大小推荐 mcli。
- 恢复、翻译与无障碍: 畸形路由、持久偏好和渲染异常提供恢复入口,补齐中英文字段、图标控件名称、退出文字和键盘提示;共享下拉框修复快速点击/触摸选到旧悬停项,禁用项不再误选其他值。
- 独立软件包: 增强可复现构建、固定工具及浏览器依赖、SBOM/签名/来源验证。systemd 保留
minio-console.service、console-user、/etc/default/console;证书目录改为/etc/silo-console/certs,需按指南处理旧证书和权限,升级不自动重启服务。
来源:Console #47、#50、#57、2.4.1 注记。
mcli 20260916 的累计改进
镜像捆绑的新客户端包含 20260913 与 20260916 两批变化:
pipe使用已应用的全局 quiet/JSON 设置,重定向输出不混入进度条;空输入保留显式 checksum,非空输入持续流式处理。MC_*布尔量接受on/off/enabled/disabled。- S3 Select
sql、传输、mirror 权限失败、legalhold、递归 retention 部分失败及mv源删除失败返回非零;mv等待删除结果,成功复制的目标不回滚。 - mirror 的逐对象权限错误不会阻止后续对象;有限任务有失败返回 1,失败任务不输出普通成功结尾。显式 summary 的 JSON 标为 failure,极短传输速度保持有限数值;列举/监听的取消重试策略仍有原有边界。
mirror --remove --watch不因源历史版本删除而误删目标;管理重启 dry run 不退化成真正重启,非 TTY 结果可靠。- 空 retention 时长、无效
find --regex正常报错,不再 panic;JSON usage error 不混入不合法格式。 - SDK 识别 HTTP 200 内嵌的 CopyObject 错误,避免
mv误认复制成功后删除源。此修复适用于客户端选用 CopyObject 的路径(通常小于 64 MiB 或显式--disable-multipart),默认大对象路径走 ComposeObject。
脚本应检查最终退出码,而非开始时的 success 消息或进度字节。--skip-errors 不把已经发生的失败恢复成退出码 0;部分 retention JSON 错误文字可能为空。命令、别名、MC_*、配置格式与包名保持兼容。
HTTP、TLS 与可观测性
- 绝对请求头期限: #196 使
--read-header-timeout/MINIO_READ_HEADER_TIMEOUT真正进入 HTTP Server,连接包装器不再让持续小读无限延长 HTTP/1 请求头期限。默认 30 秒;正文保留滚动空闲超时。缩短值也收紧 TLS 握手读取窗口;HTTP/2 保留其独立行为,TLS 写入侧和 handler CPU/存储等待不因此获得新总期限。负值关闭头部专用上限,不推荐使用。设计说明回应 #183。 - 恢复 Go TLS 默认值: 移除 Server 八处显式曲线覆盖,使 listener、节点、身份提供方、复制和 etcd transport 尊重 Go 1.27 的默认密钥交换及相应 GODEBUG 控制;证书、主机名验证保持严格(#164)。这会改变 SILO 在线上发送与接受的内容: 不设 GODEBUG 时,提供的 group 列表变为 Go 当前默认值,额外包含
SecP256r1MLKEM768与SecP384r1MLKEM1024;设了GODEBUG=tlsmlkem=0时,该开关现在真正生效——作用于整个进程,出站与入站监听器同样适用。#154 已关闭,但报告人 2026-09-17 在本版本上的复测仍然失败;discovery/JWKS 总期限仍为独立事项。参见 TLS/OIDC 说明 与《写死 TLS 参数与握手兼容性》。 - CPU 指标竞态:
loadCPUMetrics对外层和嵌套 map 加读锁,防止 Prometheus 抓取与资源更新并发导致整个进程退出。修复已随 #214 进入 main;独立 #215 以替代方式关闭,问题 #210 也已关闭。 - 配额和日志指标: 使用生效的 BucketQuota 字段;
AddSystemTarget幂等,串行化 logger 初始化和 console target 发布,防止日志订阅后重复 collector 破坏/logger/webhook指标(#106、#150、#132、#151)。
依赖、构建与工程维护
amqp091-go从 1.10.0 升至 1.14.0,包含恶意 AMQP frame 过量分配修复;SILO 中可达性需要配置 AMQP 通知目标(#176、#177)。- JWX 3.3.0 修复自定义 JSON 字段名转义;strfmt 0.27.2 修复 Go 1.27 主机名验证;LZ4 4.1.30 修复 reader、部分读取及并发行为,本版增加 Snowball/S3 Select 集成回归。
- 上游 SDK 累计包含可配置上传限制、streaming Content-Type 签名、RDMA 使用调用方 TLS 信任、列表 checksum 与可选 restore status 一致性,以及前述 HTTP-200 CopyObject 错误处理。见上游采纳记录。Console 同时更新 React Router 7.18.4,并保留 js-yaml 与 smol-toml 的拒绝服务修复及重建后的嵌入资源。
- Go x/* 依赖刷新;保持 Go 1.27.1、NetBSD 所需的 go-systemd 22.6.0 replacement 和现有 tablewriter 兼容选择。
- 容器基础镜像 digest 更新,双 Linux 架构从校验源码构建静态 curl 8.22.0;客户端安装器和镜像固定 mcli 20260916 的实际已发布归档及 SHA-256。
- 本版固定 GoReleaser 2.18.1 与 Action v7.2.3 的完整 commit;依赖文件改动也触发 Test Release Pipeline。tag 源码附带 Helm Chart 7.0.3 和新 Server/mcli 默认标签;没有单独的 Chart 发布。
- 修复条件 PUT 与标签复制测试夹具竞态,恢复集成脚本有效凭据;将相应 CPU、标签、multipart 和 S3 Select race 回归纳入 CI。
- 持续校正 rebrand guard,明确 AGPL-3.0-or-later、DCO 和无 CLA 的贡献规则,保留实际人类贡献记录;README 仓库卡片增加每日更新流程。
- 正式产品、升级、安全和设计文档集中在本站;源码仓库保留入口、必要兼容文档和测试材料。迁走临时调查与旧安全工作资料,历史证据以固定提交链接保留。
9 月 4 日的 Helm 正式镜像标签校正、mcli 归档 pin 和容器恢复发布完成了上一版的交付。
撤回的实验功能
GET 访问频率驱动的池间 ILM 分层 #60 于本周期合入,随后由 #188 移除。它从未进入正式 Server 20260903,也不属于本版的新增功能。 移除 tracker、mover、scanner hook、专用配置/XML action 和指标;十个旧 ILM 键兼容接受但忽略,读取 v8/v9 usage cache 并写回不带退役字段的 v8。
使用过中间开发构建的部署应移除 access-only 规则,编辑混合规则时保留普通动作。普通过期、远端 tier、rebalance、decommission 继续存在;独立的多池 Object Lock、条件删除、写入协调和共享远端引用保护保留。迁移说明解释具体范围。
升级与恢复要求
- 固定最终组件和制品。 实际 Server、Console、mcli、包、镜像和 Chart 应逐一核验身份。官方镜像名称统一使用
docker.io/pgsty/silo、docker.io/pgsty/mc和docker.io/pgsty/silo-console。 - 提前迁移密码策略并核对原始 Deny。 要维持旧组合限制,在同一 Deny 中保留 CreateUser 与 ChangeMyPassword。对曾丢失语句的策略从原始来源恢复。
- 安排协调维护窗口。 暂停 IAM 修改,隔离未知离线站点;升级所有参与节点/站点,包括共享 IAM 后端但未启用站点复制的节点。不支持同后端新旧混跑或滚动降级。
- 保存完整恢复点。 备份 IAM 后端及加密材料;
mcli admin cluster iam export只包含活记录,不能备份删除历史。恢复前停止相关进程,防止继续使用旧缓存/peer 确认。 - 逐入口验证身份与数据。 旧撤销凭据应拒绝,新用户、服务账号和新签发 STS 应在每个节点有效;验证签名 PUT/GET、对象字节、版本、标签、保留期和复制收敛后再恢复业务流量。
- 回滚须调和备份后的撤销。 恢复旧快照会丢失后续撤销;在每个恢复站点逐一调和并检查全部端点,必要时改用不同名称的新身份、重新签发凭据。不承诺恢复前 STS 会话连续性。禁止在线删除 tombstone 或只转换活记录来强行启动旧版。
- 分别启用两个可选行为。 桶配置 tombstone export 只有全员升级后才打开;strict multipart 还要求所有 writer 更新、旧上传排空、预检和容量验证。正常升级可继续使用默认 legacy。
- 处理开发版本残留。 若运行过写入共享
api multipart_listing的中间构建,备份后用mcli admin config reset ALIAS api multipart_listing定向清除,保留其他 API 设置;不要重置整个子系统,也不要重放含旧键的历史。使用过访问频率分层的部署按撤回指南清理。 - 检查出站链路上的 TLS 检查设备。 握手内容在 20260903 随 Go 1.27 工具链变过一次,本次再次变化。SSL 检查 NGFW、SASE 网关、IDS/IPS,或按 JA3/JA4 客户端指纹做白名单的环境,都可能让身份提供方、webhook、远端分层或复制连接以
connection reset by peer被重置,而同一容器里的curl却正常。升级后请验证 OIDC discovery 与 JWKS、审计与通知目标、远端分层和复制端点。处置办法与代价见《写死 TLS 参数与握手兼容性》。 - 单独审计历史对象。 盘点不可读 SSE-C、错误分段尺寸、标签/锁状态、
aws-chunked污染、错误覆盖和待 purge 版本。经批准的恢复清单应在副本环境验证。
操作依据:IAM 升级与恢复、历史副本审计、密码迁移、分片列表契约。虽然对象数据与纠删码布局未变,但新增的持久 IAM 状态不支持滚动降级回旧版 Server 二进制。
已知限制与未完成事项
| 项目 | 本版边界 / 当前处置 |
|---|---|
| #79 分片列表 | 已有可选 strict 实现,legacy 仍默认;生产容量、迟到创建写入屏障和完整交付验收未完成 |
| 批量条件删除 | XML ETag 仍无保护;空头、递归扩展和策略强制不属于已实现契约 |
| Streaming SigV4 | 除普通与预签名 SigV4 修复外,streaming seed 的操作头覆盖仍待后续处理 |
| IAM 与桶配置历史 | 丢失修订/撤销不能自动重建;时钟、组成员局限和历史增长成本仍需运维管理 |
| #197 两盘 EC 文档 | 仍开放 |
| 其他开放提案 | #20 Renovate、#30 Operator、#40 通知目标热加载、#61 KES/OpenBao 规划、#160 图片处理仍保持开放 |
| 历史迁移标签 | 先前迁移已丢失的标签不会自动恢复,需单独核对依赖标签的策略和生命周期规则 |
| #217 / #218 | 在途/跨站点创建、崩溃残留与重启期间列表遗漏仍未解决;范围见上文 |
验证与发布状态
发布源码 2a4d51406b7e 的 Go CI 和 Test Release Pipeline 已通过。Release 构建和 Finalize 已完成。GitHub Release 提供 36 个资产,包括六平台归档、Linux 软件包、SBOM、校验和与证明材料。
Console v2.4.1、mcli 20260916 和 pkg v3.14.1 已分别发布。2026-09-17 复核时,独立 docker.io/pgsty/silo-console 的匿名 token 请求返回 HTTP 401,尚不能确认公开拉取;可使用 Console 的 GitHub 二进制或软件包。Server 内嵌 Console 的源码选择不受此独立镜像分发状态影响。
问题索引与贡献
本版已修复或在明确范围内完成的问题组为:条件操作 #10/#133/#144/#199;联邦复制 #99/#100/#158/#165–#171;桶元数据 #77/#105/#112;加密与属性 #107/#109–#115/#117–#120;嵌入 Console #108/#147/#148;复制调度恢复 #136/#137/#139/#141/#152/#153/#185;运行与指标 #106/#116/#150/#154/#176/#183/#210。池迁移标签补丁以直接 main 提交列示;#79 保持部分实现而非关闭。编号详情和限制见上文各节链接。
感谢报告、补丁与复核参与者,尤其是 @mrjavadseydi(配额、分片列表与分层探索)、@nikitapogromsky(logger 幂等)、@Aeirx(联邦 legal hold)、@magicxor(条件 DELETE 早期方案)、@julienlau(purge/MRF)、@chodorenko(复制编码)、@orenyomtov(签名头报告)、@jiri-pejchal(Console 分享)、@AEGEGE(HTTP 报告)、@aschyolkin(CPU 竞态),以及 @vampywiz17、@kh0mka 等复现和反馈参与者。
PR #12、#125、#155、#184、#187、#195 等原始提交已由后续实现替代。完整署名见贡献记录。
12 - mcli 20260916 发布
版本: RELEASE.2026-09-16T00-00-00Z · 软件包: 20260916000000.0.0 · 源码: e952aa78f10a。
相对 20260913 的变化
- 接入 silo-pkg v3.14.1、上游 minio-go v7.3.1-0.20260915093545-32e1f32cb176 和 JWX v3.3.0。CopyObject 会重试并报告 HTTP 200 响应内嵌的 S3 错误,避免复制失败后授权
mv删除源对象;JWX 正确转义输出 JSON 的字段名。 mirror报告权限失败,包括源不可读、目标写入拒绝及本地目标删除失败。后续对象继续处理,有限任务有失败就返回 1;这些逐对象权限错误不要求--skip-errors,也不会在 watch 模式中重启整个扫描。- 列举与监听失败保留原有取消重试路径。持续拒绝列举权限仍可能导致反复重扫,本次没有重写该重试策略。
- 失败的 mirror 不再输出普通成功结束统计;显式
--summary仍输出统计,JSON 使用status: failure,文本错误诊断仍位于 stderr。同一时钟刻度内完成的极短传输不再产生无穷大的 JSON 速度值。 - legalhold set/clear、递归 retention 部分失败、
mv源删除失败都返回非零。mv等待删除结果,已成功复制的对象不回滚;retention 每个失败对象只输出一次诊断,避免重复或误导提示。 - 空 retention 时长与非法
find --regex表达式正常报错,不再 panic。
脚本兼容性与升级
上述曾返回 0 的失败路径现在返回 1。 请检查最终退出码与错误记录。mv 删除失败可能使源和已成功复制的目标同时存在,重试前应核对两端状态。
配置格式、别名、MC_* 变量、命令与包命名保持不变。pkg v3.14.1 保留 v3.14.0 引入的密码权限语义。见组件版本矩阵与密码权限迁移。
正式支持和管理接口验收以 SILO 为目标;对原厂 MinIO 与其他 S3 服务保持尽最大努力的兼容。
交付与验证
本次发布包含 19 个资产:Linux/macOS/Windows 的 amd64/arm64 共六个归档,Linux 两架构的 RPM/DEB/APK 共六个包,一个归档校验清单,以及六个包校验文件。归档、清单与 DEB/APK 通过 Sigstore 构建证明绑定到签名 tag 与精确源码;RPM 携带 PGSTY GPG 签名(9592A7BC7A682E7333376E09E7935D8DB9BD8B20)。
最终发布提交通过 Linux/macOS/Windows race 测试、Linux 386 测试、交叉编译、漏洞扫描和发布打包流水线。发布前还验收了已发布 SILO 20260903 与修复后的 Server 源码 3c26a8b0b5bd、Object Lock 与权限失败、CopyObject 故障注入及双架构 RPM/DEB/APK 安装升级。扫描未发现可达漏洞或已导入包漏洞,仍保留未使用 OpenPGP 代码的模块级提示。
CI: VulnCheck · Test Release Pipeline · Crosscompile · Go · Release · Docker
docker.io/pgsty/mc 版本标签和 latest 对应同一经过验证的 Linux amd64/arm64 manifest:
这项 HTTP-200 CopyObject 修复适用于 mcli 选择单次 CopyObject 的路径:对象小于 64 MiB,或显式指定 --disable-multipart。64 MiB 以上的复制默认走 ComposeObject 路径。
JWX 的具体范围及 GHSA-4cf7-xm37-g63h 见 pkg 3.14.1。--json mirror 失败后若未指定 --summary,不会补一条尾部统计记录;--skip-errors 也不会把已经发生的失败恢复成退出码 0。部分 retention JSON 失败记录只有 status: failure,错误对象可能序列化为 {},消费方不能强制要求人类错误文字存在。
13 - mcli 20260913 发布
版本: RELEASE.2026-09-13T00-00-00Z
· 软件包: 20260913000000.0.0
· 源码: 4f609a4d。
相对 20260903 的变化
mirror --remove --watch保留目标端历史版本。- 服务重启的 dry run 只显示计划,不执行重启;明确非交互环境行为。
- 传输与 S3 Select 出错时返回失败;空上传遵守显式校验和参数;quiet 模式下仍输出
pipeJSON。 - 布尔环境变量接受 on/off,修复跨平台 CLI/JSON 行为。
- 使用 pkg v3.14.0 与上游 SDK
v7.3.1-0.20260910142817-60bd07042d49,刷新 Go x/*、UBI 依赖,保留 Go 1.27.1。NetBSD 继续固定 go-systemd v22.6.0。
保留 pkg v3.13.3 引入的 Deny/NotResource 与有界通配匹配修复。 正确保留的 Deny 可能拒绝曾依赖丢失语句而成功的请求;已经丢失的语句仍需从原始策略恢复。
新 pkg 还改变密码能力。协调升级 Server 前请阅读密码策略迁移。 配套密码界面已随 Console v2.4.1 发布,协调升级见组件版本矩阵。
制品与验证
不可变发布包含 19 个附件:Linux、macOS、Windows 的 amd64/arm64 共六个归档包, 两种 Linux 架构的 RPM/DEB/APK,以及校验清单和软件包校验文件。 归档与校验清单已核验构建证明,RPM 携带 PGSTY GPG 签名;macOS arm64 原生执行版本输出与 Go 构建信息已核对。
docker.io/pgsty/mc 的发行标签与 latest 指向同一份已验证的 amd64/arm64 manifest:
容器发布流程 已完成,两种架构镜像均经拉取和版本检查。 打标签前 Go、交叉编译、漏洞与 Test Release 门槛均通过。 扫描没有发现可达或已导入的易受攻击包;未使用的 OpenPGP 仍有模块级 GO-2026-5932 告警。 与上游 MinIO、其他 S3 实现的兼容属于尽力保留;正式管理集成目标是 SILO。
pipe 的非空标准输入持续流式读取到 EOF;空输入使用普通零字节 PUT,而不是未知大小的 multipart。显式校验和参数通过同一路径传给上传实现。quiet/非 TTY 模式下禁用进度条,同时对空输入与非空输入统一保留 JSON 结果输出。
14 - silo-pkg 3.14.0 发布
v3.14.0 于 2026-09-13 发布,源码提交为 827f8109,模块导入路径为 github.com/pgsty/silo-pkg/v3。
密码策略迁移
本版调整了密码修改的授权语义:
- 公共方法
Policy.IsAllowedActions默认放行admin:ChangeMyPassword(除非策略显式Deny),而创建或管理他人的admin:CreateUser仍必须显式Allow。在配套升级后的 Server 与 Console 中,仅拒绝admin:CreateUser不再禁止调用者修改自己的密码;若需禁止自助改密,须显式拒绝admin:ChangeMyPassword。 - 内置
readonly策略移除了原先的admin:CreateUserDeny规则(若同一主体还绑定了另一份授予admin:CreateUserAllow的策略,该授权将正常生效)。新增的consolereadonly策略包含存储桶列举能力,并采用相同的权限拆分;两份内置策略本身均不授予任何用户管理权限。 - 集群中已保存的自定义策略与用户级权限覆盖不会自动改写。
如果希望维持旧版“同时禁止创建用户和自助改密”的限制,请在升级前将 admin:CreateUser 与 admin:ChangeMyPassword 写入同一条 Deny 语句(保持原有的资源范围与条件),并在整个回滚窗口期内保留该配置——旧版 Server 不会在改密端点上单独识别 admin:ChangeMyPassword 的拒绝规则。详见密码权限迁移指南。
后续配套版本(9 月 16 日): Console v2.4.1 已发布配套密码管理界面,并搭配 silo-pkg v3.14.1 与 mcli 20260916。全栈协调升级要求见组件版本矩阵。
依赖与验证
- 上游
minio-go升级: 锁定至v7.3.1-0.20260910142817-60bd07042d49,纳入可配置上传大小上限、流式请求Content-Type签名、RDMA 调用方 TLS 信任传递、列举操作校验和一致性以及归档恢复状态解析修复。 - 工具链与依赖刷新: 更新
golang.org/x/*依赖,维持 Go 1.26 最低版本要求与 Go 1.27.1 构建工具链,所有导出 Go 函数签名保持不变;维持go-systemd v22.6.0replacement 以确保 NetBSD 交叉编译兼容。 - 测试与安全扫描: 通过 Go 1.26.8 与 1.27.1 全量
-race测试、lint 及 LDAP 配置校验,并确认可通过 Go module proxy 与校验和数据库正常拉取。govulncheck 1.8.0扫描确认无已导入的可达漏洞包(仅未导入受影响子包的 OpenPGP 模块保留GO-2026-5932记录)。
本版继续包含 v3.13.3 的策略 Deny/NotResource 序列化修复与有界通配符匹配算法(此前因旧版 bug 丢失语句的策略仍需从原始备份恢复)。自 v3.13.0 引入的 github.com/pgsty/silo-pkg/v3 模块路径迁移已在四个维护组件中全部完成。
15 - SILO Console 2.4.0 发布
v2.4.0 于 2026-09-08 发布,
源码为 c103d08e。
已发布行为
- 对象目录默认每页 100 条,可选 50、100、250、500、1000。每页只发一次 S3 continuation-token 请求;排序、筛选和选择作用于当前页,不扫描整个目录,没有无限制的“全部”模式。
- 版本删除绑定选定对象,目录删除限制在其前缀内。生命周期编辑保留独立动作和界面未暴露的字段,复制规则删除统一保存。
- 暂时网络故障不清空会话;处理空版本控制状态、损坏的侧栏偏好与过时的下拉选择。
- Server 显式启用嵌入信任策略时恢复 Console loopback 代理行为,独立部署信任默认值不变。
- 依赖 pkg v3.13.3、MC 源码
v0.0.0-20260908140805-c8aa5d25a63a与上游 SDK0e78d3f18efe。本版只引用 MC 源码,本身没有发布新的 mcli 标签。
修复后的 Deny/NotResource 语句保留行为可能拒绝曾因去重缺陷而成功的请求。 已经丢失的语句需要从原始策略恢复。嵌入方必须复制标签对应 README 的 MC replacement。
后续版本
Console v2.4.1 提供共享下载限制、密码权限拆分、 多对象流式 ZIP、浏览器恢复与可验证发布制品,使用 pkg v3.14.1 和 mcli 20260916。 v2.4.0 使用较早的浏览器内存 ZIP 路径。升级前请阅读密码权限迁移。
v2.4.0 精确发布源码通过完整 Console CI。变更详情见 标签 changelog、 对象浏览器指南与 发布附件。
16 - Silo Console 2.2.0 发布说明
发布日期: 2026-08-26 · 版本: v2.2.0(7dc4258a6)· 仓库: pgsty/silo-console
SILO Console 2.2.0 新增面向日志与结构化文本的有界预览,收紧下载错误处理以防止截断的压缩包被当作完整文件交付,修复数据表格行操作的权限门控,将用户启停状态与用户组变更拆分为独立 API,并在写入前校验数据库通知 DSN 与 IAM 策略文档。
在底层,依赖栈迁移到 Go 1.27.0,并切换到 SILO 维护的组件:pgsty/silo-pkg 3.12.1 取代上游 minio/pkg,pgsty/mc 取代上游 mc 库依赖,minio-go 升级到 7.3.0,etcd client 系列升级到 3.7.1,修复 CVE-2026-73500。
自 v2.1.1 以来的最终变更集共 33 个提交,涉及 176 个源文件(+8,794/−2,057 行,不含重新生成的嵌入式前端资产)。
为什么版本号是 2.2.0: 本周期切换了共享策略与证书实现的依赖提供方、跨越了 etcd client 的 minor 版本边界、拆分了一条 REST 路由,并调整了文件夹下载的失败语义。
日志与结构化文本预览
对象浏览器现在可以把 .log、.txt、.json、.xml 对象作为纯文本预览。实现刻意保持多疑——「在管理界面渲染桶里的任意内容」本质上是一份 XSS 邀请函:
- 构造上就有界。 请求携带
Range: bytes=0-1048576;响应以流式读入固定缓冲区并设硬上限,Content-Range/Content-Length与实际读到的字节严格互验。超过 1 MiB 的对象报告过大——绝不会把片段当成完整内容渲染。 - 要么是文本,要么不渲染。 字节必须通过严格 UTF-8 解码(
TextDecoder开启fatal)且不含 NUL;否则报告不可预览,而不是渲染乱码或二进制垃圾。可预览性是精确白名单——四种扩展名加精确的 MIME 类型text/plain、application/json、application/xml、text/xml——.html/.htm/.xhtml被显式排除,即使其元数据自称text/plain。 - 没有活动文档。 内容渲染进单个 DOM 文本节点——不用
innerHTML、不用 iframe、不做 JSON 到 HTML 的变换。回归套件投喂 HTML、SVG、XML 载荷并断言它们保持为惰性文本。 - 对竞态免疫。 快速切换对象时,进行中的预览按代际失效,慢返回的旧对象响应不可能覆盖当前对象。取消与重试都是一等状态。
- 匿名可用。 公开/匿名对象页面通过匿名请求路径获得同样的预览,不触发任何带凭据的 API 调用。
围绕新预览类型,既有预览管线也一并修正:空对象预览为空而不是报错,追加写入的日志按新长度重新预览而不是按过期的列表尺寸截断,快速切换对象时的元数据竞态已消除。预览与分享对话框现在拿到对象的真实大小(92e8f4e65)。
下载完整性与进度计算
下载路径(进度上报、单对象、文件夹、归档与字节范围)统一改为严格校验完成状态与错误返回。
未知总大小时的进度显示
缺失、非法或自相矛盾的总大小不再变成编造的百分比:进度指示器保持不确定态,直到真实总量已知。零字节对象被显式归一化而不是落进未知总量路径;中止与取消是终态——迟到的进度事件不可能复活一个已取消的下载。下载请求恰好结算一次,JSON 错误体被安全解析,生成的对象 URL 会被回收。
流式文件夹下载
单文件夹下载改用浏览器原生的流式下载路径,不再把整个 ZIP 累积在 JavaScript 内存里——几个 GB 的文件夹不再有标签页崩溃的风险。交接模型的一个后果:控制台的传输管理器在把流交给浏览器的那一刻即报告完成(有 toast 说明),此后由浏览器自己的下载 UI 接管——交接后在控制台里取消不会停止浏览器侧的传输。多选下载仍走既有的 POST 响应,因此仍是内存 Blob;改变这一点需要单独的 API 决策,不在本版本范围内。
ZIP 完整性——一项刻意的行为变更
这是最可能被当作「下载坏了」上报的变更。 在 2.1.1 及更早版本中,文件夹/ZIP 下载若有对象读取失败,会静默跳过这些对象,交付一个 HTTP 200 但缺文件的归档。2.2.0 中任何单对象失败——列举、stat、读取、条目创建、关闭或拷贝——都会中止归档:尚未发送任何数据时返回干净的错误,流传输中途则中断连接,截断的 ZIP 再也不可能冒充完整归档。
实际后果:策略只授予某前缀的 List 而 GetObject 只覆盖其中一部分对象的用户——一种常见的 IAM 配置——以前会拿到局部归档;现在下载会在第一个被拒对象处失败。旧行为是静默的数据缺失,2.2.0 把它当作 bug 对待。请下载你能读的内容,或把文件夹下载限定在可读前缀内。
字节范围与状态码
- 畸形或不可满足的非空
Range头现在返回416并携带Content-Range: bytes */N,而不是 500。Range 解析比 Go 的宽容默认更严格:带符号、内嵌空白、bytes=-0、空 range 元素都会被拒绝。 - 对零字节对象的 range 请求返回空 200 而不是 500——这正是空对象预览 bug 的根源。
- 惰性对象
Stat的失败现在透传真实的 S3 状态码(403、404……)而不是一律 500。 206响应在写响应头之前设置Content-Length,部分响应从此携带正确的帧信息。- 对象大小现在总是序列化——REST 与 WebSocket 列表对零字节对象返回
"size": 0而不是省略字段,UI 显示0 B。这是「诚实进度」赖以成立的地基。
版本历史
S3 合法的 null 版本 ID 保持可见而不被丢弃,版本计数把前缀匹配过滤到精确对象,桶版本控制被暂停或禁用后历史仍然保留。
真正生效的权限门控
行操作按钮从未被禁用过
每个带数据表格的页面都把权限谓词传给了一个表格组件早已不读取的属性名(disableButtonFunction)——于是 10 个受影响页面(用户、用户组、策略、IDP、Webhook 设置、桶的访问/复制/生命周期面板)上的查看/编辑/删除按钮无论有无权限一律可点。谓词现在接到组件真正接受的属性上,并有一个源码守卫测试:死属性名再次出现即构建失败。服务端授权从未受影响——没权限点了也只会报错——但 UI 从此如实传达权限,而不是撒谎。
独立的服务账号能力
访问密钥管理过去把多个 UI 决策挂在一个合并的权限检查上。2.2.0 在一个模块中推导四项独立能力——List、Create、Update、Remove——并在自助 Account 页面与管理员的用户详情页面一致地应用:
- 能 list 才显示服务账号标签页,能 create 才显示创建按钮,能 remove 才允许行选择与批量删除,能 update 才显示编辑铅笔;
- View 现在是真正的只读:所有字段禁用、没有提交路径、回车键失效——以前「查看」打开的是可编辑对话框;
- 会话通告的 Create Access Key 能力对请求作用域策略的计算修正为:以
svc:DurationSeconds为条件的Deny(一种只有在具体请求存在后才能求值的有效期限制)保持该能力可见——包括通配符管理动作——而无条件或登录期即可判定的 deny 现在会正确隐藏它。最终授权仍由 SILO 在请求时裁决。旧代码对任意条件 deny 都保持能力可见,属于过度通告。 - 新增一条 OIDC 创建/列举/查看/删除的集成回归,走 UI 的显式凭据端点,并断言预期中的自我更新拒绝。
写入前校验 IAM 策略
命名策略与服务账号策略写入现在会在调用 Admin API 之前拒绝畸形文档和裸 S3 资源 ARN,并返回客户端错误。为兼容历史数据,旧策略读取仍保持宽容;但不兼容的已存策略必须先修正,才能再次保存。严格解析与资源检查位于控制台自身写入路径,而不是导入分支专有的策略 API,因此仍能维持对上游 minio/pkg v3.6.1 的源码构建下限。
匿名页面回归匿名
匿名对象浏览页不再发出只会产生 Access Denied 噪音的受保护 Object Lock/保留策略请求,并补上了语言(文/A)与暗色模式切换控件。
用户状态与用户组从此是两个操作
切换用户的启用/禁用状态与编辑用户组过去是一条合并的 PUT /user/{name} 调用,两个载荷都必填,且合并的权限门控导致仅仅编辑用户组也要求 admin:EnableUser。2.2.0 将其拆分:
PUT /user/{name}/status(新增)只改状态,校验取值为enabled|disabled,并拒绝当前登录用户启停自己。失败的切换不再让开关脱离同步——UI 反映服务器的答案,而不是乐观翻转。PUT /user/{name}/groups(既有)成为用户组编辑的唯一调用,不再要求admin:EnableUser。PUT /user/{name}在线协议上原样保留,作为已弃用的兼容端点服务既有 API 消费者;未知状态在该端点现在返回 400 而不是 500。
API 契约细节(含重新生成 Swagger 客户端的注意事项)见兼容性。
所写即所存的数据库通知表单
PostgreSQL 与 MySQL 事件目标表单围绕一个共享的 DSN 解析器/序列化器重写:
- 结构化字段与原始连接串是同一份状态:原始串在结构化字段被编辑前保持权威;一旦编辑,就重建规范化 DSN——PostgreSQL 使用 libpq 关键字/值引用规则,MySQL 使用感知 IPv6 方括号的
go-sql-driver格式。模式切换不再破坏手工输入的字符串。 - 生成的预览掩码凭据;掩码不可能进入 API 载荷(载荷始终使用原始连接值)。
- 保存要求连接串与表名同时存在,清空的值会真正传播。
- 服务器现在拒绝其配置语法会破坏的 DSN——内嵌换行、会被解析成兄弟配置键的值(比如密码里含
table=)、不平衡的引号——在存储之前返回 400,且不把提交的机密回显在错误里。 - 各通知目标(Kafka、Redis、MQTT、NATS、Webhook)的通用密码与令牌字段渲染为密码输入框,包括被环境变量覆盖的值。
准确的待重启状态
配置的新增、更新、删除、重置现在尊重服务器实际返回的是否需要重启,而不是硬编码「需要重启」(或者更糟——弄丢它)。待重启标记是单调的:一旦有操作要求重启,后续不要求重启的操作不能清除它——只有真正的服务重启才能。
上传提示
超过 5 GiB 的浏览器上传会收到不阻断的提示:控制台以单个不可续传的请求上传,这个量级应该用 mcli 的分片上传。
会话、指标认证与 i18n 加固
- 会话快速失败。 匿名/空会话立即得到 401,而不是挂在一个空凭据的 Admin 请求上。控制台同时接受规范的
401与旧式403无效会话响应;过期会话的重定向感知子路径——部署在/console/下的控制台在自己的基路径内重定向。 - Prometheus Basic 认证全路径生效。 健康检查与根路径回退探测现在都发送 Basic 凭据(以前只发 Bearer,导致 Basic 认证的 Prometheus 让所有仪表盘组件被禁用),Bearer 令牌保持优先,且所有响应体都被排空,keep-alive 连接得以真正复用。
- 占位符替换在构造上转义安全。 翻译占位符填充使用一趟式字面格式化器:值中的
$&、$1、$`、反引号、花括号保持字面,重复占位符全部填充,并有一个 AST 源码守卫测试禁止不安全的String.replace模式回归。
工具链与依赖
Go 1.27 基线
| 组件 | 2.1.1 | 2.2.0 |
|---|---|---|
go 指令、构建镜像、CI 矩阵 |
1.26.5 / 1.26.x |
1.27.0 / 1.27.x |
golang.org/x/crypto |
v0.54.0 | v0.55.0 |
golang.org/x/net |
v0.57.0 | v0.58.0 |
golang.org/x/text |
v0.40.0 | v0.41.0 |
golang.org/x/mod |
v0.37.0 | v0.40.0(关闭 CVE-2026-56864/-56865) |
golang.org/x/tools |
v0.47.0 | v0.49.0 |
SILO 分支
silo-pkg3.12.1 是正式发布依赖。pgsty/silo-pkgv3.12.1 已于 2026-08-25 发布,控制台直接固定它。它建立在 3.12.0 之上,继承策略资源边界加固、条件键查找、LDAP 与证书监视器修复,以及 Go 1.27 / etcd 3.7 依赖基线。mc库依赖切换到pgsty/mc分支,使用日期式伪版本;导入路径不变。require行刻意停留在上游v3.6.1。 Go 会忽略依赖模块中的replace指令:下游模块 require 本控制台时,解析到的是上游minio/pkg,而 SILO 的v3.12.1标签在上游并不存在。要求真实上游标签保证控制台对下游可解析;replace 只在控制台自身构建时应用分支。最终 CI 针对上游 v3.6.1 验证了公共源码构建表面。注意这只是编译层兼容——没有自带顶层 replace 的下游构建得到的是上游行为,不含分支的 SILO 专有 IAM 语义。go-systemd回钉到 v22.6.0:v22.7.0 在 NetBSD 上使用了那里不存在的CLOCK_MONOTONIC,无法编译;钉住直到上游修复发布。
etcd 3.7.1——仅客户端库
三个 etcd Go 模块一起从 3.6.8 移到 3.7.1,关闭 TLS 监听器拒绝服务漏洞 GO-2026-6107 / CVE-2026-73500。etcd 3.7 移除了遗留 protobuf 实现并使 clientv3.New 变为非阻塞——这些迁移只影响自行构造客户端或内嵌服务器的消费者。控制台两者都不做:它唯一的 etcd 路径是 silo-pkg/quick 操作一个已创建的客户端,只用普通的 v3 Get/Put。本次升级只涉及编译进二进制的客户端库——不触碰运维方的 etcd 服务器、集群数据或部署拓扑;服务器升级到 3.7 仍需遵循 etcd 官方的逐 minor 升级流程。
第三方维护保持克制
最终版本在独立兼容性审查后把 minio-go 升级到 v7.3.0,迁移其 INI 导入路径,并增加 lifecycle-filter XML 兼容覆盖。控制台侧的兼容解码器可以接受旧服务器返回的 legacy AccountInfo tag payload。其他已接受的维护变更包括 jwx v2→v3 与 httprc v3、go-openapi/swag/conv+typeutils 0.28.0、grpc-gateway 2.29.0、cheggaaa/pb 1.0.30 和 go.yaml.in/yaml/v3 3.0.5;无关的更大规模 go-openapi、pb/v3、压缩库与测试库升级仍然推迟。
前端方面,漏洞检查工作流扩展到 push、手动触发与开发依赖,使用不可变安装;刷新了有漏洞的传递依赖解析(fast-xml-parser 5.11、nanoid 3.3.18、@babel/core 7.29.7),移除了死导出与未使用的 http-status-codes 依赖。fast-xml-parser 5.x 的传递依赖树仅用于开发阶段,不进入浏览器构建产物。
安全评审
- 发布树上的
govulncheck:零个可达的漏洞符号,零个受影响的导入包。Swagger 构建工具单独扫描,同样干净。 - 依赖迁移关闭的漏洞:CVE-2026-73500(etcd TLS 监听器 DoS)、CVE-2026-56864 / CVE-2026-56865(x/mod 校验)。
- 仍会报告、但依旧不可达:模块级 GO-2026-5932 openpgp 公告——控制台不导入
x/crypto/openpgp,且该公告没有修复版本。 - 文本预览按 XSS 攻击面评审(见上文);其回归套件包含活动载荷测试。
- 权限门控修复属于 UI 真实性修复:2.1.1 中服务端授权从未被绕过;只是控制台显示了不该显示的控件。
兼容性
部署层面一切不变: 环境变量、配置格式、命令、二进制名、systemd 单元、端口、嵌入数据布局均无变化。发布二进制保持自包含;Go 1.27.0 仅是构建期要求。
HTTP API 契约(控制台自身的 REST API):
| 路由 | 变更 |
|---|---|
PUT /user/{name} |
线协议不变;标记弃用。OperationId 由 UpdateUserInfo 改名 UpdateUserInfoLegacy,请求体模型改名 legacyUpdateUser(结构相同)。未知状态:500 → 400。 |
PUT /user/{name}/status |
新增。 仅状态请求体(enabled/disabled 枚举,违反返回 422),返回的用户对象只含访问密钥与状态——客户端不得从中读取用户组数据。 |
updateUser 模型 |
变为仅状态且带枚举——对按 spec 生成代码的消费者是破坏性变更;旧结构以 legacyUpdateUser 延续。 |
| 对象下载 | 错误语义变化:坏 range 500→416(附 Content-Range: bytes */N),空对象 range 500→200,Stat 失败 500→真实 S3 状态码,ZIP 失败从静默局部 200→可见失败,206 响应携带 Content-Length。 |
| 列表与 WebSocket | size 总是序列化,包括 0。纯增量。 |
PUT /configs |
新增一类 400:拒绝服务器配置语法会破坏的数据库 DSN。 |
| 配置重置/删除 | 响应中的 restart 反映服务器的真实答案,不再恒为 true。 |
GET /session |
空凭据主体返回 401;通告的 Create-Access-Key 能力计算更严格(见服务账号)。 |
如果你从 swagger.yml 生成客户端 SDK: UpdateUserInfo 操作现在指向 /user/{name}/status 且请求体仅含状态。调用生成的 UpdateUserInfo 符号的代码依旧能编译,但目标已是新路由;旧的合并调用是 UpdateUserInfoLegacy。重新生成时请审计调用点。
运维者可能注意到的行为变化:
- 对部分可读前缀的文件夹/ZIP 下载失败,而不是静默省略不可读对象(详情)。
- Range 解析比 Go 的宽容默认严格;畸形 range 头(
bytes=-0、空元素)现在得到 416 而非尽力处理。 - 只是碰巧能用的数据库通知配置(DSN 在写入途中被配置语法破坏的那种)现在被前置拒绝并返回 400。
- 策略无条件拒绝创建访问密钥的会话不再显示创建控件(以前任意条件式拒绝都保持可见)。
- 待重启指示会持续到真正重启为止,不再会被后来一次无关的配置变更清除。
- 如果控制台前面的反向代理压缩了
/api/v1/…/download响应,文本预览的严格Content-Length校验会把所有预览判为错误。控制台自身只压缩静态资产——请让代理对 API 响应保持不压缩。
已知限制与后续跟进
修复表格操作按钮禁用属性后,暴露出两处既有谓词把行对象与字符串直接比较的 UI 缺陷:
- 「不能删除 Default IDP 配置」的行守卫将行对象与字符串
"Default"比较,导致按钮未禁用(IDPConfigurations.tsx); - 「不能删除环境变量覆盖的 Webhook 端点」的行守卫存在同样的对象与字符串类型不匹配(
WebhookSettings.tsx)。
两处操作在提交时仍由服务端拦截。此外,新的 PostgreSQL DSN 解析器在填充结构化字段时仅解析规范的 key=value 语法(非常规但 libpq 合法的 DSN 会显示为空结构化字段,编辑结构化字段时会用这些字段重建 DSN);TestCafe/Playwright 断言覆盖 UI 门控,服务端拒绝路径由集成测试套件覆盖。
验证
发布决策综合了本地候选阶段证据,以及在精确标签树 7dc4258a6 上执行的远端门禁:
本地发布准备门禁 —— go build ./...、go vet ./...(含 -tags testrunmain)、gofmt、golangci-lint、go test -race ./...、go tool swagger validate、govulncheck、TypeScript tsc、Playwright、Prettier、knip、linux/amd64 与 linux/arm64 发布标签交叉编译、go mod verify。
嵌入资产确定性 —— 前端经完整流水线(yarn build + 嵌入优化)从源码重建,与提交的 web-app/build 对比:逐字节一致,零脏文件。早期候选 19047161f 之后的九个提交修改 Go 兼容性、workflow 与浏览器测试时序,没有修改产品前端源码或嵌入资产。
最终树 CI 完整矩阵 —— Workflow 32888892876 报告 32 个成功 job,另有一个明确禁用的 React 测试占位项。覆盖 lint、semgrep、Go 与 API 测试、五个交叉编译目标、Swagger 漂移、最新 MinIO 源码构建、分布式集成、站点复制、封闭 SSO、完整 TestCafe 权限矩阵、subpath-nginx、Playwright 与覆盖率门禁。Vulnerability Check 32888899120 在同一提交上两个 job 全部通过。
发布流水线 —— goreleaser 32916237254 针对 v2.2.0 的两个 job 全部通过,并发布公开 GitHub Release。
下游契约 —— 在删除全部 replace 的临时树中,go mod tidy + go build ./... 针对上游 minio/pkg v3.6.1 成功,证明分支替换不会把分支独有符号泄漏进公共模块表面。
本周期一并交付的测试基础设施修复(让上述门禁真正起门禁作用):Docker 承载的集成/复制/SSO 套件回到 testrunmain 构建标签之后(裸 go test ./... 不再试图启动容器);SSO 门禁封闭化——不再 sudo 修改 /etc/hosts、不再临时 pip 安装、固定 SILO 镜像、自选端口、真实清理;集成门禁断言新的 416 range 语义并停止把 PostgreSQL fixture 绑定到主机端口;浏览器门禁通过发布 fixture 端口实现脱离 Linux 运行;修复了残存的品牌重塑前「MinIO administrator」选择器;有状态的 TestCafe 套件改为串行;Playwright CI 以不可变方式安装提交的锁文件。
发布制品
v2.2.0 GitHub Release 公开发布:
- 六个独立二进制:Linux amd64/arm64/armv6、macOS amd64/arm64、Windows amd64;
- 九个 Linux 软件包:amd64、arm64、armv6 各自的 DEB、RPM 与 APK;
silo-console_2.2.0_checksums.txt,以及 GitHub 为每个制品记录的 SHA-256 digest。
相关提交
16960f7ab— fix: keep unknown downloads indeterminate5968bb37d— chore(deps): align the SILO Go dependency stack288ab1240— fix: harden sessions, metrics, and translationsecf3bb492— fix: harden object previews and downloads902d9650d— chore: tighten dependency and test gates194c70c7a— build: prepare SILO Console v2.2.0927b44e26— fix: harden database notification formsda2191be9— fix: clarify console upload and secret limits6141c2445— build: refresh SILO Console v2.2.0 assets097e76155— chore(deps): bump the shared package fork to v3.12.099ca523d6— fix: split user status updates out of the combined user routef4097992f— fix: honor the server restart result for configuration changesf1280032a— fix: restore permission-gated table row actions24ce0af97— fix: keep request-scoped access key conditions visible in the console92e8f4e65— fix: pass the object size into the preview and share dialogs8f6fb3c78— test: make the SSO gate hermetic and pin it to a SILO release384a2cb95— build: refresh SILO Console assets and record the changesa73cda376— test: fix the integration gate’s stale range and host portcf5049c1d— test: make the browser gates runnable and fix a stale selector6fa19d857— fix: complete service account permission boundaries7e57771a4— build: refresh SILO Console assets57cfe7aa0— fix: restore downstream and browser release gates19047161f— test: stabilize permissions browser gatese37dec873— fix: validate IAM policies before writes28505ed23— chore: update minio-go to v7.3.016abb971e— ci: harden validation and release gates2ddfcd036— fix: accept legacy AccountInfo tag payloads31332bca9— fix: preserve policy source compatibility3a8251086— ci: allow permission tests to finishc159fff78— ci: serialize shared-role permission tests2e91cdf9a— test: wait for watch controls to become ready7dc4258a6— test: allow asynchronous UI controls to settle
链接:
17 - SILO Console 2.5:界面与管理功能更新
SILO Console v2.5.1 现已正式发布(源码提交 fff1618d9abb),同时作为 SILO 20261026 的内嵌控制台交付。本文完整汇总自 v2.4.2 以来的 2.5 系列变更,涵盖 v2.5.0 的界面重构与 v2.5.1 的问题修复。
GitHub Release · 下载 · 完整源码对比
导航、概览与监控指标
2.5 系列重构了整体界面视觉与交互:采用柔和的明暗主题配色、系统原生字体、统一的信息密度、Lucide 图标库、清晰的键盘焦点样式,并支持系统的“减少动态效果”(Reduced Motion)偏好。移动端抽屉与平板窄侧栏针对小屏做了专门适配,对象详情在移动端以可恢复焦点的底部抽屉呈现,同时完整保留中英双语切换、无障碍控件与开源许可署名。
左侧导航按当前会话的实际权限组织 Identity、Monitoring、Settings 与 Tools 分组,合并了统一的 Buckets 入口与最近访问存储桶列表,并保持登录重定向目标与既有对象深链接兼容(/browser 自动跳转至 /buckets,桶管理根路径默认进入 Summary 页)。Help 菜单继续提供文档、视频与 Blog/RSS 入口。
Overview 概览页直观展示节点与磁盘健康状态、原始物理容量、活跃告警、快捷操作及数据刷新时间。容量直接采用 Server 上报的实测值(不凭空估算纠删码可用容量),缺失的统计项明确显示为未知。Monitoring 下的 Metrics V3 面板严格区分“样本缺失”与“真实零值”,并正确处理逐节点重复导出的集群指标。注意:尽管 Server 20261026 已支持返回实时存储桶清单,存储桶与账户的对象用量统计仍由后台扫描器异步汇总。
存储桶、对象浏览器与任务中心
- 存储桶列表: 支持排序、名称筛选、URL 查询参数持久化、表格/卡片视图切换、大列表虚拟滚动及未知用量标注;使用稳定的行标识防止排序后选错目标桶,并在页面跳转后自动丢弃在途的旧搜索结果。
- 细粒度权限体验: 仅具备写入权限的用户也可正常进入对象工作区;完整保留桶根通配授权与前缀访问限制;修改标签等操作被服务端拒绝时直接展示服务端返回的错误原因(列举、读取与修改权限仍各自独立判定)。
- 在线预览与命令提示: 支持最大 1 MiB 的文本、Markdown、CSV/TSV 表格预览、源码高亮、安全 HTML 渲染及明确的截断提示;常用配置表单可直接生成脱敏的等价
mcli命令。 - Tasks 任务中心: 统一跟踪文件上传下载、原生流式 ZIP 打包下载、批量删除、历史版本清理与对象恢复任务;写操作并发受控,重试仅针对失败条目(取消任务不会回滚已完成的写入;大文件或流式 ZIP 下载触发浏览器保存后,请在下载完成后核对本地文件完整性)。
- 键盘导航与分页: 新增键盘上下移动、Shift 范围选择、当前页全选、快捷键面板与按权限裁剪的右键菜单。对象列表继续采用游标分页,排序、名称筛选与全选仅作用于当前页。
身份管理与高延迟诊断
用户详情页集中展示账号状态、直接绑定策略、用户组继承策略与 Access Key 数量;策略管理页明确区分原生内置策略、已被覆盖的内置策略与自定义策略,并显示策略分配计数及受影响身份。原生内置策略默认只读(需显式确认后才允许覆盖),已被覆盖的内置策略提供一键 Reset 恢复原生定义。重新加载失败时会清空过期的编辑器内容,切换界面语言时保留未保存草稿,表单统一补齐无障碍标签关联并默认遮蔽远端密钥。
注意:内置策略 Reset 与实时存储桶清单需要配合 Server 20261026 使用。 单独升级独立部署的 Console 不会修复旧版 Server 的策略缓存,也不会替换旧版 Server 内嵌的前端界面。
在诊断工具面,Health、Trace、Logs、Watch、Speedtest 与 Profile 六类实时诊断流统一复用唯一的读取协程完成 WebSocket 关闭握手(Close 帧发送与等待共享 5 秒超时预算,且不打断正常活跃流),彻底修复了 Azat / @azataiot 在 #63 中报告的高延迟链路下健康报告截断与 1006 异常关闭问题(超时错误返回标准 1008 状态码,不泄露内部堆栈细节)。同时,健康报告下载在版本探测与正文读取之间复用同一个 JSON 解码器以保留预读缓冲帧,拒绝被截短、已取消或失败的响应流,并保持 madmin v3 的签名传输与重试策略。
2.5.1 补丁修复
- 用户组状态切换(#67): 单独切换用户组启用/禁用状态时保留组内现有成员;显式传入
members数组时仍按原语义替换成员列表。 - OIDC 组权限与反向代理会话(#66): 正确保留 OIDC 字符串数组格式的组声明权限;仅在启用了 HTTPS 或配置了可信 TLS 反向代理转发头时设置
Secure会话 Cookie,不再盲目信任未校验的客户端转发头。 - 凭据导出与流式 ZIP 错误状态(#68): Access Key 导出完整保留原始 UTF-8 JSON 字节;流式 ZIP 下载若在写出首个响应字节前失败,直接透传底层 S3 错误状态码。
- 无障碍与焦点恢复(#68): 修复表格与表单控件的键盘焦点恢复、可访问名称及进度条数值属性;窗口尺寸变化导致标签栏重排时保持当前焦点标签可见。
- 配套依赖升级(#69): 升级至正式版
mcli 20261026、silo-pkg v3.15.2以及支持 HTTP204移除复制配置的上游 SDK。
依赖与交付验证
本版基于 Go 1.27.3、Node 24.22.1、Vite 8.3.5、GoReleaser 2.19.0、silo-pkg 3.15.2、mcli 20261026 与上游 minio-go 320af050c445 构建;为保持终端输出格式与跨平台兼容,继续固定 tablewriter v0.0.5、go-humanize v1.0.1、go-runewidth v0.0.29 与 go-systemd v22.6.0(详见统一依赖与安全审计清单)。
GitHub Release 提供各平台二进制归档、Linux 软件包、源码包、SHA-256 校验和、SPDX SBOM 以及 Sigstore/GitHub 构建溯源证明。Windows 归档改用 .zip 格式(Linux 与 macOS 保持 .tar.gz),官方多架构镜像已发布至 Docker Hub(docker.io/pgsty/silo-console:v2.5.1),核验步骤见发布契约。
前端静态资源与内嵌产物在隔离工作目录中完成逐字节可复现构建。SILO Console 正式维护的管理目标为 pgsty/silo(对上游 MinIO 保持尽力而为兼容),既有 CONSOLE_* 环境变量、API 路由、服务单元名称与 Go 模块路径均保持不变;详细的 API 与内嵌依赖说明见 Console 兼容性指南。
18 - silo-pkg 3.15:Go 1.27.3 与 S3 SDK 修复
silo-pkg v3.15.2 现已正式发布(源码提交 0416eb1f4505),由 SILO 20261026 组件栈以 github.com/pgsty/silo-pkg/v3 模块路径直接引入。本文完整汇总自 v3.14.3 以来的 3.15 系列更新(v3.15.0、v3.15.1 与 v3.15.2)。
3.15.0:Go 工具链与共享依赖升级
模块最低 Go 版本要求由 1.26 提升至 1.27.3,并同步更新了 13 个直接依赖模块:JWX 3.4.0、etcd api / client/pkg / client 3.7.3、gRPC 1.84.0、grpc-gateway 2.32.0、go-json 0.11.2、swag/conv 0.29.2、go-colorable 0.1.16、cpuid 2.4.1、fwd 1.2.1,以及固定在 ce908d29299b 的两个 Google API/RPC 生成模块。
下游应用需使用 Go 1.27.3 重新编译以纳入标准库证书校验修复。公开包 API、IAM 策略格式、授权判定逻辑以及 v3.14.3 的策略匹配性能优化均保持不变。
3.15.1:上游 S3 SDK 修复
v3.15.1 将上游 minio-go 从 v7.4.1 推进至 ab93db7ba435,合入了以下修复:
- 在发送不完整分片前直接拒绝被截短的顺序或并行流式分片上传。
- 修复
ReadAt到达 EOF 后的顺序读取状态,并在访问元数据前拒绝负偏移参数。 - 修复调用
Object.Stat之后的读取与Seek边界计算。 - 对批量删除回退路径中的重复错误去重,确保每个失败项只上报一次。
3.15.2:移除桶复制配置兼容
v3.15.2 进一步选用上游 v7.4.2-0.20261025165926-320af050c445(伪版本,上游尚未打 v7.4.2 标签)。移除存储桶复制配置(含向 SetBucketReplication 传入空配置)现在同时接受服务端返回 HTTP 200 与 HTTP 204,而 AccessDenied 等真实鉴权或请求失败仍正常返回错误(见上游提交对比)。
兼容性与验证
为保持既有 CLI 输出格式与 NetBSD 编译兼容,下游应用继续固定 go-humanize v1.0.1、go-runewidth v0.0.29 与 go-systemd/v22 v22.6.0。由于 Go 不会传递继承依赖模块的 replace 指令,各嵌入方需在自身 go.mod 中显式声明所需的模块替换。
v3.15.2 已通过含 LDAP 集成在内的全量 lint 与 -race 竞态测试、模块校验及三项 CI 流水线(Go、LDAP、VulnCheck)。HTTP 协议夹具验证了两个复制移除入口均同时接受 200/204 并保留 403 错误;此前的 3.15 依赖回归测试亦覆盖了 JWT 校验边界、本地 etcd 认证/Watch/租约持久化及 CLI 输出格式。模块级扫描中的 GO-2026-5932 位于未被导入的弃用 OpenPGP 包中,不影响运行代码(详见统一安全审计清单)。
silo-pkg 仅作为 Go 源码模块发布,Server、Console 与 mcli 通过重新编译集成该版本。正式维护的依赖组合为 PGSTY 组件栈,对上游 MinIO/MC 保持尽力而为兼容。GitHub Release · 完整源码对比。
19 - Silo Console 2.1.0 发布
发布日期: 2026-08-06 · 版本: v2.1.0 · 仓库: pgsty/silo-console
SILO Console 2.1.0 是独立发布 2.0.0 之后的第一个功能版本,主要包含三项改进:
- 双语界面——全部控制台页面、帮助条目与文档链接支持中英文切换,切换按钮出现在每一页,且不引入新的运行时依赖;
- Metrics V3 仪表盘——仪表盘从 MinIO Metrics V2 指标迁移到 V3,并针对 V3 改变的底层语义做了显式适配;
- 边界场景正确性修复——全选框与批量操作作用于同一批对象,占位符兼容包含
$&的对象名,时间戳统一携带时区,空指标显示“无数据”而非虚构的0。
这是一个 小版本。环境变量、模块路径、API 契约、二进制名称和数据布局均无变化,升级就是换二进制或换镜像。
同日已发布 2.1.1 补丁
v2.1.1 与本版本同日发布,补全了下文所述的图例加固:图例构造器无法解析的标签占位符会被直接移除,而不是把字面花括号漏进 Traffic 图表的图例;最后一处替换分支也完成了转义加固,标签值中的 $& 或 $1 不会再被当作替换指令;License 页面显示的版本号也从 2.0.0 修正为实际版本。除此之外没有任何变化——直接升级到 2.1.1 即可,本文所有内容照旧适用。
如果你内嵌了这套控制台,请重新生成嵌入资产
2.1.0 修复了 2.0.0 之后 main 分支上的一个打包缺陷:go:embed 负载中仍是 2.0.0 的前端构建产物,因此从中间提交构建出的二进制会提供旧版界面。2.1.0 的正式发布产物基于重新生成的负载构建,不受影响。
双语控制台
这是一套对象存储的管理界面,而它的运维使用者中有相当一部分以中文为第一语言。2.1.0 在不引入 i18n 框架的前提下把界面变成双语——嵌入式交付意味着每一 KB 都要计入二进制体积。这对应 issue #6:该 issue 原本提议使用 i18next,而"零依赖"是本次实现相对它唯一一处有意的偏离。
实现方式
设计约束是:不加新依赖、不加构建步骤、不引入字符串抽取流水线,并且 部分覆盖绝不能让页面出错。
- 英文原文就是字典的 key。
t("Create Bucket")查找对应的中文条目;查不到则原样返回英文。因此覆盖度可以增量生长,写错 key 的后果是退化成英文,而不是暴露console.bucket.create这样的裸标识。 - 三份字典,一次合并。
zh.ts(165 条界面框架)、zhHelp.ts(247 条帮助内容)、zhScreens.ts(1373 条功能页面)合并时以框架优先,合计约 1785 条。 - 语言偏好完全复用暗色模式的模式:
localStorage→systemSlice→setLanguage。不做浏览器语言探测,默认英文,选择完全显式。 - 集中拦截而非逐点改写:页头包装器、确认对话框、帮助条目、路由定义、仪表盘面板渲染器各自在输出的最后一步翻译。这正是 220 个页面文件能够在不触碰业务逻辑的情况下完成本地化的原因。
- 模块拆分是必要的。
i18n/lang.ts只存放纯函数原语(translate、localizeUrl)且不导入 store——systemSlice依赖它,反向导入会形成循环依赖。Hooks(useT、useLanguage、useLocalizedLink)与interpolate()放在i18n/index.tsx。
切换控件是一个描边风格的 文/A 图标,挂载在所有页面的页头,登录页复用同一控件。
覆盖范围
登录与 SSO 流程、导航与命令面板、仪表盘与全部指标面板、存储桶与完整对象浏览器(上传、预览、分享、版本、回溯)、用户/用户组/策略/访问密钥、配置与事件目标、IDP 与 KMS、日志、健康报告、性能测试、性能剖析、对象检查、跟踪、监视,以及许可证页面。
除可见文本之外:
- 文档链接会本地化。
silo.pgsty.com的链接在中文下加/zh前缀;Pigsty 站点做域名对调(pigsty.io↔pigsty.cc)。GitHub、MinIO、AWS、YouTube 链接保持不变。 - 帮助面板的博客源按语言区分,中文下拉取
/zh/blog/index.xml,并为每种语言维护独立缓存。 - 命令面板在两种语言下都能搜到。菜单项显示时翻译,但保留英文原文作为关键词,因此"桶"和 “buckets” 都能命中。
- 图表图例只翻译静态前缀。
translateLegend保留[server:drive]这类实例后缀;数据层保留原始图例,所以那些依赖图例做数值匹配(容量求和)的组件继续正常工作。 - 时间戳统一携带时区格式,详见下文。
代价
嵌入负载增加约 61 KB(2.79 MB → 2.85 MB,+2.2%),零新增依赖,字典进入独立的按需加载分块。英文渲染路径字节稳定:使用默认语言时,输出与 2.0.0 完全一致。
保持英文的字符串
后端错误信息(182 条)由 Go 服务端产生,前端无法翻译。少量硬编码在 vendored mds 组件库内部的字符串——收起态菜单的 “Sign Out” 提示,以及数据表格的 “Columns”、“Loading…” 和 ON/OFF 开关——仍是英文;其中两处(“Sign Out”、“Actions:")通过作用域 CSS 规则做了中文替换,其余需要改动 vendor 才能处理。
Metrics V3 迁移
仪表盘此前查询的是 MinIO Metrics V2 名称,而 SILO 部署抓取的是 V3(/minio/metrics/v3)——也就是说,仪表盘依赖的是监控流水线已经不再采集的端点。2.1.0 将全部 26 个部件 重写到 V3 目录——31 条查询,涉及 29 个不同的指标名——并移除三个从未被任何布局引用的部件(51/61/62)。这对应 issue #7,Info 页面的那一半是 #8。
这里的决定是 V3 only:不做运行时回退、不做探测、不提供版本选择开关。SILO Console 面向的是 SILO 部署,服务端、抓取流水线与控制台是一同交付的。SILO 服务端继续为外部消费者提供 V2 端点,只是控制台不再使用。回退机制在这里反而有害——保留 15 天 V2 序列的指标库会让 or 回退悄悄读到过期数据。
V3 改变的语义
有三条 V3 特性会让"照名字改写"的迁移出错,每一条都需要明确的应对:
- 集群组指标由每个节点重复导出。
/cluster/*指标不带 server 标签,也不做 leader 门控,因此 N 节点的抓取会得到 N 条重复序列。查询统一用max()/min()聚合——绝不能用sum(),那会把集群总量乘以节点数。 - 零值默认不导出。任何取值 ≤ 0 的指标都会被跳过,离线磁盘数、修复中磁盘数、纠删集健康状态在取值为零时会直接从指标流中消失,导致统计卡片渲染成空白面板。所有受影响的查询都配了伴随守卫,让面板读出真实的
0。 - 移除
minio_heal_*命名空间。V2 的修复活动信号本身是内存态的(重启即清零,任意扫描都会刷新),现替换为两张语义明确的卡片:纠删健康(以写入法定人数为基线)和 用量数据时效(扫描器用量快照的陈旧程度)。
零值语义
本次迁移针对八类边界场景明确区分了 零值、无数据 与 尚未完成首次扫描:
- 容量 的空闲/已用以恒定存在的总量为基线,因此写满的集群显示
0 空闲,而不是整个消失。 - 在线磁盘 针对全部离线的场景加了守卫——恰恰是最需要看到这个数字的时候,零值跳过会抹掉面板。
- 桶与对象计数 改用用量组自身的新鲜度指标做守卫,因此尚未完成首次扫描的集群显示 无数据,而不是编造一个
0。 - 空的单值结果 渲染为
—,而不是0。 - 空的大小分布 不再伪造七个零高度的柱子。
- 小数速率保持可见(
parseFloat轴域、两位小数的 CPU 格式化器),不再被压成0。 - 不足一秒的用量数据时效 收敛到"1 秒”,而不是渲染成空白。
回归测试套件(api/admin_info_metrics_test.go)现在把每条部件查询钉死在 V3 目录上,校验部件 ID 唯一性,并强制执行逐部件的守卫分类法:健康与流量类需要在线节点数伴随项,用量计数类需要用量组新鲜度伴随项,容量类需要总量基线。完整映射记录在 docs/metrics-v3.md。
顺带修复
- 部件 17 把
sent_bytes查了两次,部件 11 把syscall_read查了两次——两组节点间/系统调用的收发配对都退化成了重复项。 - 无标签矩阵(
max()聚合的结果)序列化时 完全没有metric字段,导致前端的标签提取崩溃,表现为容量环图显示0 B、用量增长图为空。已加守卫。 - 一个从未被使用的逐部件 Prometheus label-values 预取请求,让每次部件请求最多多等一秒。已删除。
- 仪表盘的用量卡片、图表控件以及密集的流量/资源面板按统一语法重建,现在在平板宽度下也能正常重排。
工作中还发现两个 服务端 缺陷,选择上游跟踪而非在此绕过:minio_cluster_usage_buckets_since_last_update_seconds 发出的是纳秒(对象变体是正确的),以及 V3 桶级发送/接收流量被对调。
正确性修复
能扛住真实对象名的占位符
String.prototype.replace 会把 替换值中 的 $&、$'、$`、$1 当作指令解释。而 S3 的 key 合法地允许包含 $。于是一个名为 report$&.csv 的对象不会按原样渲染——它会把匹配到的占位符文本重新注入输出,破坏整条消息。全部 37 处 字典占位符替换现已改为传入函数形式的替换值,函数形式不做任何此类解释。该缺陷原本就存在于英文界面中,在本次本地化排查时一并检出修复。
与批量操作一致的全选
vendored 数据表格在缺少 onSelectAll 时会渲染一个无法翻译的纯文本 “Select” 表头——七张可选表格全都如此。更麻烦的是,直觉的修法是错的:直接用可见行替换整个选择集,会 丢掉被当前过滤条件隐藏的行,于是表头复选框与随后的批量操作可能作用于不同的集合。实现只切换当前可见行,并保留被过滤隐藏的选择,因此表头状态不可能再暗示一个与实际操作对象不同的集合。
带时区的时间戳
桶、对象、版本、回溯与访问密钥的时间戳此前混用冗长英文格式,并且有几处使用 不带 AM/PM 的 12 小时制——这根本是歧义的。现在它们在两种语言下统一渲染为 yyyy-MM-dd HH:mm[:ss] (ZZZZ)。
扛得住实时数据的翻译运行时
t() 同样会收到运行时字符串:User-Agent、RSS 标题、对象名。由此做了两项加固:
- 未命中时 无条件原样返回——隐式的
@context后缀剥离被移除,因为它会悄悄改写恰好含有@的实时数据; - 字典查找加上
hasOwnProperty守卫,因此恶意输入即便命中继承自Object.prototype的成员(constructor、toString)也无法把函数泄漏到界面上。
交互与可访问性
- 会话过期后打开深链会在
/login之间 来回弹跳,不断累积重定向链,而不是干脆落到登录表单上(#1)。 - 收起态的侧边栏按钮没有可访问名称,屏幕阅读器只能报为未命名控件(#4)。访问密钥输入框现在显式声明 autocomplete 意图,而不是让密码管理器去猜(#5)。
- 移动端的指标与存储桶面板改为滚动,不再被裁切(#3)。
- 性能测试的控件行改为换行而不是溢出卡片,时长可填秒或分钟,大小的默认单位改为 MiB 以匹配其自身的单位列表。
- 侧边栏桶列表的虚拟行距与 44px 的行高对齐,选中与悬停高亮不再互相重叠。
- 单位标签渲染所选单位的 显示名,而不是原始取值。
没有 SUBNET,没有遥测
上游已移除 Subnet、Registration 与 Call Home,本项目继承了该状态,但仍残留三处痕迹。2.1.0 予以清除:
- 健康诊断 websocket 的
subnetResponse字段从来就不指向任何 subnet——它只是一个"报告已生成"的哨兵值——现改为reportStatus: "ok"; - 两条帮助文案声称健康报告"会自动上传到 SUBNET"、检查输出"传输到 SILO SUBNET"。两者都不属实。它们现在描述真实行为:报告在部署端生成,由浏览器下载;
- 删除从未被引用的
CONSOLE_SUBNET_PROXY常量。
顺带说明,2.1.0 的出网行为没有变化,仍然是:无分析、无遥测、无埋点、无外部脚本与字体。silo-console update 依旧禁用。版本目录仅在显式设置 SILO_RELEASE_SERVICE_HOST(或 RELEASE_SERVICE_HOST)时才会连接——没有默认值。浏览器唯一的自动出网请求是帮助面板的博客源,且只在用户打开 Blog 标签页之后发生。
升级指南
没有任何需要迁移的内容。2.0.0 到 2.1.0 之间,环境变量、模块路径、协议字段、systemd 单元、二进制名称与数据布局均无变化。
有两点值得知道:
- 仪表盘现在要求 Metrics V3。如果你的 Prometheus 只抓取 V2 端点,仪表盘面板会显示无数据。请把抓取目标指向
/minio/metrics/v3;由 Pigsty 管理的部署已经如此。 - 语言默认为英文,按浏览器选择并存入
localStorage。不存在服务端默认值,也不做浏览器语言探测,因此现有部署升级后外观不会发生变化。
验证范围
打标签之前,针对最终代码树执行了以下门禁:go build、go vet、golangci-lint(0 问题)、全部 Go 包的单元测试、gofmt、TypeScript 类型检查、前端生产构建、全量 Prettier 检查、字典重复 key 检查,以及对完整 diff 的调试残留扫描。
嵌入负载从干净目录重建两次并确认逐字节一致,满足发布流水线零差异门禁的要求;Metrics V3 查询已在含真实集群数据的线上指标库上完成验证。
已知限制
- SSO 端到端测试套件依赖外部 OpenLDAP/Dex/MinIO 拓扑,本轮未在该环境中运行;OIDC 代码路径已由单元测试覆盖。
- 后端错误信息与若干 vendored
mds组件字符串仍为英文(见保持英文的字符串)。 - 中文翻译覆盖控制台自身的界面;帮助条目正文已翻译,但它们所链接的文档页面遵循文档站自身的语言覆盖情况。
- 两个服务端 V3 指标缺陷(桶用量时效的纳秒单位、桶级流量对调)在上游跟踪,控制台侧未做绕过。
- 自动自更新仍然禁用,升级需要显式执行。
已关闭的 Issue
2.1.0 关闭了针对 2.0.0 提出的全部 issue。每个 issue 在 tracker 上都留有一条评论,说明修复方式、涉及的提交,以及补充的测试覆盖。
| Issue | 解决方式 |
|---|---|
#1 — 未认证深链无限递归 /login |
改为绝对且感知 base path 的登录目标;补充深链与子路径部署的测试 |
| #2 — Uptime 陈旧、图例畸形、菜单局促 | Uptime 取自真实服务器状态,图例改用 V3 的 name 标签解析,图表控件 32 px,弹出菜单设最小宽度 |
| #3 — 390 px 视口裁切内容 | 指标标签页改为可横向滚动;桶列表在移动端使用明确的列宽预算 |
| #4 — 收起态侧边栏按钮无名称 | 标签改为视觉隐藏而非从可访问性树中移除;折叠开关具名且可键盘操作 |
| #5 — 访问密钥字段缺少 autocomplete 元数据 | 在独立的自动填充 section 中声明 username / new-password 字段级 token |
| #6 — 中英文本地化 | 手写双语层,零新增依赖,以英文原文为 key 兜底 |
| #7 — 监控查询迁移到 Metrics V3 | 仅 V3;26 个部件、31 条查询、29 个指标名,配套守卫分类与回归测试 |
| #8 — 用可用的 V3 健康信号替换 N/A | Erasure Health 与 Usage Data Age,与高级仪表盘共用同一份部件数据 |
有三项验收标准如实记为未达成,而不是含糊勾掉:web-app 目前没有单元测试运行器,因此 #6 的 i18n 测试套件与 #2 中针对 constructLabelNames 的专项测试都需要先引入测试工具链;另外 #6 要求的"如何新增翻译 key"的贡献者文档尚未编写。
关联提交与链接
v2.1.0 的完整变更由以下 20 个逻辑提交构成。v2.1.0 标签另外还带有三个更晚的文档提交,它们重写了仓库 README,不改变任何已交付的行为。
8764f5d— fix(web): stop recursive login redirects437c56c— fix(ui): make the dashboard and bucket list usable on narrow screens85fc0c6— fix(a11y): name collapsed sidebar controls and credential fieldse3fed07— fix(metrics): rebuild dashboard cards, chart controls, and layoutfa11576— feat(login): polish controls and legal attribution9fc17c1— feat(i18n): add hand-rolled EN/ZH core, dictionaries, and language toggle622c02e— feat(i18n): localize login, navigation, and the help system6a03719— feat(i18n): localize dashboard and metrics screens14b1c2d— feat(i18n): localize bucket and object browser screens0298062— feat(i18n): localize identity, configuration, and event destinations41094f6— feat(i18n): localize observability, admin tools, and shared componentse964992— feat(metrics): migrate the dashboard to MinIO Metrics V30b2251f— fix(i18n): harden the translation runtime for live data and chart legends9b60148— fix(console): unify timestamps on a timezone-carrying standard formatbf110ae— fix(console): give selectable tables a visible-rows select-all5fc8f22— fix(i18n): escape-proof all placeholder substitutionsfef8fab— fix(console): polish speedtest, sidebar, and help chromec4911e8— chore(console): drop SUBNET remnants from health reporting1d631c4— docs: record the SILO Console v2.1.0 changelog912d847— build: regenerate optimized embedded web assets
相关链接:
20 - Silo Console 2.0.0 发布
发布日期: 2026-08-04 · 版本: v2.0.0 · 仓库: pgsty/silo-console
SILO Console 2.0.0 是这套对象存储管理控制台以独立项目身份发布的第一个主版本。它从 georgmangold/console 的 v1.9.1 维护线继续演进,完成了三件事:
- 建立独立身份——产品名称、视觉系统、文档入口、源码归属与发布链路全部迁移到 SILO 项目体系,同时保留 Go 模块路径、环境变量等兼容契约;
- 重塑用户界面——登录页、主题系统、仪表盘与全站细节按统一的设计语言重新打磨,配套全新的品牌图标集;
- 强化工程质量——嵌入式前端资产从约 10MB 压缩到 3.5MB,已知依赖漏洞清零,并修复了包括运行时数据竞争在内的一批上游遗留缺陷。
升级前先看兼容边界
2.0.0 的主版本变更集中在 公共身份和交付契约,对象数据格式与 S3 协议保持不变。使用旧仓库、旧发布二进制名或旧容器镜像名的安装脚本必须更新;使用 CONSOLE_MINIO_SERVER、CONSOLE_MINIO_REGION、github.com/minio/console 或 MinIO 兼容 Admin API 的现有集成保持原样,不应做全局替换。
为什么是 2.0.0
这套控制台最初源自 MinIO Console,随后由 Alevsk/console 与 georgmangold/console 两条社区维护线继续发展。SILO Console 在此基础上由 Pigsty 社区接续维护,为 SILO 提供浏览器管理界面。
版本号从 v1.9.1 提升到 v2.0.0,主要是因为以下对外契约同时发生变化:
- 产品名称统一为 SILO Console,主仓库迁移到
pgsty/silo-console; - 正式发布二进制从
console改为silo-console; - 发布资产、校验和、软件包元数据、命令行说明与项目链接全部切换到 SILO;
- 界面中的项目身份、帮助入口、版权归属、源代码供应与商标说明重新建立。
2.0.0 采取的是"对外身份清晰、对内兼容克制"的迁移策略:需要运维人员明确感知,但不对底层兼容接口做机械式改名。
名称与交付契约
| 范围 | 旧名称或旧位置 | 2.0.0 契约 |
|---|---|---|
| 产品 | Console / MinIO Console 的遗留表述 | SILO Console |
| 源码仓库 | georgmangold/console |
pgsty/silo-console |
| 正式二进制 | console |
silo-console |
| 二进制资产 | console-<os>-<arch> |
silo-console-<os>-<arch> |
| 校验和文件 | console_<version>_checksums.txt |
silo-console_<version>_checksums.txt |
| 网站与文档 | 上游或前维护者入口 | silo.pgsty.com 与 silo.pgsty.com/docs/ |
容器部署使用 Docker Hub 的 pgsty/silo-console,当前版本及拉取命令见 Console v2.4.1 发布说明。
命令行程序的作者、用途、帮助文本和项目描述已切换为 Pigsty 与 SILO Console。DEB/RPM/APK 软件包的厂商、维护者、主页、描述与许可证元数据相应更新,可执行文件安装到 /usr/local/bin/silo-console。
刻意保留的兼容标识
以下名称保留 minio 或 console,属于接口、协议或安装兼容层的一部分:
| 兼容面 | 2.0.0 中的状态 | 原因 |
|---|---|---|
| Go 模块 | 保持 github.com/minio/console |
改动会破坏全部 Go import 与生成代码 |
| 服务端地址 | 保持 CONSOLE_MINIO_SERVER |
现有部署广泛使用的环境变量 |
| 服务端区域 | 保持 CONSOLE_MINIO_REGION |
现有部署兼容契约 |
| 其他配置 | 既有 CONSOLE_* 变量继续有效 |
避免无收益的配置迁移 |
| S3/Admin API 名称 | 保留 MinIO-compatible 字段与枚举 | 它们描述实际协议和 SDK 接口 |
| 源码开发产物 | make console 仍生成 ./console |
保持开发工作流和脚本兼容 |
| 软件包 systemd 单元 | 保持 minio-console.service |
避免升级时出现两个服务或丢失原服务状态 |
| systemd 用户与配置 | 保持 console-user 与 /etc/default/console |
避免不必要的账户和配置文件迁移 |
因此,升级脚本不能执行全仓库或全配置的 minio → silo、console → silo-console 替换。未来若要迁移这些兼容接口,需要提供别名、弃用周期和明确的双读策略。
全新界面
2.0.0 对整套控制台界面进行了端到端重构。
登录页
登录页完全重写:左侧品牌面板以纯 Canvas 生成缓慢流动的正弦光网动画(零外部依赖,遵循 prefers-reduced-motion,切至后台标签页时暂停),文案以 “Keep the S3 Interface / Own the Object Store” 呈现项目主张,底部保留完整的 MinIO 商标声明;右侧表单功能与既有自动化测试选择器完全不变。SILO 字标所用的 Chakra Petch 字体以约 20KB 的本地子集打包,不产生任何外部网络请求。
统一主题系统
控制台的全部颜色收敛到一个亮暗两套的主题层:中性灰阶承载正文与边框,品牌钢蓝色承载主操作与选中态,侧边栏在明暗模式下统一使用与登录页同源的深色系。表单控件与卡片采用统一的圆角与过渡,输入框获得键盘焦点光环,模态框有入场动画(同样遵循 reduced-motion)。服务端下发自定义样式(customStyles)的优先级保持不变。
控制台细节
- 仪表盘(Metrics):统计卡片按统一语法重构——弱化标签、等宽数字、状态圆点对齐;环形图与信息条接入主题;移除了上游实现中的绝对定位布局。
- 空态统一:Watch、Trace、桶事件/复制/生命周期等所有数据面板的占位文本统一为居中弱化样式,不再是左上角的裸文本。
- 垂直选项卡:桶详情等页面的选项卡从带边框的灰色矩阵改为安静的药丸列表,并消除了栏底的空白残留格。
- 许可证页:新增 VERSION 区,同时显示所连接服务端的版本与 Console 自身版本;无
admin:ServerInfo权限的账号不会发起请求,该行自动隐藏。页面同时集中说明 AGPLv3 授权、AGPL 第 13 节下的源码获取权利、来源谱系与商标边界。 - 一批交互修复:移动端首次加载即收起侧边栏(原先要等窗口 resize 事件);侧边栏底部导航不再在窗口高度变化时延迟跟随;桶列表手风琴的高亮条铺满整行;仪表盘在窄屏下不再产生隐式横向溢出;帮助面板改为真正的按需加载——登录页不再向任何外部站点发起请求。
品牌图标集
favicon、PWA 与 Apple Touch 图标此前仍是上一代手绘徽标的 PNG 导出。2.0.0 将全部尺寸(ico 16+32、favicon 16/32/96、apple 180、manifest 192/512)从官方 silo.svg 矢量徽标重新光栅化,主屏尺寸带防裁切安全边距;Web App Manifest 裁剪为现代图标集,移除 2014 时代的 legacy density 条目。图标总体积从 473KB 降至 160KB,浏览器标签页图标从此与站内品牌完全一致。
更小、更快
嵌入式交付是这套控制台的核心形态——前端资产通过 go:embed 打进二进制。2.0.0 对这条链路做了系统性优化:
- 嵌入负载从约 9.6MB 降至 3.5MB。文本资产(JS/CSS/SVG 等)在构建期以确定性 gzip 预压缩后嵌入;仅被现代浏览器忽略的 legacy WOFF 字体(约 1.25MB)、以及一批完全未被引用的孤儿图片资产被移除。
- 首屏传输从约 5.7MB 降至约 1.7MB。此前静态资产完全未压缩传输;现在预压缩资产直接以
Content-Encoding: gzip发出(零运行时压缩开销),对极少数不接受 gzip 的客户端动态解压回退。 - 正确的 HTTP 语义。Accept-Encoding 按 RFC 9110 完整解析 q 值(
gzip;q=0会得到未压缩内容),响应携带Vary: Accept-Encoding;静态路径与 SPA 入口对非 GET/HEAD 请求返回 405 并带Allow头。 - 可复现构建。压缩使用纯 JS 实现(fflate)以保证跨平台字节级确定性;发布流水线新增强制门禁——在干净环境重建嵌入资产后必须与提交内容零差异。
发布二进制(含全部前端资产、strip 后)约 35–40MB;对下游 SILO 服务端而言,内嵌这套控制台的体积代价从约 10MB 降到约 3.5MB。
安全与依赖
Go 侧:构建基线升级到 Go 1.26.5,golang.org/x 系列全部更新至最新。govulncheck 报告的全部可达漏洞已清零:
| 依赖 | 修复版本 | 公告 |
|---|---|---|
google.golang.org/grpc |
v1.82.1 | GO-2026-6061 |
github.com/prometheus/prometheus |
v0.311.3 | GO-2026-5710 / -5662 / -5381 / -5264(含远程读 DoS) |
github.com/klauspost/compress |
v1.18.7 | GO-2026-5841 |
唯一剩余公告位于 golang.org/x/crypto,官方尚未发布修复且代码路径不可达,作为已知事项记录。
前端侧:生产与开发依赖树的完整审计清零,包括 form-data 的高危 CRLF 注入、DOMPurify 与 qs 的多项公告;React Router 迁移至 7.18.2(保留 v6 兼容的声明式 API,全站路由经过完整回归验证)。唯一被显式豁免的公告仅涉及本项目未使用的 unstable API。
运行时正确性:修复了 HTTP 日志目标在初始化与关闭之间的真实数据竞争,以及测试套件中共享 mock 的竞态;受支持的 Go 包全量通过 -race 检测。作为附带收益,go-m1cpu 升级修复了新版 macOS 上本地 go run 的 cgo 崩溃。
更新检查与默认网络行为
本版本对升级和版本目录功能采取保守默认:
silo-console update的自动自更新被禁用,命令只给出提示,不会下载或替换二进制;- 版本目录新增
SILO_RELEASE_SERVICE_HOST配置,原有RELEASE_SERVICE_HOST作为兼容回退;两者均未设置时不连接任何远端版本服务; - 帮助面板的 Blog 内容仅在用户打开时按需拉取,跳转链接只接受
https://silo.pgsty.com。
自动更新会在发布资产签名与回滚链路稳定后再重新评估。
发布产物与平台矩阵
正式发布包含 16 个资产:
| 类型 | 覆盖范围 |
|---|---|
| 独立二进制 | Linux amd64/arm64/arm、macOS amd64/arm64、Windows amd64 |
| 系统软件包 | DEB / RPM / APK × amd64/arm64/armv6 |
| 校验和 | silo-console_2.0.0_checksums.txt(SHA-256) |
发布流水线在 tag 推送时触发,工作流的第三方 Action 已固定到具体提交,并在构建前强制执行"干净检出 + 资产重建零差异"门禁。
升级指南
独立二进制
从源码构建时,make console 仍生成 ./console;用于正式服务前按发布名称安装。
DEB/RPM/APK 与 systemd
软件包继续安装 /etc/systemd/system/minio-console.service,单元内部启动 /usr/local/bin/silo-console。EnvironmentFile=/etc/default/console、console-user 与既有 CONSOLE_* 变量不变。这个保留让软件包升级继续作用于原有服务,而不是平行创建一个新服务。
配置与集成
- 不要重命名
CONSOLE_MINIO_SERVER或CONSOLE_MINIO_REGION; - 不要修改 Go import 中的
github.com/minio/console; - 自建版本目录优先迁移到
SILO_RELEASE_SERVICE_HOST; - 依赖
console update的脚本改为显式下载、校验并部署发布资产; - 按进程路径识别服务的监控更新为
/usr/local/bin/silo-console。
本版本不改变对象数据布局,也不要求对存储桶和对象执行迁移。
验证范围
发布验证覆盖 Go 全包 -race、go vet、golangci-lint、govulncheck、前端类型检查、生产构建、Prettier、死代码检查与完整依赖审计,并执行了以下专项校验:
- 对全部 184 个嵌入文件各发起 gzip 客户端、普通客户端与 HEAD 三种请求,响应体与嵌入源做逐一哈希比对;
- RFC 语义探测(含
gzip;q=0, *;q=0.5等组合 q 值)、方法限制、OIDC 回调与 SPA 深链; - React Router 7 全站路由回归:深链、客户端导航、桶详情选项卡切换与浏览器历史后退;
- 移动端首屏侧边栏行为、登录页外部请求监听、明暗主题全站巡回;
- 下载正式发布资产验证校验和逐字节匹配、二进制版本自报一致,并用发布产物直连真实服务端完成冒烟测试;
- macOS 与 Linux 双平台的资产重建零差异验证。
已知限制
- 自动自更新暂时禁用,升级需要显式执行;
- SSO 端到端测试套件依赖外部 OpenLDAP/Dex/MinIO 拓扑,本轮未在该环境中运行(OIDC 代码路径已由单元测试与 HTTP 层验证覆盖);
golang.org/x/crypto存在一条官方尚未发布修复、且代码路径不可达的公告;- SILO 尚未维护独立的视频资料库,帮助面板中的视频是明确标注的上游兼容性资料;
- 管理能力依赖 MinIO-compatible Admin API,不能把 SILO Console 当作适用于任意 S3 服务的通用浏览器;
- 保留的 Go 模块、环境变量、协议字段和 systemd 服务名仍会在代码、配置和进程管理界面中出现。
关联提交与链接
v2.0.0 的完整变更由以下 8 个逻辑提交构成:
50797de— feat: establish SILO Console identity and compatibility23ae6e8— feat: redesign and harden the SILO Console web app7a83a77— build: update Go toolchain and dependencies1330d25— fix: eliminate logger shutdown and test mock races06b3a34— docs: publish the SILO Console v2.0.0 guide4b24372— build: regenerate optimized embedded web assetsc38eb64— ci: package and publish SILO Console v2 releasesb952a12— brand: regenerate the icon set from the official silo.svg emblem
相关链接:
21 - silo-pkg 3.13.0 正式发布
发布日期: 2026-08-30 · 版本: v3.13.0 · 提交: 215f116 · 仓库: pgsty/silo-pkg
3.13.0 是一个破坏性版本:本模块正式启用独立导入路径 github.com/pgsty/silo-pkg/v3,同时退役 pgsty/silo-go 分支,直接依赖上游 minio-go。维护栈各组件(silo、silo-console 与 mcli)均已在 2026-09-03 / v2.4.0 版本波次完成新路径迁移,详见组件版本矩阵。
版本速览
- 已发布:
silo-pkg v3.13.0标签与 GitHub Release,声明module github.com/pgsty/silo-pkg/v3。 - 已终结:
github.com/minio/pkg/v3模块身份,以及每个消费者都必须重复一遍的replace指令。 - 已终结:
github.com/pgsty/silo-go/v7分支,本版本直接依赖上游minio-go。 - 未变: 所有包、符号与行为。移动的只是它们被导入的路径。
- 下游接入: 已在 SILO 20260903、Console v2.4.0 与 mcli 20260903 完成同步迁移。
为什么要迁移路径
此前本分支保留上游的 github.com/minio/pkg/v3 路径,以便充当直接替代品——消费者用一条 replace 指令即可选中它。但 Go 不会继承依赖模块声明的 replace,在准备下一个 SILO 服务器版本时,这套安排的三笔账同时到期。
每个消费者都要重复一遍重定向,漏写的那个会静默构建到上游。 一个依赖了本包却没写 replace 的模块,会解析到真正的 minio/pkg,编译通过,然后悄无声息地失去本分支的行为。
require 那行必须写一个源码早已不匹配的版本。 ParseConfigStrict 在上游要到 v3.11.0 才出现,Resource.IsBareARN 则在任何上游版本都不存在。当源码需要 v3.12 的 API,旁边却写着 require github.com/minio/pkg/v3 v3.6.1,这是靠改数字无法变真的元数据。
为此打的补丁还会传播。 pgsty/mc 里有一行纯粹为此存在的编译期哨兵——引用 Resource.IsBareARN——目的是把静默降级变成响亮的构建失败。而把 mc 的下限抬高、让元数据变诚实,又会通过模块图把要求推上去,顶高 silo-console 那条刻意压低的下限——那条下限存在的意义恰恰是防止这件事。
上游路径在这里能提供的回报很少:minio/pkg 是一个小型内部库,而本模块的消费者只有 silo、silo-console 和 mcli。Silo Go SDK 则保留上游的 github.com/minio/minio-go/v7 路径——那里的直接替代能力有真实价值,上游也仍在积极维护。
上游 minio-go 取代 Silo Go SDK
pgsty/silo-go 已经不再包含任何功能性差异。它唯一独有的改动 Return CopyObject checksums in UploadInfo 已于 2026-08-24 合入上游,其余内容只是一个版本字符串、一个 logo、一份 README 和一段 lint 工具声明。
上游最新标签 v7.3.0 比该合并早 14 个提交,其中包括并行分段上传中共享校验和哈希器的数据竞争修复,因此钉住这个标签反而是倒退。本版本改为依赖伪版本 v7.3.1-0.20260828014306-0e78d3f18efe,待上游切出新标签后再换成标签。
兼容性
所有包、导出符号与行为均未改变。本版本移动的是它们被导入的位置,仅此而已。
请与 silo、silo-console、mcli 的配套改动一起采用。单独升级本包的消费者将无法构建——新旧路径是两个不同的模块,类型无法在它们之间传递。
变更前:
变更后:
并把 github.com/minio/pkg/v3/... 的导入改写为 github.com/pgsty/silo-pkg/v3/...。继续沿用旧安排的消费者仍可构建于 v3.12.2 及更早版本之上,这些版本依然可用。
有一个后果值得预期:两条路径现在是不同的模块,因此一次构建里可能同时包含两者——某个第三方依赖若导入 github.com/minio/pkg/v3,它的导入不再被重定向。在 SILO 技术栈中这种情况只出现一次,来自 minio/colorjson 与 minio/dperf,二者都只用到 pkg/v3/console。而该包的颜色开关是 fatih/color 的进程级全局变量 NoColor,所有副本共享同一个,因此关闭颜色仍然会在各处一并生效。
验证
go build ./...、go vet ./...、go mod tidy -diff、gofmt -l .全部干净;go test ./...通过 23 个包。- 发布提交上的 CI:Go、LDAP Config Validator、VulnCheck。
- 新路径已由一个不带任何
replace指令的全新模块从模块代理解析成功,导入policy并运行通过。 - 下游迁移在发布前已端到端验证:
mcli(194 个文件)、silo-console(36 个文件)与silo(181 个文件)均通过构建、vet 与各自测试套件;silo的 rebrand guard 通过,兼容基线差异恰为 19 条被删除的导入记录,环境变量、指标、请求头、路由、策略取值与导出符号均无变化。
22 - silo-pkg 3.12.0 正式发布
发布日期: 2026-08-24 · 版本: v3.12.0 · 提交: 2b087a1 · 仓库: pgsty/silo-pkg
3.12.0 是直接从主线发布的中版本,包含两条主线:第一,为“只有 ARN 命名空间前缀、却没有指定任何资源”的策略增加严格写入保护;第二,把维护基线推进到 Go 1.27 与 etcd 3.7。它新增两个导出的检查/校验方法,将验证过的消费者下限提高到 Go 1.26;同时也是第一个由 SILO 服务端(eee05a17c,SN-2026-005,随 SILO 20260903 发布)在具名策略与服务账号策略写入路径上启用严格校验的 silo-pkg 版本。
发布状态一览
- 已经发布:
silo-pkg v3.12.0标签、GitHub Release,以及裸 ARN 前缀的严格库级校验。 - 服务端接入:
eee05a17c(SILO 20260903)在具名策略与服务账号策略写入路径启用严格校验。 - 刻意保持宽松: 既有 IAM 策略加载、IAM 导入与站点复制接收路径。
- 延后: STS 内联策略严格校验与 Console 客户端侧提前校验;服务端仍是权威边界。
裸 ARN 前缀为何会成为策略哑弹
正常的 S3 资源 ARN 必须在命名空间前缀后指定资源:
但原策略解析器也接受只有前缀的形式:
这个字符串没有指向任何 bucket 或对象。原解析器把它归一到通配资源类型,同时把 arn:aws:s3::: 保留为匹配模式;而真正进入 S3 鉴权的候选资源长成 bucket 或 bucket/object。因此整份策略虽然校验成功,这个模式通常什么也匹配不到。
对真正执行资源匹配的 Statement,实际影响取决于 Effect,以及前缀写在 Resource 还是 NotResource:
| 语句形状 | 原有运行结果 |
|---|---|
Allow + 裸 Resource |
什么也不授权 |
Deny + 裸 Resource |
本应生效的拒绝没有触发 |
Allow + 裸 NotResource |
没有排除任何东西,可能远比预期授权得更宽 |
Deny + 裸 NotResource |
可能远比预期拒绝得更宽 |
危险的两格属于依赖错误策略配置的 fail-open,而不是未认证远程漏洞,也没有 CVE。管理员、策略模板或自动化必须先提交这种错误资源,问题才会出现。同一问题也适用于已经注册的 S3 Tables 与 KMS ARN 前缀。
不操作资源的 Admin Action、sts:* Action Statement,以及 KMS 两阶段鉴权的第一阶段,本来就跳过资源匹配;裸前缀不会改变它们现有的运行时判定。严格写入仍拒绝这个具有误导性的字段,避免策略看起来像“限定了资源”,实际上该范围根本没有参与判定。
历史 *arn:... 形式
在沿用旧版本的宽松兼容路径中,把精确裸前缀解析后重新序列化,仍会在前面带上通配资源类型标记:
这两种写法重新解析后得到完全相同的内部资源值。因此 3.12 同时识别精确前缀与历史星号形式。存量/导出策略,以及会在发送前先解析再序列化策略的客户端,都可能出现后者。
原有通配语料保持不变:*、**、***、*foo,以及 arn:aws:s3:::* 这样的显式资源仍按原方式解析。
严格写入,不做存储迁移
修复刻意把“加载已有策略”与“创建新策略”分开:
ParseConfig与Validate继续宽松;既有存量策略保持相同的加载、匹配与序列化行为。ParseConfigStrict与ValidateStrict在Resource和NotResource中都拒绝“只有已注册 ARN 前缀、没有资源”的形式。Resource.IsBareARN()识别精确/历史形式归一后的值,不改变导出的Resource结构、ParseResource、匹配算法或 JSON 表示。ResourceSet.ValidateStrict()向消费者提供严格资源集合校验。
保留原资源表示对混合版本站点很重要:v3.11 与 v3.12 节点仍以相同方式比较、序列化存量策略,因此本修复不会制造站点复制 mismatch,也不要求迁移 IAM 存储。
SILO 在三个边界启用保护
SILO 提交 eee05a17c 选用 silo-pkg v3.12.0,并在以下场景使用严格解析:
- 创建或替换具名 IAM 策略;
- 创建带内联 Session Policy 的服务账号;
- 更新服务账号的内联 Session Policy。
本轮中,以下兼容敏感路径仍保持宽松:
- 加载已经落盘的具名策略与嵌入策略;
- IAM 导入/恢复;
- 站点复制接收与应用;
- STS 内联 Session Policy;
- Bucket Policy——它现有的 bucket/action 校验已经会拒绝这些形式。
启用 ParseConfigStrict 还会激活两条早已存在的 Admin Policy 规则:同一条 Admin Statement 不能同时携带 Resource 与 NotResource;作用于 bucket 的 Admin Action 不能使用非 S3 资源。这些都是刻意的鉴权收紧,已经记录在安全公告台账 SN-2026-005 中。
本文所说的 裸 ARN 前缀,是 arn:aws:s3::: 这种命名空间后没有任何资源的形式;它不同于 3.11 桶/对象边界修复中的合法 裸 bucket ARN,例如 arn:aws:s3:::my-bucket。
运维需要做什么
工具不会自动改写存量策略,因为无法推断原作者真正想指定哪个资源。部署包含服务端严格接入的 SILO 构建前,应当:
- 检查具名 IAM 策略中的精确/历史裸前缀;
- 检查服务账号的内联策略;
- 将每一处改成真正想要的具体资源;只有确实想表达整个命名空间时才使用尾部通配符;
- 所有站点完成滚动升级后再审计一次。
不要机械地把每个命中改成 arn:aws:s3:::*:那可能把原本不起作用的语句变成集群范围的授权或拒绝。含裸前缀的旧策略仍可加载,但不能通过三个严格写入端点原样交回;在修改同一策略或服务账号的其它属性前,必须先纠正该资源。
更安全的审计方式,是使用 policy-info 与 access-key-info API,而不是完整 IAM Export——后者包含普通用户与服务账号的密钥。STS 严格校验继续延后,直到可以单独审计仍在使用的机器客户端及其 Session Policy 模板。
为什么是中版本
本次使用 v3.12.0 而不是 v3.11.1,因为它同时跨越三条兼容边界:
- etcd 客户端从 3.6 中版本线进入 3.7;
- 模块验证过的
go下限从 1.25.0 提高到 1.26.0; - 新增了导出的裸 ARN 检查与严格资源集合校验 API。
模块路径仍是 github.com/minio/pkg/v3;/v3 导入后缀与全部现有 import 都无需修改。
Go 与依赖基线
go 与 toolchain 指令承担不同职责:
go 1.26.0是选定 etcd 3.7 模块要求的消费者下限。toolchain go1.27.0是维护开发与 CI 基线。- CI Actions 迁移到 Node 24 runtime。
主要选中版本变化如下:
| 模块 | 3.11.0 | 3.12.0 |
|---|---|---|
go.etcd.io/etcd/{api,client/pkg,client}/v3 |
3.6.6 |
3.7.1 |
golang.org/x/crypto |
0.54.0 |
0.55.0 |
golang.org/x/net |
0.57.0 |
0.58.0 |
golang.org/x/text |
0.40.0 |
0.41.0 |
github.com/minio/minio-go/v7 |
7.0.97 |
7.0.99 |
github.com/minio/mux |
1.8.2 |
1.9.2 |
github.com/cheggaaa/pb |
1.0.29 |
1.0.30 |
github.com/lestrrat-go/jwx/v3 |
3.0.12 |
3.0.13 |
github.com/lestrrat-go/httprc/v3 |
3.0.1 |
3.0.6 |
github.com/grpc-ecosystem/grpc-gateway/v2 |
2.27.3 |
2.29.0 |
go.uber.org/zap |
1.27.1 |
1.28.0 |
其它小型更新包括 uax29 2.3.1、fastjson 1.6.10、secp256k1 4.4.1 与 goccy/go-json 0.10.6。旧 lestrrat-go/option v1、gogo/protobuf 与陈旧的测试专用依赖退出选中依赖图。
etcd 3.7.1 是 3.7 版本线上第一个修复 GO-2026-6107 / CVE-2026-73500 的版本;该问题是未经认证即可触发的 TLS listener 拒绝服务。升级这些 Go 客户端模块 不会 自动升级运维使用的外部 etcd 服务端。SILO 不依赖被移除的 grpc.WithBlock 行为,发布验证也实际覆盖了 3.7.1 客户端连接 etcd 3.6.14 服务端。
依赖图声明 coreos/go-systemd 22.7.0,但模块将其 replace 为 22.6.0,因为 22.7.0 无法在 NetBSD 编译。SILO 服务端保留相同的可移植性覆盖。
兼容性
- import 路径与模块主版本不变。
- 既有策略继续按原方式加载和执行;只有严格创建/更新调用会拒绝错误前缀。
- 不执行策略、IAM 数据库、线缆协议或 etcd 数据迁移。
- 在 etcd 客户端拨号选项中使用
grpc.WithBlock的下游,需要改用受支持的 readiness 检查;SILO 不使用它。 - 真正升级外部 etcd 集群仍是独立运维流程。
- 本分支没有引入上游 AIStor Memory 与新的 AIStor 专属 S3 Tables Action 词汇。
消费者按以下方式选用本版本:
验证
已打标签的包通过:
- 仓库完整
make test门禁:固定版本 lint 加go test -race -tags kqueue ./...; - 重复运行裸 ARN 测试,以扰动 Go map 遍历顺序;
go mod verify、go vet、git diff --check与govulncheck,可达漏洞为零。
SILO 接入通过:
- 完整 IAM 服务端套件,包括具名策略精确/历史形式拒绝,以及服务账号创建/更新拒绝;
go test ./cmd -count=1、go vet ./cmd与go test ./...;- golangci-lint 2.13.1 零问题、
go mod verify与make check-gen; - 变异测试证明三个严格调用点与其集成断言都是承重的。
通过 VCS 直接解析模块,确认 v3.12.0 指向提交 2b087a1,模块校验和为:
Git 标签、GitHub Release、直接模块归档、来源提交与校验和均已验证。
相关变更
2bc3a91:CI Actions 迁移到 Node 24c8c6872:对齐 SILO Go 依赖栈2b087a1:在严格策略写入中拒绝裸 ARN 前缀;v3.12.0标签提交30c49bd:标签之后更新 README 依赖示例eee05a17c:SILO 启用具名策略与服务账号策略的严格写入56c67dacf:登记SN-2026-005
服务端发布范围
服务端严格策略写入集成(eee05a17c)已随 SILO 20260903 发布。STS 内联策略的严格校验仍保持延后,以便单独审计机器客户端与会话策略模板。
23 - Silo Pkg 3.11.0 发布
发布日期: 2026-08-04 · 版本: v3.11.0 · 提交: d8b1fa7 · 仓库: pgsty/silo-pkg
这是本分支的 第一个定版。它恢复了上游 minio/minio#20449 所报告的 IAM 桶/对象资源边界:策略条件键绕过修复、三个 LDAP 连接缺陷、证书监听器泄漏、有种子 RNG 的缺陷,以及模块真实的最低 Go 版本。
升级前需要确认两件事
- 本版本收紧了鉴权。 十二个桶级写操作不再能通过
arn:aws:s3:::bucket/*这样的对象级资源模式被授权。如果你自己编写桶级策略,请阅读 IAM 桶/对象边界——受影响者只需改一行策略,而MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on可完整恢复原有行为。 - 需与服务端条件键修复配套升级。 本版本的策略解析改动与服务端“保留内部条件键名”的改动各自覆盖问题的一半。服务端配套改动(
2f55347f7)已随 SILO 20260804 发布。
这个仓库是什么
silo-pkg 是 minio/pkg 的维护分支,为社区版 MinIO 分支提供上游(现由闭源产品驱动)不会再接纳的修复。仓库于 2026-08-02 由 pgsty/minio-pkg 改名而来。
模块路径刻意保持不变,仍然是 github.com/minio/pkg/v3,因此所有 import "github.com/minio/pkg/v3/..." 无需改动,只有 replace 指令的右侧需要更新:
/v3 后缀是模块的主版本号,不是目录名,不可省略。这也正是本次发布编号为 v3.11.0 而非 v4.0.0 的原因:Go 要求标签的主版本必须与 go.mod 中声明的主版本后缀一致,因此在一个 .../v3 模块上打 v4.0.0 会被工具链直接拒绝。真要发布 v4,就必须修改模块路径,并改写服务端、mc 与 Console 中约 395 处 import——那等于放弃"保留上游路径"所换来的直接替换能力,而这正是保持上游路径的意义所在。
IAM 桶/对象边界
每一个桶级 S3 操作,鉴权时对象名都是空的。IAM 匹配器把它拼成资源串,而对空对象名的情况补了一个尾斜杠:
"bucket/" 会被通配模式 "bucket/*" 命中,因为 * 匹配空串。于是一条把 s3:* 授在 arn:aws:s3:::bucket/* 上的策略——读起来是 “任意操作,但只作用于这个桶里的对象”——也连带授予了桶级操作。在多租户集群里,只持有这条授权的租户可以调用 PutBucketPolicy 装上 {"Principal":"*"},把桶变成匿名公网可读或可写,或者给自己授予桶级控制权;它也可以直接把桶删掉,而这正是上游 issue 中的复现步骤。
匿名访问所走的桶策略评估路径从来没有这个斜杠,是正确参照。只有 IAM 这条路径错了,而且只错在一个地方。
为何不修正整条边界
对所有桶级请求都不再补斜杠,是显而易见的修法,上游也试过:那次改动当天就因打破依赖旧行为的策略而被回滚。有两个性质让"完整修正"成为一次迁移,而不是一个补丁。
它会撤销真实部署所依赖的授权。 它撤销的不只是危险的桶写入——通过 bucket/* 授予的 ListBucket、GetBucketLocation、ListBucketMultipartUploads 同样会被撤销。证据就是上游自己的测试套件:11 个 STS 集成测试把 s3:ListBucket 授在 bucket/* 上,然后断言列举能成功。连写服务端的项目都这么写,生产策略里只会更多。
它切的是两个方向。 匹配器对 Allow 和 Deny 拼的是同一套资源串,所以删掉斜杠在收紧过度授予的 Allow 的 同时,也放松了过度阻断的 Deny。一个用 Deny s3:* on bucket/* 锁死某个桶的管理员,会悄无声息地失去那层保护。
保护集合是如何确定的
范围由一个问题决定:够到这个动作,能让调用者拿到它的对象级授权本来就给不了的东西吗?
之所以该问这个问题,取决于缺陷的触发条件。资源匹配发生在动作匹配 之后,所以这个 bug 只有在语句本身已经授予了那个桶级动作时才会触发——现实中这意味着 s3:*。因此受影响的主体本就对这个桶里的每个对象拥有完整的读、写、删权限。关键在于:对于一个已经控制桶内全部对象数据的调用者,触及某个桶级动作还会额外赋予什么能力。
不再接受对象级授权的十二个动作:
| 动作 | 入选理由 |
|---|---|
PutBucketPolicy、DeleteBucketPolicy |
能把访问权发给别的主体(包括匿名),也能给调用者自己补上从未授予的桶级动作。自我提权与公开暴露。 |
PutBucketObjectLockConfiguration、PutBucketVersioning |
击穿的恰恰是专门用来"防住有写权限的人销毁数据"的保护。 |
PutReplicationConfiguration、PutLifecycleConfiguration |
以服务端凭据运行,并在调用者权限被吊销后继续生效。 |
DeleteBucket、ForceDeleteBucket |
不可逆地销毁桶实体及其配置。上游 issue 的原始复现动作。 |
PutBucketCors、DeleteBucketCors、PutBucketQOS、PutInventoryConfiguration |
在今天的服务端没有挂任何行为——要么根本没有 handler,要么 handler 在鉴权之后直接返回 NotImplemented。收走它们不影响任何能用的东西,并且提前覆盖。 |
刻意不予保护,并且有测试对此做出断言——于是把其中任何一个加回去,都是一次带可见代价的明确决定,而不是往列表里添一行:
PutBucketTagging、PutBucketEncryption、PutBucketNotification。 它们都是桶级写入,早期草案确实纳入过保护。三者都不给调用者任何它还没有的访问权——受损的是所有者的合规姿态,不是访问边界;而一个拿到s3:*onbucket/*、并被告知"这个桶归你"的租户,完全合理地会去给它打标签、设默认加密、配事件通知。用很低的安全收益去换实打实的兼容成本,在维护版本里是个错误的交易。CreateBucket。 它作用于一个还不存在的桶,没有东西可篡改、可摧毁;而供应流程常用租户自己的bucket/*凭据去创建租户的桶。- 读/列举族(
ListBucket、GetBucketLocation、各类配置读取)。打破它们正是上游那次完整修复被回滚的原因,它们要等一次带迁移路径的发布。
改动只作用于 Allow 语句。Deny 语句保持历史资源串,因此任何桶级封锁都不会被削弱,NotResource 排除也保持完整覆盖范围。
单调性,以及那个错了两次的论断
上面这一切都建立在一条性质上:这个变更可以收走权限,但绝不能新增权限。 而这条性质被断言过两次,两次都是凭推理而非凭测试,也两次都是错的。把"怎么错的"记录下来,比只记录最终状态更有价值。
第一次尝试让省略的斜杠同样作用在了 NotResource 匹配上——而 NotResource 是 排除。Allow s3:* NotResource bucket/* 这样的语句,历史上不会作用于该桶的桶级请求;把排除拿去和裸桶名匹配,排除就不再命中,于是它所限定的那条 Allow 反而变宽了,而且恰恰是在受保护的那些写入上。
第二次尝试修好了这一处,并在发布时写着结论“可证明地单调”。针对定长通配模式的测试给出了反例。省略斜杠改变了模式所匹配的目标字符串,而一个模式完全可能匹配 "mybucket",却从来匹配不上 "mybucket/"。定长通配是最直接的例子:
? 恰好匹配一个字符。对九字符的 "mybucket/" 它匹配不上,所以这条语句从来没有授予过那个桶级写入;而对八字符的 "mybucket" 它匹配上了,于是这次加固授予了有缺陷的匹配器都拒绝的操作。
在受保护路径上,匹配器现在要求 两种形式同时命中——裸桶名,以及历史的 "bucket/"。结果是与历史判定取交集,因此在构造上就是单调的:不存在任何它能新满足的模式。mybucket* 照旧授予(它本来两种形式都匹配),mybucket/* 照旧被收走,mybucke? 像以前一样被拒绝。
证据
这条性质是被验证的,不是被论证的。我们生成了一份 27000 条鉴权判定 的语料——15 种资源模式 × 3 个桶 × 5 种对象名 × 20 个动作 × 6 种语句形式——分别在加固前基线与本版本上执行,并逐条比对:
| 迁移方向 | 条数 |
|---|---|
false → true(变宽) |
0 |
true → false(收窄) |
144 |
| 不变 | 26856 |
那 144 条收窄全部落在设计意图之内,没有一条溢出:动作恰好是受保护的十二个;语句形式只有三种 Allow,Deny、NotResource 排除与 deny-NotResource 三种形式 零变化;资源模式只有四种对象级模式;请求只有桶级请求,对象级请求完全未被触碰。12 × 4 × 3 = 144,严丝合缝。
两个层次都有回归测试。本仓库有十二条匹配器测试钉死每个方向,其中包括一条不变量测试,确保受保护动作个个都是纯桶级动作——ResetBucketReplicationState 名字唬人,实为对象动作,不入集合。服务端有三条端到端测试驱动真实 handler,分别位于客户端、内联会话策略与 S3 路由三个层次;三条在修复前的构建上全部失败,在本版本上全部通过。
需要改什么
只有当你的存量策略把十二个动作之一(或 s3:*)授在含 / 的资源模式上、且同一个桶没有裸桶 ARN 时,你才会受影响。修法是在对象模式旁边补上裸桶 ARN:
这种配对写法是惯例形式,也是上游自己的测试所采用的写法,在本版本之前同样有效。内置策略不受影响——readwrite、readonly、writeonly、diagnostics 全部使用 Resource: "*"。
MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on 在启动时读取一次,可完整恢复历史匹配行为——过度授予与过度阻断两个方向一并恢复。它目前是单一的全局开关,按动作粒度的作用域已列入待办。
策略条件键解析顺序
getValuesByKey() 此前会先按规范 MIME 拼写(http.CanonicalHeaderKey)查找策略条件键,再尝试原始名称。而它读取的那张表里,混放着服务端为当前请求计算出的值(SourceIp、SecureTransport、CurrentTime、username 等,以条件键拼写存储)和请求自带的 HTTP 头(以规范 MIME 拼写存储)。
先查规范拼写,就让客户端的请求头能够覆盖服务端算出来的值。
对 MinIO 服务端而言这是一次策略绕过。最简单的例子是 s3:prefix:一个 Prefix 请求头可以满足家目录前缀条件,而真正的 ?prefix= 查询参数仍然列举整个桶。同一条路径还能触及 aws:SourceIp、aws:SecureTransport、aws:CurrentTime、aws:EpochTime、aws:username、aws:userid、aws:principaltype、aws:UserAgent、aws:groups、ldap:username、ldap:groups、jwt:groups、s3:versionid、s3:signatureversion、s3:signatureAge、s3:authType 与 s3:LocationConstraint。匿名桶策略直接暴露。SigV4 也拦不住,因为客户端可以添加不在 SignedHeaders 列表里的头。
还有第二重后果:当服务端以一种拼写存值、而策略键解析到另一种拼写时,错误的条目会胜出。s3:object-lock-mode 可能解析到调用者的 X-Amz-Object-Lock-Mode 请求头,而不是服务端实际会施加的保留模式。
修复反转了查找顺序:先精确匹配条件键本身的名字,只对确实指代请求头的条件键(例如 s3:x-amz-* 家族)才回退到规范拼写。这移植了 minio/pkg#226,并补上了上游那次改动没有携带的回归测试。
在库的原始映射层面,如果生产者把同一个逻辑字段同时以精确条件名和规范 MIME 名存入,现在精确名胜出。这是一条库层查找规则,不是"查询参数优先"的 S3 线缆协议规则。Silo 服务端会先按真实来源规范化条件值。对于存储类别与上传标签这两处 Header 与查询形式都保持兼容的字段,Header 只要出现就胜出,包括空值,查询参数仅作回退。
LDAP 连接路径
connect() 中的三个缺陷,其中两个由本分支自己在 b0c08a7 中引入,随 v3.6.2 与 v3.6.3 发布。使用这两个版本的用户应尽快升级。
ServerInsecure 开启时 StartTLS 被跳过。 上游把 StartTLS 调用放在只由 ServerStartTLS 控制的外层块里,因此同时开启两个选项时,会先建立明文连接再升级。b0c08a7 把该调用移进了 else 分支,导致只要 ServerInsecure 为真,StartTLS 就不可达。连接保持明文,随后的 bind 就在这条连接上发送了凭据。MinIO 的 MINIO_IDENTITY_LDAP_SERVER_INSECURE 与 MINIO_IDENTITY_LDAP_SERVER_STARTTLS 是独立开关,Validate() 不拒绝任何组合,所以这个状态是可达的。
本版本恢复了上游语义:两个开关是 叠加关系,而非互斥。ServerInsecure 关闭隐式 ldaps://;ServerStartTLS 仍然执行升级。暴露窗口仅限 v3.6.2 与 v3.6.3。
没有 TLS 配置段的 Config 可能在 ldaps:// 路径上 panic。 l.TLS.Clone() 移出 StartTLS 分支之后,普通 ldaps:// 连接也会调用它。Clone() 对 nil 接收者返回 nil,而下一行却给 ServerName 赋值。MinIO 服务端总会提供 TLS 设置,但这是一个库,mc 同样在消费它。现在代码会回退到空的 tls.Config,与 DialURL 本来会构造的一致。
StartTLS 没有超时。 go-ldap 只在 requestTimeout > 0 时才启动请求计时器,而 StartTLS 本身没有超时。一台完成了 TCP 建连、随后对扩展请求不再响应的服务器,可以让连接 goroutine 永久挂住。现在计时器在 StartTLS 之前就已武装。
StartTLS 失败会泄漏连接。 这一条继承自上游。拨号失败不会返回连接,因此 StartTLS 失败是 connect() 里唯一可能同时返回连接与错误的路径。调用方只在错误为 nil 时接管所有权,于是对一台升级功能损坏的服务器,每次登录尝试都会遗留一个 socket。失败路径现在会关闭连接并返回 nil。
其它修复
- certs:文件监听器从未被停止。
Manager.AddCertificate()注册了两个notify.Watch()却一个都不停:如果第二个失败,第一个就泄漏;而且两个都会在 manager 关闭后一直存活到进程退出。Certificate.Watch()与watchFile()有同样的问题。四条路径现在统一使用watchDirSafe(),它返回一个在出错与ctx.Done()时被调用的停止函数。这移植了 minio/pkg#228 的certs/部分。在 Windows 上该函数用轮询替代文件系统通知,而不是把轮询仅作为失败回退,因此证书重载可能滞后一个symlinkReloadInterval(10 秒)。本分支没有 Windows CI,该平台仅做了交叉编译。 - rng:reader 的子密钥取自一个被清零的局部变量。
init()把 32 字节熵读进r.tmp,却从一个同名的、已清零的局部变量派生出四个子密钥,把四条按块划分的流坍缩成了一条。随后Reset()与ResetSize()会逐字节重放上一条流。MinIO 每次randreader.New()都创建新的 reader 且从不 reset,因此实际服务端影响有限;这个缺陷是 warp 暴露出来的。这移植了 minio/pkg#230。 - xtime:
Duration实现了UnmarshalJSON却没有MarshalJSON。 编码产出的是纳秒整数,而解码无条件剥掉首尾各一个字节并期待带引号的字符串,两个方向都无法往返。现在它使用time.Duration的字符串形式编码。这移植了 minio/pkg#242。
兼容性影响
- 十二个桶级写操作不再能通过对象级资源模式获得授权。 见需要改什么。对象访问、
ListBucket、CreateBucket、桶标签、默认加密与事件通知均不受影响,Deny语句与NotResource排除同样不受影响。 - 最低 Go 版本从
1.26.1降回1.25.0。go指令里的补丁号对每一个消费者都是硬性下限,而不是构建该模块所用工具链的记录。惯例做法是go行写语言版本、单独的toolchain行写开发版本。1.25.0才是依赖图实际要求的版本,也是上游声明的版本。CI 会在GOTOOLCHAIN=local下用 Go 1.25 构建完整测试套件,因此这个下限是被证明的,而不是宣称的。 xtime.Duration的 JSON 线缆格式变更,从纳秒整数改为"2h"、"30m"这样的时长字符串。已持久化的数值形式无法再读回。在 MinIO 与mc中未发现此类用法:批处理作业定义以 YAML 持久化,msgp 路径仍为 int64。- 同时开启
ServerInsecure与ServerStartTLS、且 LDAP 服务器不支持 StartTLS 的部署,在 v3.6.2/v3.6.3 上会以明文成功连接,现在则连接失败。这是正确结果,但它暴露在连接阶段而非配置校验阶段。对这类服务器请关闭ServerStartTLS。 Policy.IsAllowedActions对那十二个受保护动作可能与直接判定不一致。 它遍历SupportedActions,其中包含s3:*这个模式本身,因此返回的集合可能包含s3:*——从而看起来允许某个受保护动作——而直接求值却是拒绝。服务端没有任何地方调用它,Console 调用时传的是空桶名,永远走不到加固分支。此处选择记录而非修改:在维护版本里改变一个公开 API 的输出,风险更大。
与上游 v3.11.0 的差异
版本号跟随上游的线,不声称内容一致。以 policy/ 下的动作字符串常量为口径,实测差异如下:
| 数量 | |
|---|---|
上游 minio/pkg v3.11.0 |
291 |
silo-pkg v3.11.0 |
270 |
有 24 个动作只存在于上游: 6 个 s3:*ObjectAnnotation*、5 个 admin: 动作(DistJobStatus、Get/SetBucketCompression、两个 TablesReplication*),以及 13 个覆盖函数 CRUD 与打标签的 s3tables: 动作。它们属于本分支刻意不采纳的 AIStor 词表,因为社区版服务端并不实现这些功能。
有 3 个动作在两侧名称不同。 上游对它们做了改名与拆分,本分支保留较早的名称:
silo-pkg v3.11.0 |
上游 minio/pkg v3.11.0 |
|---|---|
s3tables:TagResource |
s3tables:TagTable、s3tables:TagWarehouse |
s3tables:UntagResource |
s3tables:UntagTable、s3tables:UntagWarehouse |
s3tables:ListTagsForResource |
s3tables:ListTagsForTable、s3tables:ListTagsForWarehouse |
因此,一条写了这六个动作名之一的策略,在两者之间 只有一个 能通过校验。Silo 服务端、mc 与 Console 都没有引用它们,所以在本生态内没有影响;但从上游 v3.11.0 切换过来的消费者应当知道,动作词表并不可互换。
rng 没有 arm64 汇编。 上游在本分支分叉点之后加入了 rng/xor_arm64.{go,s},本版本在 arm64 上回退到纯 Go 的 xor_noasm.go 路径。结果正确、交叉编译干净,但在该架构上比上游慢。它是未来同步的一个干净候选:纯性能改动,不牵涉词表分歧。
服务端配套行为
- 本版本的条件键改动 必须 与服务端"保留内部条件键名、按语义来源填充取值"的改动配对,见文首提示。
s3:signatureAge只有在 SigV4 预签名请求校验器算出它之后才会暴露。在其它任何请求类型上,客户端提供的x-amz-signature-age头都会被忽略。s3:prefix、s3:delimiter、s3:max-keys只来自查询参数。内容哈希、拷贝源、元数据指令、SSE 与对象锁条件只来自对应的请求头。校验预签名请求时消费的X-Amz-Content-Sha256查询值不会成为策略条件。s3:x-amz-storage-class保留其兼容的查询形式,PutObject与CreateMultipartUpload上的请求标签同样保留。这两个字段都是 Header 出现即胜出,只有 Header 缺失时才使用查询参数。s3:ExistingObjectTag/*只来自从已存储对象加载的标签,因此请求自带的X-Amz-Tagging不能再冒充既有对象状态。PutObject、CreateMultipartUpload与PutObjectTagging把s3:RequestObjectTag/*绑定到这些 handler 实际消费的标签输入。其余动作路径出于兼容保留了历史的X-Amz-Tagging头回退,因此只在 API 确实消费标签的地方,才把请求标签条件当作约束使用。aws:SourceIp由转发头计算得出。它是否可强制执行,取决于服务端的可信代理配置;参见服务端自己关于MINIO_API_TRUSTED_PROXIES的发布说明。
验证
以下全部在打标签的那个提交上执行,工作树干净,标签与 HEAD 一致:
make test——golangci-lint 加go test -race -tags kqueue ./...,全部包通过。go mod tidy -diff干净;gofmt -l为空;go vet ./...干净。linux/amd64、linux/arm64、darwin/arm64、windows/amd64四个组合的交叉编译。govulncheck ./...——零个可达漏洞。仅剩一条模块级提示 GO-2026-5932(x/crypto/openpgp):该包已停止维护、没有修复版本,且本仓库并未 import 它。- 从空模块缓存经公共 proxy 解析,确认发布出去的版本确实可获取。
- 上文所述的 27000 条鉴权判定语料。
依赖与工具链
依赖更新清除了 govulncheck 此前报告的九项 可达 问题:经 sftp 触达的七个 x/crypto/ssh 问题、经 etcd 触达的 gRPC GO-2026-6061,以及经 oidc 触达的 go-jose GO-2026-4945。
有五个依赖——minio-go、minio/mux、etcd client/v3、go-oidc、lestrrat-go/jwx——刻意未升级。MinIO 通过 replace 消费本模块,而最小版本选择会取整个依赖图中的最高版本,因此在这里升级它们会连带把服务端也拽着往前走。这五个都没有必须升级的已报告漏洞。
三个工作流此前都向 setup-go 索要低于 go.mod 要求的 Go 版本,并在第一条 Go 命令上失败,现已对齐。linter 此前还从 master 分支拉取安装脚本并每次重装;URL 与版本现已固定到 v2.11.3,且当已安装版本匹配时会跳过下载。
刻意未采纳的上游改动
- AIStor 策略词表(Memory/cortex、Tables/Iceberg、KMS、压缩与注解)以及带类型的动作常量重构,社区版服务端均不实现。这也是动作词表差异的来源。
securityAuditAdmin:它授予admin:ExportIAM,因而会暴露每一个密钥,与名字给人的印象相反。- rng 的 AVX2/NEON 汇编。其中 arm64 那一半已在上文列为未来同步候选。
net.BandwidthBytesPerSec(上游声明了却从未读取)、replicationAdmin与DistJobStatusAction。- 两项先采纳、复核后又移除的改动:
consolereadonly内置策略与GetAllGlobalCertificates,两者都没有消费者。一旦运维把内置策略名绑定到用户身上,再撤回就格外危险:策略映射按名字持久化,而无法解析的名字会并入一个拒绝一切的空策略;它继承的admin:CreateUserDeny 也无法与iamAdmin组合使用。那个证书辅助函数清点的是社区版服务端从不填充的缓存。 - 上游的 golangci-lint
tool指令,它会给每个下游消费者的模块图增加约 200 个 linter 依赖。
刻意推迟的部分
minio/minio#20449 的一般性问题——bucket/* 仍会触及 ListBucket、GetBucketLocation、各类配置读取、CreateBucket 以及上述三个租户可能合理使用的写入——在这里 没有 被关闭。彻底关掉它意味着撤销真实部署所依赖的授权,因此它属于一次带迁移路径的发布。
那次发布欠运维的东西,比"一份更长的动作清单"要多,因为没有人能穷举所有部署的存量策略——这给"靠猜来划定保护集合"的做法设了一个硬上限。有三件事能抬高它:
- 启动时的策略审计:遍历存量策略,逐条点名哪一条的含义会改变,授予与拒绝两个方向都点。它是只读的,甚至可以 先于 强制生效单独发布,从而把"升级后的意外"变成"升级前的清单"。
- 会自我解释的拒绝:当一个请求因为"只有对象级授权匹配上"而被拒时,就把这句话说出来,并点名那个兼容开关。一次 30 秒能自诊断的破坏,成本比静默破坏低一个数量级。
- 带作用域的开关:
MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH今天是全有全无,只想要回一个动作的运维,被迫连自我提权那条路一起重新打开。
相关提交
- d8b1fa7:fix(policy): settle the bucket-write hardening’s scope and monotonicity
- 1f97549:fix(policy): extend the bucket-write hardening to every bucket-only write
- 3c24ad1:fix(policy): withhold object-only grants from sensitive bucket writes
- da6a22a:docs: say what this fork is and how to depend on it
- 4055b2f:fix(xtime): marshal Duration as a duration string
- 13c26cd:fix(rng): initialize the reader subkeys from the seeded entropy
- 88b37ac:fix(certs): stop file watchers on every exit path
- 74dd36e:fix(ldap): keep StartTLS when ServerInsecure is also set
- 424c3d0:fix(ldap): close the connection when StartTLS fails
- 045d10f:fix(ldap): guard a nil TLS config and arm the StartTLS deadline
- 5c4bf50:fix(policy): prefer the exact key name over the canonical header form
- 802539f:chore(deps): refresh the dependency set and declare the real minimum Go
- e4ec64a:ci: build on the Go version go.mod requires, and prove the declared minimum
- 747d8b8:build: pin the golangci-lint installer and skip a matching install
24 - Silo 20260903 正式发布
版本日期: 2026-09-03 · 正式发布: 2026-09-04 · 版本: RELEASE.2026-09-03T13-18-01Z · 上一版本: RELEASE.2026-08-06T00-00-00Z
SILO 20260903 是首个完整使用 Silo 品牌的版本之后的一次安全与正确性发布,重点收紧核心服务端不变量:客户端 header 不能凭空获得复制权限;浏览器 Origin 不能在鉴权前触发桶元数据 I/O;并发桶配置写入不能彼此静默覆盖;授权与校验和行为进一步对齐 AWS S3。
本文以 20260806 为基线,汇总 2026-09-03 交付的服务端、Console、共享包与客户端完整变更。后续修复(包括 SN-2026-011)已分别随 SILO 20260916、SILO 20261015 与 SILO 20261018 发布。
亮点
- 复制信任来自授权。
X-Minio-Source-Replication-Request与相关内部字段只有在签名验证、精确 marker 校验以及s3:ReplicateObject/s3:ReplicateDelete授权后才获得复制语义。不可信字段在鉴权后清洗,因此不会破坏 SigV4。 - 桶级 CORS 完整落地。
PUT、GET、DELETE ?cors持久化真实桶策略,覆盖服务端全局 fallback,并通过站点复制收敛。预鉴权查找只读驻留元数据;启动期与已知元数据加载失败状态都保持 fail-closed。 - 桶元数据更新串行化。 共享
metadata.lock覆盖所有整记录配置写入、迁移、导入、站点 adoption 与 healing。ForceCreate不再擦除既有配置;存在 Object Lock 文档的桶始终使用纯Enabled版本控制。 - 授权与请求动作一致。 显式删除版本需要
s3:DeleteObjectVersion;用户和组的启用/禁用按目标状态检查对应 action;策略写入拒绝空的 ARN namespace。 - 校验和进一步对齐 AWS S3。 UploadPart 可由服务端计算校验和;联邦
UploadPartCopy返回校验和;multipart completion 返回ChecksumType;非法断言使用 AWS 兼容错误;CRC64NVME与COMPOSITE的无效组合被拒绝。 - SSE-C 读取与复制统一校验密钥。 零字节对象和
GetObjectAttributes不再绕过密钥认证;null-version 改写与原地换钥不会再留下不可读密文或不一致的 checksum metadata。 - 发布前主动减法。 删除死代码与过期 lint 例外;兼容快照只追踪真实对外服务面;依赖锁定到已审 revision;timeout 测试改用私有随机源。
- 客户端版本归入同一基线。 mcli 20260903 新增只读 checksum verify,完成 fail-closed 凭据脱敏,修复 Metrics JSON 与 S3 Select,严格校验策略写入,并提供签名软件包、溯源证明与验证过的 amd64/arm64 镜像。
安全修复
仓库安全台账为五个没有 CVE 的发现分配了稳定的本地编号。SN- 不是 CVE。完整威胁模型、兼容影响与运维动作集中记录在 SILO 20260903 安全说明。
| 编号 | 影响面 | 修复后的不变量 | 运维影响 |
|---|---|---|---|
SN-2026-006 |
SSE-C 零字节对象的读取与复制 | 即使没有 payload block 可解密,也必须认证客户密钥 | 错误密钥返回 403 AccessDenied;正确密钥不变 |
SN-2026-007 |
SSE-C 对象的 GetObjectAttributes |
获取属性需要客户密钥,除非请求确实来自已授权复制对端 | 裸 replication marker 不能跳过密钥认证 |
SN-2026-008 |
读、写、multipart、删除、Snowball、事件中的内部复制字段 | 复制语义需要鉴权与对应复制权限 | 普通客户端携带内部样式 header 时仍按普通 S3 语义处理 |
SN-2026-009 |
管理 API 的用户与组状态变更 | 启用与禁用分别校验不同 action | 过去只授予一个 action 却依赖双向操作的自定义管理策略需要拆分 |
SN-2026-010 |
带 versionId 的 DeleteObject / DeleteObjects |
显式删除版本需要 s3:DeleteObjectVersion |
检查 grant;原本用 Deny s3:DeleteObject 阻止永久删除的策略还需显式 Deny 新 action |
五个缺陷都继承自已归档的上游服务端代码,影响此前所有 SILO 版本。SN-2026-008 是对 CVE-2026-34204 接收端全链路修复的补全。
内嵌 Console v2.3.0 线还包含可信代理边界、TLS 校验修复、响应与日志脱敏、WebSocket 转发上限。
S3 正确性与互操作
Multipart 校验和
本版本关闭了 #46、#47、#48、#50 报告的 multipart 互操作问题组:
- 客户端在创建上传时选择算法、但没有为每个 part 提供 checksum header 时,
UploadPart由服务端计算所选校验和; - 旧版联邦后端的
UploadPartCopy不再丢掉远端返回的 checksum; CompleteMultipartUpload返回ChecksumType,缺失、畸形、矛盾或不支持的 checksum 使用 AWS 兼容错误;- 未知算法以及无效的
CRC64NVME+COMPOSITE组合直接拒绝,不再静默 canonicalize。
实现刻意分层:wire parser 拒绝非法声明,multipart state 记录所选算法和类型,完成阶段再将最终断言与状态比对。没有显式启用额外 checksum 的普通客户端不受影响。
独立证据记录见服务端计算 UploadPart 校验和、multipart completion 错误语义与 ChecksumType 传递。
CopyObject 与 SSE-C
CopyObject 现在会:
- 在可选压缩前对逻辑对象计算 checksum;
- 在响应中返回 checksum 字段;
- metadata-only copy 保留 transform state;
- 用源密钥解密源 checksum metadata,并为目标密钥重写;
- null-version 在任意 pool 方向复制时都不会丢失 current-version metadata;
- 对象层必须改写数据时,正确完成原地 SSE-C 换钥与重加密。
零字节对象与 attributes 修复消除了两个彼此独立的错误假设:“没有数据被解密”曾被等同于“密钥已经认证”。新规则是显式的:访问 SSE-C metadata 或 ciphertext 必须成功解封对象密钥,除非请求已经跨过授权 replica 边界。
CopyObject 状态矩阵与真实互操作证据记录在 CopyObject 的 SSE-C、checksum 与响应正确性。
列举与联邦
- ListObjects 快捷路径在 bucket 不存在且带 prefix 时也返回
NoSuchBucket(#32、PR #37)。 - 联邦
UploadPartCopy在公开响应中保留后端 checksum(PR #72)。 - 站点复制状态按站点计算 metadata 操作,不再把组级结果重复相乘,并将 CORS 作为独立配置字段校验。
missing-bucket shortcut 的完整记录见 ListObjects 必须先证明桶存在,再做优化。
桶级 CORS 与请求信任
桶级 CORS 端到端实现:
- S3 XML 类型与 rule matcher 校验协议 grammar 和多规则 preflight;
- bucket metadata 保存原始配置,
GET ?cors原样返回; - 外层 middleware 优先使用桶策略,不存在时才回落全局 origin 配置;
- 站点复制用带 tombstone 的 LWW register 单独承载 CORS;
- 预鉴权查找不加载 metadata、不创建 cache entry;
- 启动、已知桶元数据加载失败、删除、refresh 与按需重载都会显式维护 fail-closed 状态。
load-failure 状态是必要复杂度。预签名 URL 用自身签名完成鉴权,不需要 bucket policy;如果服务器忘记“真实桶的 CORS 文档加载失败”这一位信息,再回落宽松全局策略,就会丢掉这个已授权浏览器请求唯一的 origin 边界。
复制请求加固遵循同一原则。服务端先认证原始请求——内部 header 可能属于 SigV4 签名内容——再根据身份与权限得到一个私有 trust decision,最后清洗不可信的 request clone。clone 与原请求共享 trailer map,streaming checksum 不会丢失。Snowball worker 按 entry 推导信任,不继承 request-wide privilege bit。
完整设计与被否决方案记录在 鉴权前不做 I/O,Header 不产生权限。
桶元数据与 Object Lock
桶配置存放在同一个 .metadata.bin 记录中,但此前 policy、lifecycle、encryption、tags、quota、replication、Object Lock 与 CORS 使用彼此独立的锁更新。两个正确的 read-modify-write 因此可能都返回成功,后保存的一方却静默覆盖先前字段。
本版本用一个有界的 metadata.lock transaction 串行化所有整记录 mutation,同一把锁覆盖:
- 常规配置保存与删除;
- 旧元数据 migration 与 import;
- bucket 创建、
ForceCreate与站点 adoption; - healing 与 inconsistent-version repair;
- 只合并变化字段的 replication receive path。
实现没有把元数据系统改造成通用事务框架:既有 record 与 parser 保持不变,只集中 serialization boundary,并将复制导入限制为真正发生变化的字段。
Object Lock 还有第二条不变量:有效 lock 配置解析为 enabled 后,versioning 一律归一化为纯 Enabled;prefix exclusion 与 suspended 状态不能保留。判定依据是解析后的配置,不是与最小 XML 文档做字节比较,因此带 Default Retention Rule 的合法文档也无法绕过。测试覆盖 Update、读回、磁盘重载,以及两种畸形旧 versioning 状态。
IAM、策略与配置行为
- 显式版本删除按 AWS 的
s3:DeleteObjectVersion授权;复制删除保留s3:ReplicateDelete合同。 SetUserStatus与SetGroupStatus按目标状态授权,不再统一检查 enable action。- 新建或更新 named policy 与 service-account policy 时,拒绝空的 S3、S3 Tables、KMS ARN namespace、它们的历史序列化形式,以及同时含
Resource与NotResource的 statement;已存 policy 仍可加载。 - 已启用的旧 PostgreSQL/MySQL notification target 必须给出 connection string;启动现在以不含凭据的诊断失败,而不是静默丢掉所有 target。
MINIO_CONFIG_ENV_FILEparser 保留 named target、引号值与受支持的 shell-like assignment,但不会把文件当 shell 执行。
这些属于兼容性收紧,不是格式迁移。部署前必须阅读升级检查。
详细记录分别覆盖按目标状态授权用户/组操作、安全解析配置环境文件与旧数据库通知迁移的 fail-fast 设计。
组件
20260903 的依赖与配套发布线固定如下:
- Go 1.27.1
minio-go/v7: 上游兼容 pseudo-version,revision 结尾为0e78d3f18efe;临时silo-go分叉从服务端依赖图退役madmin-go/v3:v3.0.110silo-pkg/v3:v3.13.2,使用自有github.com/pgsty/silo-pkg/v3模块路径- 内嵌 Console:
v2.3.0,包含可信代理、TLS、脱敏与 WebSocket 安全修复 - 捆绑 mcli:
RELEASE.2026-09-03T07-13-05Z,保留mc兼容 alias - Helm Chart:
7.0.2;请使用正式发布的 Server 镜像pgsty/silo:RELEASE.2026-09-03T13-18-01Z与 mcli 镜像pgsty/mc:RELEASE.2026-09-03T07-13-05Z
tag 源码中的 Helm 提示: 签名 Server tag 的
helm/silo仍保留临时值RELEASE.2026-09-03T00-00-00Z。发布后提交4c164907f已把当前main上的 Chart 修正到正式 tag。若直接从 tag 源码归档渲染 Chart 7.0.2,请显式设置image.tag=RELEASE.2026-09-03T13-18-01Z;二进制与软件包不受影响。
服务端有意保留 MinIO 兼容的 Go module 与 wire identifier。替换 import target 不会改名公开 S3/Admin API、MINIO_* 配置、x-minio-* header、/minio/* route 或磁盘 metadata。
工程清理
最终发布审查删除了不保护兼容性或正确性边界的复杂度:
- 删除废弃 encryption helper、旧 handler path 与未使用 event-target function;
- 用更小的真实服务 route 兼容基线替代源码级 exported-symbol inventory;
- 删除
wait_pipelint exclusion,迁移到gomodguard_v2; - 用两个 helper 收口 CORS load-failure 生命周期,不在六条路径里分别 open-code set 操作;
- 站点复制 import 只更新发生变化的 metadata 字段;
- dynamic-timeout 测试使用私有随机源,不再修改 package-global seed;
- 保留共享 metadata lock、CORS tombstone、两级 replication trust 与覆盖各项已复现故障的回归测试。
发布前验证记录(包含测试期间发现并修复的问题)见 SILO Server 20260903 发布前复审。
升级检查
生产切换前请阅读从 RELEASE.2026-08-06 升级。至少完成:
- 给确实需要删除显式版本的身份授予
s3:DeleteObjectVersion;凡是用Deny s3:DeleteObject防止永久删除的策略,都要同时 Deny 新 action; - 拆分自定义管理策略中的 enable 与 disable grant;
- 重新提交 policy 前修正裸 ARN prefix;
- 给启用的旧 PostgreSQL/MySQL notification target 增加 connection string;
- 核对显式选择 checksum algorithm/type 的应用;
- 站点复制组所有成员全部升级后,再创建或修改桶级 CORS;
- 回滚前导出 CORS 配置,因为 20260806 不理解该字段;
- 分布式集群在一个维护窗口切换所有节点,混合 Silo 二进制无法成组。
对象与纠删码磁盘格式不变;分布式集群要求所有节点运行同一版本。
已知问题与明确延期
以下事项不在本版本修复范围内:
- 条件删除(#10、PR #12)。
DeleteObject忽略 HTTPIf-Match,DeleteObjects忽略每个<Object><ETag>,都会执行无条件删除,详见设计分析(已在后续 SILO 20261015 中修复)。 - 非 CORS 的多站点配置删除(#77)。 一个站点删除 policy、SSE、tag 或 quota 后,仍持有配置的对端可能把它恢复。单站点不受影响;CORS 使用 tombstone-aware register,也不受此缺陷影响。依赖这些复制删除的部署必须逐站核对(已在后续 SILO 20260916 中修复)。
ListMultipartUploads过滤(#79)。prefix类似精确 key 匹配,max-uploads、key-marker与delimiter尚未完整生效,详见兼容性分析与 2026-10-18 决策(提交4733e1423)。- 旧联邦后端
CopyObject(#99、#100)。 旧联邦后端可能忽略请求的 checksum algorithm,并拒绝 inline source object;不使用该后端的部署不受影响(已在后续 SILO 20261015 中修复)。 - 混合版本站点复制。 20260806 对端会接受但忽略桶级 CORS,并持续报告 mismatch;所有站点升级前不要配置 CORS。
- 回滚桶级 CORS。 20260806 重写 bucket record 时会丢掉未知 CORS 字段;先导出,重新升级后再恢复。
ILM relocation(PR #60)、更广泛的 SSE 支持(#61)、operator 发现(#30)、NATS target 热重载(#40)、Renovate(#20)等开放 enhancement 不在本版本范围内。
验证记录
完整本地验收运行在 ebac0ca73bbf251b070bb6df4d8005015841f901:
- 完整
cmd与internal测试套件; go test -race ./cmd,365.448 秒通过;- lint 0 issue、rebrand/compatibility guard、生成文件检查与
govulncheck; make verify覆盖 FS、erasure、分布式 erasure、erasure sets、多池、IPv6 多池:174 PASS / 0 FAIL。
之后只有一行代码修复 84e1580a4:GetConfig 按需重载成功后清除 CORS load-failure bit。后续依赖工作把工具链推进到 Go 1.27.1、把 x/crypto 推进到 0.56.0。在精确发布源码 9b11dc9469e650815b775cb47b039610644f5da4 上,git diff --check、完整 cmd 与 internal 测试、完整 cmd race、rebrand 与生成文件 guard、lint、govulncheck,以及远端 Go CI、VulnCheck、Test Release、Release workflow 全部通过。
最终功能验收使用四台 Ubuntu 24.04 arm64 虚拟机,每台四块 XFS 数据盘。测试覆盖 20260806 → 20260903 协调升级、回滚与再次升级;TLS 上的完整 mcli 功能脚本;1,004 个对象上传/下载 checksum 对比;单节点与 quorum loss;单盘重建;以及对象、版本、CORS、tag、quota、ILM、Object Lock、IAM、delete marker 与离线补传的双站点复制。结束时 16 块盘全部在线,没有未恢复的数据不一致。
binary/package Release 公开后,容器发布发现一处只影响交付的 pin 错误:首次 Docker workflow 在推送任何镜像前停止,因为 tag 中的 Dockerfile 已选择 mcli 20260903,却仍保留两条 20260901 归档摘要。提交 ce2326c94 与 9936a69d8 修正 pin,并新增一个收窄的恢复模式,从不可变且带 attestation 的 mcli checksum manifest 解析摘要。恢复运行 33847571968 随后使用原始 Server release 归档构建、运行、生成 SBOM attestation,并发布两个架构。classic 的 release/latest manifest 为 sha256:b616a0cf8cb281e7e6bb3c9b1fb53875b4016a2878223925541c18f82d6c5ca3;distroless 为 sha256:2711cdc5bce0ada353a4871dcda60f48f46414fdd69a45c36c71f6b7ebe1aead。
正式发布的服务端 GitHub Release 标识精确标签源码,以及经过验证的归档、软件包、checksum、SBOM 与 provenance;classic 与 distroless 镜像均发布一致的 amd64/arm64 manifest。独立发布的 mcli Release 不可变,包含 19 个已验证资产,并发布一致的 amd64/arm64 版本镜像与 latest;共享包 v3.13.2 与 Console v2.3.0 各自保留独立发布证据。
已解决事项台账
发布准备期间已经完成 tracker 收口:核心问题关闭,刻意排除的工作留在独立 open issue 中:
| 跟踪项 | 解决方案 |
|---|---|
| #102 | 已由合并的 PR #103 关闭:共享 metadata.lock,完整覆盖 writer、migration、adoption;需要先复现的残余审计拆到 #105 |
| #58 | 已由合并的 PR #104 关闭:显式版本授权、multi-delete auth/audit context 与 least-privilege replication;PR #59 作为被替代实现关闭 |
| #46、#47、#48、#50 | Multipart checksum 选择、计算、响应、校验与错误 |
| #32、PR #37 | missing-bucket listing shortcut 返回 NoSuchBucket |
| PR #57 | 所选 client/server stack 已提供 CompleteMultipartUploadResult.ChecksumType |
代表性变更
1c9a2431f至13e6458d9:实现桶级 CORS 与站点复制938603458至04b097fd9及 Snowball follow-up:认证复制语义,消除预鉴权 metadata I/Of9f9fa6c9至32a1b81e4:复现并串行化跨类型桶元数据更新3b5de82f5、21646eebd:保证 Object Lock 的 versioning 不变量,覆盖 retention-rule 文档f8b598f1d至d2d47a41f:对齐显式版本删除授权b73581b05、474cd5801、74c97d005:认证 SSE-C 零字节与 attributes 读取7fea6d5a5、5d152416d、7e079ff05、d28885d0e:对齐 multipart checksum 行为c0e715977、e73436c99、ffb70eb37:修复 CopyObject transform、checksum 与 SSE-C rotation84e1580a4:metadata 按需重载成功后解除 load-failure guard
致谢
本版本吸收了社区贡献者提交的问题与修复方案,也包含分叉自身的安全与兼容性审计。checksum、missing-bucket listing 与显式版本授权等工作都从公开 issue/PR 开始。
完整作者记录见 CONTRIBUTORS.md。
25 - 显式版本删除现在要求 DeleteObjectVersion
自 Server 20260903 起(pgsty/silo#104,对应 Issue #58),SILO 按照删除请求实际执行的操作类型选择所需权限:
| 请求 | 所需权限 |
|---|---|
未携带 versionId |
s3:DeleteObject |
| 版本 UUID | s3:DeleteObjectVersion |
显式 versionId=null |
s3:DeleteObjectVersion |
DeleteObjects |
对每个 XML 条目独立应用映射 |
此前所有情况均要求 s3:DeleteObject,而 s3:DeleteObjectVersion 仅用于检查显式 Deny。这导致仅持有 DeleteObject 的主体可以永久移除指定的历史版本,而仅持有 DeleteObjectVersion 的最小权限清理主体却无法执行版本清理。
修复后,仅持有 DeleteObject 的主体仍可执行不带版本号的删除或创建删除标记(Delete Marker),但在尝试删除指定 UUID 或 null 版本时会收到 AccessDenied。仅持有 DeleteObjectVersion 的主体可以永久删除指定版本,但不能创建删除标记。显式 Deny 与 s3:versionid 策略条件保持原有求值优先级。批量删除(DeleteObjects)按每个条目自身的 VersionId 求值,外层 URL 查询参数不会污染其他条目的条件值。
复制兼容性
存储桶与站点复制的目标策略无需新增 s3:DeleteObjectVersion。已认证请求通过精确的内部复制标记与 s3:ReplicateDelete 获得复制删除信任,接收端继续沿用已部署的 s3:DeleteObject + s3:ReplicateDelete 策略契约;而针对 s3:DeleteObjectVersion 的显式 Deny 仍会阻止复制版本清理。
这种区分既避免了升级后的目标站点静默拒绝永久删除复制,也不会给仅持有 ReplicateDelete 的凭据赋予额外的普通删除能力。双站点回归测试验证了使用最小权限策略(不含 DeleteObjectVersion)的目标端用户:永久版本删除与删除标记均能正常收敛。
升级影响
- 请检查当前仅授予
s3:DeleteObject,但需要执行mc rm --version-id、mc rm --versions、Console“删除全部版本”或 SDK 指定versionId删除的用户、服务账号、OPA 及外部授权策略,为其补充s3:DeleteObjectVersion。 - 对于普通的指定版本删除,外部授权插件现在只会收到一次
s3:DeleteObjectVersion判定请求,不再像修复前那样先收到一次仅检查 Deny 的s3:DeleteObjectVersion调用、再收到一次s3:DeleteObject调用。 X-Minio-Force-Delete前缀强制删除仍由s3:DeleteObject控制。- 本次变更不涉及传输协议或磁盘存储格式迁移。
完整的操作权限矩阵参见对象删除。
26 - mcli 20260903 正式发布
发布日期: 2026-09-03 · 版本: RELEASE.2026-09-03T07-13-05Z · 源码: a2ef95c0
距离 mcli 20260806 二十八天,本次发布汇总了客户端此后积累的全部变更。工具链升级到 Go 1.27.1,共享依赖栈与 SILO 家族对齐,silo-pkg 以自有模块路径导入,go.mod 如实描述二进制的构建来源。fork 以来第一个真正的新命令 —— mcli checksum verify —— 到来了,它对端点实际返回的字节只读地核验存储的 S3 附加校验和。让 --json admin prometheus metrics 无法使用的 panic 已修复,mcli sql 打印有效结果行后可能因重复关闭响应而 panic 的问题也已修复。每一条可能打印凭据的路径 —— --debug trace、admin trace、错误消息、JSON 错误文档、checksum 报告 —— 都按 fail-closed 原则重写。发布流程本身的变化不亚于代码:产物只从 main 精确顶端、且该提交 CI 全绿的 GPG 签名标签构建,每种格式都带有 LICENSE、NOTICE 与生成的 CREDITS,携带 Sigstore 构建溯源证明,并落入不可变的 GitHub Release。
本次发布构建自 a2ef95c0,即 pgsty/mc#27 的合并提交:自 RELEASE.2026-08-06T00-00-00Z 以来 58 个可达提交,其中 50 个非 merge 提交,涉及 262 个文件(+12,742 / −6,566 行)。中间的 20260901 构建仍可从 GitHub 获取,但本站以 20260806 为公开文档基线,只记录完整的 20260903 结果。
行为变更
- macOS 最低版本升至 13。 Go 1.27 链接 darwin 二进制时的最低系统版本为 13.0,darwin 归档包在 macOS 12 及更早版本上无法运行。
mcli --json admin prometheus metrics重新可用,并按名称确定顺序输出 metric family。纯文本 metrics 输出不变。pipe的标准输入为空时,现在执行普通的零字节 PUT,而非单分片的 multipart 上传。生成的 ETag 是d41d8cd98f00b204e9800998ecf8427e,而非<md5>-1形式。非空输入不受影响。- 策略写入在客户端严格校验 ——
admin policy create、admin user svcacct add/set、idp ldap accesskey create/edit。裸 ARN(如arn:aws:s3:::)被拒绝(表示该前缀下的全部资源请写arn:aws:s3:::*);命名策略缺少Version被拒绝;空策略被拒绝;同一 statement 内混用 S3 与 admin action 被拒绝。后三种情形服务端本来就会拒绝,因此只有裸 ARN 改变了"什么能被存入"。读取既有策略仍然宽松;服务账号的会话策略仍可省略Version,admin user svcacct set --policy也仍接受空文档 —— 这是清除内联策略、让账号回到继承策略的方式。 - 写在命令名之前的全局参数格式错误现在会报错。
mcli -H "bad" ls,以及在 app 层无法解析的--resolve、--limit-*取值,此前会被静默忽略、命令照常运行;现在与命令层形式一样以同样的消息失败,且只报告一次、输出到 stderr(--json下为 JSON 错误文档);此前 CLI 库会先把该文本回显到 stdout。 - 错误消息不再回显密钥。
alias set对错误的 secret key 只报告长度要求;MC_CONFIG_ENV_FILE的解析错误给出行号而不重复该行;SSE-C 密钥错误不再回显密钥;admin config set对携带密钥的key=value打码;远端复制目标打印时不含凭据;格式错误的--custom-header按位置报告,从不按值。 - 支持产物改为私有。
support diag、support profile、support perf、support inspect、admin cluster bucket export与admin cluster iam export写出的文件以0600创建,包括对上一个文件的轮转备份。此前是0644或0666。 --debug显示得更少。Authorization头只保留 scheme(AWS4-HMAC-SHA256 **REDACTED**);token、cookie、API key、SSE-C 密钥以及每一个--custom-header的值都被打码;2xx 响应的 body 不再 dump。admin trace的输出在默认与详细两种渲染下以同样方式脱敏:按名字打码的 header 值、查询串、body、错误文本与注记。- User-Agent 报告
minio-go/v7.3.0(SDK 自身的版本常量),而非minio-go/v7.0.98。
主要变更
- Go 1.27.1:模块、容器构建阶段、Linux/macOS/Windows CI、交叉编译、tidy 检查与漏洞分析全部使用 1.27.1。Go 官方维护的模块族同步更新:
x/net0.58.0、x/sys0.47.0、x/term0.45.0、x/text0.41.0、x/crypto0.56.0、x/mod0.40.0、x/sync0.22.0 与x/tools0.49.0。golangci-lint继续留在产品模块图之外,按钉死的 v2.13.1 独立安装。 - 以自有模块路径导入 SILO 包。
go.mod现在直接 requiregithub.com/pgsty/silo-pkg/v3v3.13.2。客户端的策略校验依赖只有那里才有的辅助函数 ——policy.ParseConfigStrict与policy.Resource.IsBareARN—— 而对上游minio/pkg做replace不会被任何把本模块当作依赖引用的项目继承(pgsty/mc#12),因此改为如实声明依赖。上游minio/pkg仅作为colorjson的间接依赖存在,由依赖下限检查钉在 v3.6.1,gomodguard则阻止上游 import 路径回流。minio-go从 v7.0.99 升到上游minio/minio-go的最新 master 提交,以伪版本v7.3.1-0.20260828014306-0e78d3f18efe表示;过渡期的pgsty/silo-gofork 已退役。最终依赖刷新包括 etcd 3.7.1、go-pretty6.8.3、klauspost/compress1.20.0、Prometheus client/common/procfs 1.24.1/0.71.0/0.22.0、grpc-gateway2.30.0、gRPC 1.83.2、Protobuf 1.36.12 与 JWX 3.2.0。go-systemd通过 SILO 的可移植性钉子有意停留在 22.6.0 —— 22.7.0 在 NetBSD 上无法编译。 - 运行时版本下限受到保护。 第一轮依赖调整曾因移除开发工具而悄然拉低了十余个运行时模块的选定版本 —— 其中包括
shoenig/go-m1cpu,其旧版本在启用 CGO 的新款 Apple Silicon 上会在初始化阶段崩溃 —— 该候选版本被否决。buildscripts/check-dependency-floors现在把go.mod中的每一条依赖与上一个RELEASE.*标签比较,出现回退即构建失败;唯一允许的例外是go-systemd钉子。 mcli checksum verify(设计文档)。将存储的 S3 附加校验和 —— CRC32、CRC32C、CRC64NVME、SHA1、SHA256,类型为FULL_OBJECT—— 与对象 API 返回的逻辑字节逐一核验,支持单个对象、--recursive前缀、--versions全部版本或精确的--version-id,以及 JSON Lines 候选清单。对未版本化对象以If-Match读取并在读后重新 stat,与核验并发的写入会被报告为UNKNOWN_OBJECT_CHANGED而非误判为不匹配。每个对象得到MATCH、MISMATCH、NO_CHECKSUM、WOULD_VERIFY(dry run)、十种UNKNOWN_*分类之一,或三种SKIPPED_*之一;汇总包含objects、verified计数(MATCH+MISMATCH,即真正重算过校验和的结果)、各状态计数与incomplete。--fail-on接受mismatch、unknown、no-checksum(任一对象缺少校验和、或根本没有核验任何对象时失败)、any(默认:不匹配、未知,以及被--max-size跳过的对象)或none。--report把同样的记录写入新建的0600JSON Lines 文件。无论 stdout 是否为终端,结果都写到 stdout;--json在非终端下输出紧凑的 JSON Lines —— pgsty/mc#5 报告的非 TTY 静默问题已修复。支持 dry run、--max-workers、--max-size、时间过滤,以及通过--enc-c的 SSE-C。该命令在 CI 中针对真实 SILO 服务器验证。- 凭据脱敏,fail-closed。 早期的模式匹配脱敏实现只识别预期形态、会放行非常规格式的凭据:含斜杠的 access key、首值为空以掩盖第二个值的
Authorization、非十六进制签名、藏进 credential scope 或SignedHeaders的密钥、Proxy-Authorization、cookie、X-Api-Key、响应 trailer、带 userinfo 的跳转Location、把请求头反射进错误 body 的服务端、--json错误输出中被 JSON 转义的密钥、重复出现两次的短 token。最终设计只有三条规则、没有例外:Authorization类的值只保留 scheme;名字看起来像密钥、或由调用者通过--custom-header提供的头一律打码、不问内容;客户端自己没有生成的文本 —— 响应 body、服务端错误消息、trace 注记 —— 先按凭据形态扫描,再按进程学到的每一个密钥字面值擦除。最后这一层由进程级的密钥登记表支撑:别名 secret key 与会话令牌、MC_HOST_*取值、各种编码形态的 SSE-C 密钥、tier 与 service principal 密钥、GCS 凭据文件、LDAP 密码及其返回的 STS 凭据、SUBNET 令牌、--secret-key/--account-key/--api-key参数,以及携带密钥的key=value参数,都在读入时、校验或任何网络调用之前登记。出现位置先收集为区间并合并再替换;JSON 错误文档在解码后的值树上只清洗字符串叶子,因此 key 与非终端下的紧凑格式都不受影响。四十余条边界测试用例、一个让真实客户端对着"反射所有收到内容"的端点运行的黑盒测试,以及对 SILO 服务器的实时抓包,共同钉住了结果。 admin trace脱敏。 服务端为其他客户端请求提供的 header map 走的是 S3 tracer 从未触及的路径。人类可读与 JSON 两种渲染、默认与详细两种形式,现在都基于脱敏后的副本 —— 事件对象在两者间共享、永不被修改。查询串(预签名 URL 的签名、位于第一个参数的会话令牌)、body、错误文本与注记都会按事件自身的 header 值擦除,因此其他客户端发送的 token 不可能进入特权 trace 输出。header 按名字打码:其他客户端以不像密钥的名字发送的--custom-header,会按服务端看到的样子显示。
缺陷修复
- Metrics JSON 不再 panic。 20260806 客户端的
mcli --json admin prometheus metrics在 v2 与 v3 两种 metrics API 下都会以panic: Invalid name validation scheme requested: unset失败。madmin-go构造了 Prometheus 文本解析器的零值,而prometheus/common0.66 起拒绝这种用法。客户端现在以 UTF-8 校验模式构造解析器,遇到问题返回普通解析错误而非 panic,并按名称顺序输出 family。 pipe空输入改为普通 PUT;此前对零字节发起的单分片 multipart 上传既无必要,又会生成 multipart 形式的 ETag。- RPM 载荷校验与签名脚本对齐:内容与发布元数据不符的 RPM 会在签名之前被拒绝。
sql打印完结果行后不再 panic。 SDK 的 select 读取器会在每个终止事件上自行关闭 HTTP 响应,而客户端又关闭了一次;在 zstd 压缩的响应上两次排空相互竞争,对 SILO 服务器的查询约五分之二会在结果行已经写出之后以panic: invalid memory address、退出码2收场(pgsty/mc#23)。客户端现在改为取消请求并排空结果管道,而不是再次关闭响应;在真实服务器上连续 820 次查询零 panic,而旧客户端 50 次中失败 21 次。
安全加固
- 运维人员产出的文件不再对全局可读。
support diag一边警告归档可能包含敏感环境信息,一边以0666写出;共用的moveFile帮助函数在把每个0600临时文件搬到最终名字的途中放宽为0644,而即便保留源文件权限,早期客户端留下的0644仍会被带进轮转备份。现在每个支持产物都以0600创建,并在写入第一个字节之前 chmod。 Test_FullSuite遇 panic 即失败。 功能套件此前会从 panic 中 recover 以执行清理、然后报告成功;套件中任何位置的 panic(包括二进制构建)在 CI 里都不可见。- 新命令帮助中残留的
play/别名 —— 仓库里唯一仍在宣传 MinIO 运营演示别名的文件 —— 已替换,品牌门禁现在除主机名外也拒绝命令示例中的裸别名。 - 补齐 AGPL 声明:六个 fork 自有文件此前只带许可证文本的前半段。
工程与交付
- 每种产物都带第三方声明。
CREDITS由buildscripts/gen-credits.sh从链接进六个 GoReleaser 目标的运行时模块并集生成,并在 CI 中比对,依赖变更不可能让它悄然过期。LICENSE、NOTICE与CREDITS随 GoReleaser 归档包、DEB/RPM/APK 软件包以及每一个容器镜像(/licenses/目录)一同交付。 - CI 在
main上运行。Go与Crosscompile此前只在 pull request 上运行,merge commit —— 真正被打标签的提交 —— 从未被测试;现在每次推送到main都会运行。它们的并发组以github.head_ref为键,而它在 pull request 之外为空,于是每次手动触发都会取消其他所有运行;现在改以 pull request 编号为键、ref 作为回退。VulnCheck也改为每周运行,因为归档上游的 fork 可能数周没有提交。CI 中的功能套件现在针对 SILORELEASE.2026-08-06T00-00-00Z运行。 - 只从签名标签发布。 产物工作流没有手动触发;产物来自推送的
RELEASE.*标签,事件 SHA、标签指向的提交与检出三者必须一致。verify-release-tag.sh要求 annotated 标签带有来自预期密钥的有效 OpenPGP 签名 —— 指纹与公钥位置来自仓库变量,而非标签指向的树本身,且导入的密钥必须与预期指纹一致。check-release-commit.sh要求被打标签的提交是origin/main的精确顶端,并且四个工作流对该 SHA 都有成功的 push-to-main 运行、按工作流文件路径匹配;pull request 与手动触发的运行不算证据。check-release-state.sh(pgsty/mc#6)按标签串行运行、从头替换恰好一个既有 Draft、拒绝已发布的 release,并在上传软件包前再次确认只有一个 Draft。每一个判定都住在带 fixture 覆盖的 shell 脚本里;测试中的假gh既钉住判决,也逐字核对传入参数。 - 溯源与不可变。 归档包、checksums、DEB 与 APK 软件包携带 Sigstore 构建溯源证明(
gh attestation verify <file> --repo pgsty/mc)。RPM 有意排除:sign-release-rpms.sh会在 release 仍为 Draft 时用密钥9592A7BC7A682E7333376E09E7935D8DB9BD8B20的分离式 GPG 签名改写其字节,早先做的证明会指向没有任何已发布 RPM 拥有的摘要。GitHub release 一经发布即不可变;修复资产意味着新标签。pgsty/mc容器镜像只在gh attestation verify把每个归档绑定到release.yml@refs/tags/<tag>、发布提交摘要、GitHub 托管 runner、其自身文件名与 SHA-256 之后才从经证明的归档构建;解包出的二进制的 ELF 机器类型必须与归档架构一致;每个架构的镜像先拉取、运行并检查标签,然后才合并 manifest,latest只从双架构 manifest 写入。UBI 基础镜像按摘要钉住,由 Dependabot 保持更新。 - 仓库治理适配单维护者项目。
main允许维护者直接推送;本次发布完成后,陈旧的 pull request 规则与依赖精确检查名称的耦合已删除。发布完整性不依赖这条分支规则:制品门禁仍要求被打标签的精确提交拥有成功的 push-to-main Go、Crosscompile、VulnCheck 与 Test Release 运行。RELEASE.*标签仍仅允许管理员创建且不可变;secret scanning、push protection、Dependabot 告警与安全更新保持启用。 - 打标签前后均完成验证。 在精确源码
a2ef95c035d9ae7cc01469a63926900f1786f9e2上,tidy/verify、依赖下限、单元测试、完整 race 套件、lint、actionlint、源码感知的govulncheck、九个标准交叉编译目标、干净缓存的 Go proxy/sumdb 构建、针对临时 SILO 服务端的 172 项功能检查、与已发布 20260901 二进制的 47 条命令黑盒对比,以及七个额外交叉目标全部通过。四个精确 SHA 的 main 工作流和两个发布工作流全部通过。不可变的公开 Release 包含 19 个资产;归档包与 sidecar 均通过校验和核验,11 个带证明的 subject 全部绑定到该标签与源码提交,两种 RPM 均通过 GPG 验证,pgsty/mc的版本标签与latest也被独立确认指向同一份 amd64/arm64 manifest。源码扫描没有可达漏洞。
兼容性
本版本的完整 --help 树与 20260806 二进制做了 diff:唯一差异是新增的 checksum 命令。在同一服务器上并排对比,head、cat、get、cp、mirror、find、share、sql、stat 与 ls 的输出与 JSON 字段集完全一致;二十份真实形态的策略除裸 ARN 外接受/拒绝结果一致;admin policy info --json 逐字节相同。mc 命令名与 mcli 软件包名;~/.mc / ~/.mcli 配置目录;github.com/minio/mc 模块路径及全部 import 路径;MC_* 环境变量;协议头(x-minio-*)与 minio-go User-Agent 前缀;minio tier 类型;.part.minio 传输后缀;minio-job 抓取任务名;以及软件包格式、产物命名与 YYYYMMDDHHMMSS.0.0 版本方案均未改变。客户端继续兼容 MinIO 服务器及其他 S3 兼容端点。把本模块当作 Go 依赖引用的项目现在直接解析到 github.com/pgsty/silo-pkg/v3,不再需要自己为它写 replace。
已知问题与边界
- 当服务端自身的完整性校验拒绝读取时,
checksum verify报告的是UNKNOWN_READ_ERROR而非MISMATCH—— SILO 的 bitrot 保护会在对象 API 返回之前拒绝损坏的分片。MISMATCH意味着存储的校验和描述的字节与对象 API 返回的不同,这正是该命令要找的历史写入路径缺陷;UNKNOWN永远不会被报告为MATCH。 - Access key ID 只要出现在凭据结构内就会被打码,但把裸 access key 反射进错误消息的服务端仍会让它被打印:它在合法消息中同时充当用户标识。短于三个字符的密钥不登记。当 secret key 与 access key 相同时 —— 默认的
minioadmin:minioadmin—— 错误文本中的这个标识也会被打码,因为这个字符串就是密钥。 --json错误文档中cause.error的 key 按字母序而非结构体顺序排列;key 与值本身不变。mcli sql在 stderr 报告查询失败后仍以0退出(pgsty/mc#25):逐对象的错误只报告而不中止运行,以便递归查询继续。与上游一致。govulncheck追踪到间接依赖x/crypto/openpgp中的 GO-2026-5932;不存在修复版本,客户端也不调用它。- JWX 3.2 按标准更严格地执行 JWT
crit处理。终端宽度依赖刷新也可能改变 Indic 或大量 ZWJ 文本的对齐;两者均未影响已测试的命令面。 - minio/mc#5139 继续适用:
mirror --remove --watch在源端删除对象的 非当前版本 时,可能误删目标端的现存对象。 - 不阻断发布的质量债 —— 归档可复现性、测试工具链可移植性、KMS / SSE-S3 / 多站点复制的延后覆盖 —— 记录在 pgsty/mc#21。
关联提交
- 98a8b0f:build: prepare the 20260903 dependency release
- 6686b64: chore(deps): align the SILO Go dependency stack
- 423490d: fix: stop JSON metrics from panicking
- 14b05e6: build: generate and package third-party notices
- e938cea: fix: align RPM payload signing validation
- 8158605: release: adopt Silo Go SDK v7.3.1
- d6ba236: ci: allow manual release workflow runs
- b6b2655: ci: release an existing tag on dispatch
- 70a2950: fix: preserve embeddable pkg compatibility
- aa07b1c: feat: add read-only object checksum verification
- 1b39423: fix: preserve checksum output in pipelines
- a31a42b: docs: record checksum verify output contract
- 2121081: fix: validate policy writes strictly
- 712bf3a: fix: use regular PUT for empty pipe input
- 9a3805d: ci: make release retries tag-idempotent
- 7bc9843: test: make report permissions portable
- 2d5abc2: chore: complete the AGPL notice on fork-authored files
- f5c5dc9: build: import the SILO package under its own module path
- a8e7eb4: ci: test main on push and stop dispatch runs cancelling each other
- b75d28b: fix: stop checksum verify help from advertising the play alias
- c05da7b: chore: drop configuration for bots that are not installed
- a29b455: fix: stop –debug from printing credentials
- 08244df: fix: keep secrets out of error messages and traces
- 30a7ea0: fix: stop writing support artifacts world-readable
- 14bd724: test: fail the full suite when it panics
- 4abbb3a: feat: expose how much checksum verify actually verified
- f484d0d: ci: make a release prove its commit, and pin what it builds from
- 2c33a4e: chore: ignore the local consumer-module review scratch directory
- bdc742a: fix: close the remaining –debug credential leaks
- 3998392: fix: withhold SSE-C keys and credential URLs the parser rejects
- c1358c4: fix: force 0600 on rotated support artifacts too
- 45e5144: fix: fail –fail-on no-checksum when nothing was verified
- 3674933: ci: make the release gate provable and its claims true
- 8b7b2e9: test: exercise checksum verify against a real server
- 4b36b0a: fix: make credential redaction fail-closed and scrub final output
- a6c14da: ci: verify build provenance before repackaging archives into images
- 915cfd9: fix: reject a malformed app-level global flag instead of ignoring it
- 81e2767: fix: rebuild SigV4 traces from known fields and widen secret scrubbing
- 625713c: fix: keep only the scheme of a signed header and scrub JSON structurally
- ec12b64: fix: redact admin trace output and register every credential ingress
- 1445e88: ci: release only from a signed tag at the tip of main, verify exact provenance
- f188939: fix: close final credential and release verification gaps
- f5b88dd: fix: redact the default admin trace and stop the shape sweep mangling prose
- 59989f8: fix: let svcacct set clear a policy again, report bad global flags once
- d38412a: fix: classify an SSE-C refusal with a key as a read error, keep policy and size messages clear
- b291b53: fix: register a URL password as written, keep listing parameters visible in traces
- 9dfca8f: test: drive the SSE-C refusal classification through the verify path
- 76b2e89: fix: keep an unquoted DSN password whole and match auth schemes case-insensitively
- 328efee: fix: register the password before the first separator of an unquoted DSN payload too
- 7057705: fix: avoid double-closing S3 Select responses
27 - mcli 20260806 发布
发布日期: 2026-08-06 · 版本: RELEASE.2026-08-06T00-00-00Z
距离 mcli 20260804 仅两天,本次发布完成了客户端向 Silo 身份的整体切换。这是一次刻意保持「纯品牌与封闭」性质的发布:--version 与 --help 现在以 Silo 客户端的身份呈现,所有残余的 MinIO SUBNET 外联路径在构建期被关闭,诊断工具链中内置的厂商加密公钥被移除,贡献政策改为无 CLA + 强制 DCO 签署。本周期 零依赖变更、零协议变更 —— go.mod 与 20260804 逐字节一致 —— 因此回归面被严格限制在文案、命令门禁与 CI 三个层面。
行为变更
所有原先会连接 MinIO SUBNET 的路径均已在构建期关闭,且无法在运行时重新开启:
mcli license register、mcli support upload、mcli support proxy set、mcli support callhome enable,以及mcli license update ALIAS的在线续期形态,均打印稳定的提示信息 —— “MinIO SUBNET services (registration, licensing, uploads) are disabled in this Silo build of mc; diagnostics remain available locally.” —— 并恒定以退出码1结束。脚本中如有这些调用应予移除。基于本地文件的mcli license update ALIAS license.key仍然可用,许可证使用内置公钥离线验签。mcli support diag/perf/profile/inspect恒定以本地(airgap)模式运行:诊断报告、性能剖析与 inspect 归档全部写入本地文件,不向任何地方上传。--airgap参数保留以维持兼容(实际上始终生效),SUBNET 注册不再是任何诊断命令的前置条件。mcli support callhome disable|status、mcli support proxy show|remove、mcli license info与mcli license unregister照常工作 —— 它们只读取或清除本地与服务端配置。- 全新生成的配置不再自动写入指向 MinIO 公共演示集群的
play别名,默认别名为local、s3、gcs。已有配置文件永远不会被修改,旧版配置迁移逻辑仍识别历史条目。 mcli --version增加一行身份说明(“Silo object storage client, based on MinIO technology”)与第二行版权信息。首行的机器可读格式保持不变,解析首行的脚本不受影响。
主要变更
- CLI 全面切换 Silo 身份:客户端自我介绍改为 “Silo client for object storage and filesystems”。约 220 处帮助文本重写:涉及被管服务器的用法说明改用 “Silo/MinIO server” 措辞,示例别名从
myminio/play换成mysilo,LDAP 示例 DN 换成dc=example,dc=com,示例分层名称换成SILOTIER-*。事实性表述保持事实:minio分层 类型、协议头以及第三方互操作提及均未触碰。 - SUBNET 构建期关闭:连接能力在编译期被单一开关移除,所有 SUBNET 请求汇聚的唯一 HTTP 出口以上述稳定错误拒绝。命令入口提前拦截,诊断命令强制本地模式,
mcli license info显示的 AGPL 许可说明不再附带商业订阅推销。专门的回归测试(cmd/subnet-disabled_test.go)钉住了全部行为,上游合并无法悄悄恢复任何外联。 - 治理 —— 无 CLA,强制 DCO:贡献按 inbound=outbound 原则以 AGPL-3.0-or-later 接收;贡献者保留自己的版权,维护者不获取项目许可证之外的任何权利。每个提交必须携带
Signed-off-by尾注,由新增的 CI 工作流强制校验(尾注须与提交作者邮箱匹配,仅豁免 GitHub 官方 bot 地址)。CONTRIBUTING.md、PR 模板与中英文 README 均已写明政策,行为准则的联系方式改为本分支维护者。 - 双版权署名:运行时输出与帮助信息同时致谢两条脉络 ——
Copyright (c) 2015-2025 MinIO, Inc.与Copyright (c) 2025-2026 PGSTY,源码构建动态计算截止年份。NOTICE明确声明分支关系,以及与 MinIO, Inc. 无隶属、无背书关系。 - 发布线更名为
main:工作流分支过滤器、文档与贡献指引全部指向main,旧的master引用已清除。
安全加固
- 移除厂商加密公钥:此前
mcli support inspect在未提供密钥时,会回退到用内置的 MinIO RSA 公钥加密输出 —— 产生只有厂商才能解密的归档。内置公钥现已移除:inspect 改用服务端为每次请求生成并回传给调用方的随机密钥(或运维人员自备的密钥),而任何未配置接收方的加密上传路径都会直接失败,绝不静默借用第三方密钥。运维人员产出的诊断数据,现在始终由其本人掌握解密能力。 - 品牌政策门禁:
buildscripts/check-branding.sh接入make verifiers与 CI。一旦命令树中重新出现 MinIO 运营的端点、商业推销 URL、上游产品身份、或任何内嵌的MII…公钥,构建即失败 —— 同时显式豁免有意保留的兼容标识(环境变量、协议头、模块路径、旧配置迁移默认值与原始版权头)。
工程与交付
- CI 迁移到 Node 24 Actions 运行时:
actions/checkoutv7、actions/setup-gov7、goreleaser-actionv7 及 Docker 系列 Actions —— 全部继续钉在 commit SHA 上,由 dependabot 保持更新。 - 功能测试只针对受控服务器:测试套件默认连接本地服务器(
localhost:9000)而非 MinIO 公共演示集群;CI 从pgsty/silo下载钉死的 SILO 服务端版本RELEASE.2026-08-04T00-00-00Z(经 SHA-256 校验)后再运行套件。 - 零依赖变更:本周期没有任何模块升级;20260804 建立的安全基线(Go 1.26.5、零个可达已知漏洞)原样延续。
- 发布前验证:覆盖 245 个文件的全量 diff 核对、品牌/兼容分类的 grep 扫描、调用图外联可达性检查(确认任何命令与参数组合均无法触达
subnet.min.io/play.min.io/dl.min.io),以及验证每条禁用路径均返回稳定错误与退出码1的冒烟测试。
兼容性
脚本与集成所依赖的一切均有意保持不变:mc 命令名与 mcli 包名/二进制名;~/.mc / ~/.mcli 配置目录(由调用名派生);github.com/minio/mc 模块路径及全部 import 路径;MC_* 环境变量;协议头(x-minio-*)与 minio-go SDK 的 User-Agent 前缀;minio 分层类型;.part.minio 断点传输后缀;Prometheus 抓取任务名 minio-job;以及软件包格式、发布资产命名与 YYYYMMDDHHMMSS.0.0 版本方案。客户端与 MinIO 服务器及其他 S3 兼容端点保持完全兼容。
已知问题
20260804 发布说明中标记的 mcli watch 回归已在服务端解决:修复随 SILO 20260804 交付,本客户端的 CI 现在正是针对该版本运行包括 watch 在内的功能测试套件。将 mcli 与 SILO 服务端 20260804 或更新版本搭配即可正常接收桶事件;更早的已发布服务端版本仍受影响。
上游未修复的历史缺陷继续适用,其中最严重的是 minio/mc#5139:mirror --remove --watch 在源端删除对象的 非当前版本 时,可能误删目标端的现存对象。在版本化桶上组合使用 --remove --watch 时请务必谨慎。
关联提交
- 8a883ca:ci: move the branch filters to main and fetch the server from pgsty/silo
- 8c304dd:ci: move the pinned actions onto the Node 24 runtime
- 02b1c11:docs: name the release line main, not master
- 810bbd2:ci: pin the functional-test server to a release whose watch API works
- d145647:fix: disable SUBNET connectivity and licensing upsell paths
- 5061c4f:rebrand: adopt Silo identity in CLI help and examples
- c7f7706:docs: align governance files and package metadata with the fork
- 65c71b2:test: default functional tests to a local server and add brand gate
- c62a64d:fix: credit both MinIO and PGSTY in copyright notices
- d205f88:docs: adopt no-CLA plus DCO contribution policy
- 95326ce:docs: add related-projects table and polish contribution wording
- d2c0db7:fix: remove the vendor encryption key and close the proxy-set path
- 0c6704d:fix: repair a link and help text damaged by the brand sweep
28 - Silo 20260806 发布
版本: RELEASE.2026-08-06T00-00-00Z · 提交: 3be10fcc1a44f6620ded0bd303461f9d688cca23
SILO 20260806 是 首个以 Silo 之名发布的版本。上一个版本 20260804 是以 pgsty/minio 名义交付的最后一版;本版本完成了向 github.com/pgsty/silo 的切换,重命名了每一个交付表面——二进制、软件包、容器镜像、systemd 服务、Helm chart——同时刻意原样保留了 MinIO 部署所依赖的每一个线上协议与配置表面。在改名之外,本版本新增了原生健康检查(silo healthcheck)、单二进制的 Distroless 容器镜像试点、装入每个交付物的完整许可合规材料,以及以兼容性快照与构建溯源为门禁的发布管线。
本版本覆盖 RELEASE.2026-08-04T00-00-00Z 之后的 28 个提交,变更 396 个文件,新增 27,188 行、删除 19,561 行。发布前通过了六阶段验收,包括一次真实的四节点 TLS 集群从 MinIO 到 Silo 的迁移——数据逐字节校验、维护闸门滚动重启、故障注入,以及完整的回滚彩排。
亮点
- 品牌切换完成,兼容性即契约。 仓库、二进制(
/usr/bin/silo)、软件包(silorpm/deb/apk)、镜像(docker.io/pgsty/silo)、服务(silo.service)全部改名;S3 与管理 API、/minio/*路由、MINIO_*环境变量、x-minio-*响应头、磁盘上的.minio.sys格式、Go 模块路径全部保留,并由 CI 兼容性守卫冻结。 - 原生健康检查:
silo healthcheck [live|ready|cluster|cluster-read]探测服务器自己的健康 API——正确的退出码、解码后的 quorum 诊断、TLS 自动探测、--maintenance下线前闸门——容器内无需 shell、curl或mc。 - Distroless 镜像试点:
pgsty/silo:<RELEASE>-distroless基于gcr.io/distroless/static,恰好装载一个程序——silo二进制——内置 exec 形式HEALTHCHECK,/data在镜像层内以可写方式创建。 - 经典镜像行为不变: 同样的入口脚本、同样的捆绑工具,
mc ready local继续可用,也没有给它添加HEALTHCHECK。捆绑客户端升级为mcli20260806。 - 合规补齐: LICENSE 与 NOTICE 装入每个软件包与镜像,CREDITS 按实际链接的模块集合(291 个模块)重新生成并纳入 CI 守卫,项目采用无 CLA、基于 DCO 的贡献政策。
- 组件刷新: 内嵌 SILO Console 2.1.1、
silo-pkg3.11.0、mcli20260806、Go 1.26.5。 - 以溯源为门禁的发布: 容器镜像只从已发布、校验和与 attestation 双重验证过的发布产物构建;镜像 SBOM 与溯源 attestation 现在同样覆盖 Distroless 变体。
改名
改了什么,与刻意没改什么:
| 已重命名(交付表面) | 已保留(兼容表面) |
|---|---|
仓库:github.com/pgsty/silo(main 分支) |
S3 API、管理 API 与请求签名行为 |
二进制:/usr/bin/silo |
/minio/* 路由,含 /minio/health/* 与指标端点 |
软件包:silo-*.rpm、silo_*.deb、silo_*.apk |
MINIO_* 环境变量与 x-minio-* 响应头 |
镜像:docker.io/pgsty/silo(另有 -distroless) |
磁盘格式(.minio.sys)、纠删码、版本控制 |
服务:silo.service(与 minio.service 冲突并取而代之) |
Go 模块与导入路径(github.com/minio/...) |
默认配置目录:~/.silo(存在旧 ~/.minio 时回退兼容) |
捆绑 mcli 的 mc 兼容别名 |
服务器呈现自己的身份——silo --version 输出 AGPL-3.0 许可、MinIO 2015-2025 版权、PGSTY 修改版权与 “based on MinIO technology” 归属——所有继承自上游的 MinIO 运营服务连接(更新源及其验签密钥、SUBNET、遥测)被切断而非重定向。容器入口脚本翻译 legacy minio argv 词元,因此 docker run pgsty/silo minio server /data 继续可用。
CI 中运行快照式 rebrand 守卫:对 334 个路由字面量、437 个环境变量词元、84 个响应头与 9,014 个导出符号的任意双向漂移直接判失败。
原生健康检查
服务器二进制现在可以探测自己的健康端点,使容器健康检查不再需要第二个二进制——这也是 Distroless 镜像的依赖所在:
- 检查词汇与
/minio/health/<path>一一对应;live(默认)回答"这个进程是否在服务",ready在配置了 KMS/etcd 时追加其可达性,cluster一对评估每个纠删集的写/读 quorum。 - 退出码只有
0(健康)与1(其余一切)——绝不使用 Docker 保留的2。单行诊断解码服务端的x-minio-server-status与 quorum 响应头供docker inspect采集;--json输出机器可读判定。 - 探测目标按服务器推导自身监听地址的方式推导:
--address/MINIO_ADDRESS,HTTPS 由 certs 目录中public.crt+private.key的存在自动判定,或用--url/MINIO_HEALTHCHECK_URL整体覆盖。环境变量形式的存在是因为探针进程看不到服务器的命令行——当服务器地址或 TLS 来自 CLI 参数时,一个环境变量即可矫正内置探针。 silo healthcheck --maintenance cluster回答下线前的问题:退出0表示此节点可安全下线而不失去高可用;HTTP 412(退出1)表示不可以。- 跳过证书校验,与 kubelet 对 HTTPS 探针的文档行为一致;传输层忽略
HTTP_PROXY,环回探测永不进代理。
Kubernetes 完全不需要这些——kubelet 的 httpGet 探针从容器外打 /minio/health/live 与 /minio/health/ready——且 cluster 检查不应进入单容器探针:它反映的是全集群 quorum,不是单个进程。完整设计依据(含源码核实的端点语义)记录于健康检查设计笔记。
Distroless 镜像试点
在经典镜像之外,本版本发布 Distroless 变体:pgsty/silo:RELEASE.2026-08-06T00-00-00Z-distroless,另有滚动 distroless 标签。
- 基底为
gcr.io/distroless/static-debian12:CA 证书、tzdata、/tmp、含nonroot(65532)条目的/etc/passwd——没有 shell、没有包管理器、没有 libc。之上恰好一个程序:/usr/bin/silo(外加/licenses/下的许可三件套)。镜像 128 MB,对比经典镜像 199 MB。 - 二进制即
ENTRYPOINT;内置 exec 形式HEALTHCHECK运行silo healthcheck ready(interval 30s、timeout 10s、start-period 2m、retries 3),Compose 用户零配置即获得可用的depends_on: condition: service_healthy。 /data在镜像层内以全员可写方式创建——运行时已没有入口脚本可以修补卷属主,而这正是让所有权限模式(含--user)都能工作的原因。这在 Distroless 变体中修复了 #55 记录的非 root 失败。- 此变体不支持:已弃用的
MINIO_USERNAME/MINIO_GROUPNAME降权路径(改用--user或 KubernetesrunAsUser)、docker exec <c> sh式调试(改用临时容器工具)、镜像内mc(改用已发布的mcli或客户端镜像)。 - TLS:把证书挂到
/tmp/.silo/certs(容器内默认 certs 目录),服务器与内置探针会从同一位置各自推导出 HTTPS;CLI 参数配置的服务器则设置MINIO_HEALTHCHECK_URL。
经典镜像仍是默认且保持不变。试点验证充分后,Distroless 变体将成为推荐镜像;决策记录见上述设计笔记。
容器镜像
经典镜像与 pgsty/minio:RELEASE.2026-08-04T00-00-00Z 做了逐字段对照:入口、暴露端口、卷、工作目录、用户与(不存在的)健康检查配置完全一致。差异恰好三处且均为刻意变更:Cmd 由 ["minio"] 改为 ["silo"];移除上游更新验签密钥变量 MINIO_UPDATE_MINISIGN_PUBKEY(上游渠道更新永久关闭);声明 HOME=/tmp 以与入口脚本的可写 home 保证一致。
捆绑客户端升级为 mcli RELEASE.2026-08-06T00-00-00Z(保留 mc 别名),按架构以 SHA-256 摘要钉版并在构建期对照发布校验和验证。已发布的 mcli 20260806 与本服务器的互操作性——分段上传、版本控制、预签名 URL、metadata/tags、用户与策略管理——已在发布验收中验证。
Helm chart
Chart 以 silo 7.0.1 发布,经迁移守卫验证在模拟升级中与旧 chart 的 7 个渲染资源身份保持稳定。默认镜像标签现在指向本版本——docker.io/pgsty/silo 是全新仓库,继承的旧默认值本不可能拉取成功。Chart 仍未附带 liveness/readiness/startup 探针;按设计笔记的后续阶段规划补齐。
打包与迁移
RPM、DEB、APK 软件包恰好安装六个文件:/usr/bin/silo、silo.service、sysusers 定义(创建 silo 系统用户)、/etc/default/silo(config/noreplace)、LICENSE 与 NOTICE。RPM 以 PGSTY 维护者密钥 GPG 签名(9592A7BC 7A682E73 33376E09 E7935D8D B9BD8B20)。RPM 与 DEB 现在统一携带 PGDG 风格的 1PGSTY release 段——silo-<版本>-1PGSTY.<架构>.rpm 与 silo_<版本>-1PGSTY_<架构>.deb——取代此前 RPM 继承的裸 -1 与 DEB 缺失的 revision;APK 命名保持不变,因为 Alpine pkgrel 只接受 -r<整数>。
silo.service 为接管而设计:Type=notify(就绪由服务器自己发信号)、Conflicts=minio.service + After=minio.service(启动 Silo 会停掉运行中的 MinIO 服务)、以及 两个 环境文件——先读 /etc/default/minio、后以 /etc/default/silo 覆盖——现有 MinIO 配置无需编辑即被继承。对数据属主为 minio 用户的既有部署,用文档规定的 drop-in 保持属主不动:
分布式迁移必须全体节点一起切换。
集群引导会(按校验和)验证每个节点运行相同的二进制。混合集群——部分节点 Silo、部分仍是 MinIO——无法组网:新节点停在 activating,无限期记录 Expected Silo binary checksum ... seen: ... 与 Waiting for at least 1 remote servers with valid configuration。请在 所有 节点上停止 MinIO,然后(近同时地)在所有节点上启动 Silo。全部节点运行 Silo 之后,滚动重启一切正常——每台重启前用 silo healthcheck --maintenance cluster 做闸门。
来自验收实测的迁移排障提示:若 Silo 以软件包默认的 silo 用户启动,而部署的 TLS 证书位于 minio 用户家目录之下,会以 HTTPS specified in endpoints, but no TLS certificate is found 失败并连续重启直至 systemd 启动限制生效——上面的 legacy-user drop-in 即是解法。迁移窗口期间保留 MinIO 软件包与服务(处于 disabled):回滚路径——停 Silo、起 MinIO——已经彩排,且能读取 Silo 窗口期写入的全部数据,因为迁移既不动数据属主也不动数据格式。
组件与依赖
- SILO Console 2.1.1 —— 内嵌控制台,取自
pgsty/silo-console,保留github.com/minio/console导入路径。 silo-pkg3.11.0 —— 保留策略/LDAP/证书修复,含 #15 跟踪的 LDAP-over-TLS 修复。mcli20260806 —— 镜像内捆绑并已单独发布;见其发布说明。- Go 1.26.5 —— 工具链与 20260804 一致。
构建、CI 与发布管线
- 兼容性即 CI 门禁: rebrand 守卫对路由、环境变量词元、响应头、指标、存储/策略标识符与导出符号做快照,任何未经评审的漂移直接失败;配套脚本断言交付表面(二进制路径、unit 内容、镜像布局),并确保运行时代码中不再存在任何上游在线端点。
- 发布镜像门禁: 发布管线的每次运行都构建两个容器镜像并断言(除其他外):Distroless 的
HEALTHCHECK存活于镜像配置(它是 OCI 规范之外的 Docker 扩展)、/data以全员可写交付、不存在 shell 与/usr/bin/minio、Docker 健康状态仅凭内置探针即转 healthy、SIGTERM 在 root 与--user 1001:1001双路径下均优雅停机。 - 溯源链: 镜像从已发布的发布产物构建,先经校验和验证与对确切 tag 的
gh attestation verify;经典与 Distroless 镜像均推送分架构 SBOM 与溯源 attestation;Distroless 健康检查门禁在多架构 manifest 提升之前运行。 - 工作流运行时 全面迁移到 Node 24。
兼容性与升级注意
- 软件包升级是接管而非原地更新。 安装
silo,保持/etc/default/minio原样(会被继承),启用silo.service;启动它会经冲突关系停掉minio.service。数据不动。 - 用上述 legacy-user drop-in 保持数据属主稳定;迁移期间不要 chown 存储、不要移动证书。
- 分布式集群:只能全停切换。 见上方警告——Silo/MinIO 混合节点无法组网。
- 容器用户: 镜像现为
docker.io/pgsty/silo;docker.io/pgsty/minio冻结在 20260804 作为存档。经典镜像行为不变——包括mc ready local健康检查——Distroless 变体严格自愿选用。 - Distroless 的差异是刻意的: 无 shell、无镜像内
mc、无MINIO_USERNAME路径;健康检查原生;CLI 参数配置的服务器需为内置探针设置MINIO_HEALTHCHECK_URL。 - Helm 用户: chart 7.0.1 的默认值现在能拉取本版本;若钉版本请显式覆盖
image.tag。 - 已知且未变: 经典镜像仍不在层内创建
/data,因此完全非 root 的docker run配 Docker 管理卷会一如既往失败(#55,Distroless 变体已修复);20260804 说明中继承的 Postgres/MySQL 遗留通知迁移限制仍然适用(#53)。 - 客户端配套使用
mcli20260806;旧客户端在未变的线上协议下继续可用。
验证
本版本分阶段验证,每一步留有证据记录:
- 健康检查命令的单元与端到端矩阵:目标推导与优先级链(flag/env/派生)、真实 TLS 自动探测、退出码契约、JSON schema、超时有界性、用法错误;
- 四节点集群上的语义验证:停掉 4 节点中的 2 个后,
cluster报告 503 且write-quorum=5,而cluster-read与live保持 200——写/读 quorum 分野现场观测,与纠删码推演一致; - 镜像验收:经典镜像与 20260804 基线逐字段对照;Distroless 镜像断言至文件清单、精确健康检查配置,及 root/非 root/TLS/环境变量覆盖四个运行场景;
- 以真实迁移收尾的六阶段发布前验收:Pigsty 部署的四节点 TLS MinIO 20260804 集群(16 盘、EC:4)经软件包接管路径迁移至 Silo——参考数据(分段、多版本、带标签对象)逐字节读回一致、四轮维护闸门滚动重启、
kill -9故障注入下负载均衡持续 IO 24 轮成功 23 轮(唯一失败恰在击杀当秒)、Prometheus 指标连续,以及完整的回滚至 MinIO 再切回——证明迁移可逆。
验证边界
本轮发布验证未连接外部在线 LDAP/OIDC/KMS/etcd 服务;amd64 软件包完成了交叉构建与载荷校验;Windows 与 Intel macOS 目标仅做交叉编译。
交付物
pgsty/silo的 GitHub ReleaseRELEASE.2026-08-06T00-00-00Z:带校验和的平台归档、溯源 attestation、RPM/DEB/APK 软件包(RPM 带 GPG 签名);docker.io/pgsty/silo:RELEASE.2026-08-06T00-00-00Z与latest;docker.io/pgsty/silo:RELEASE.2026-08-06T00-00-00Z-distroless与distroless——从完成的 Release 按需发布;- 配套发布:
mcli20260806、silo-pkg3.11.0、内嵌 SILO Console 2.1.1; - 设计记录:原生健康检查与 Distroless 镜像。
选定变更
15def34dc、77bdc4c0c:清除上游交付残留;呈现 Silo 身份并关闭继承的上游服务15ab10833:交付物改名为 silo 并补全软件包载荷30749911b:镜像装载 silo 二进制并翻译 legacy argv 命令e071bb77e:以保持身份的 silo chart 替换 minio chartbd8df5166:以兼容性、打包与溯源证据为 rebrand 设门禁6613c2a3c:钉住外部测试固件并针对 silo 二进制运行套件fd2ca1c6d、c46b16ec6、c47733abc、f1c77d5a2:切换到 pgsty/silo 与 main;记录归档分支6740e6978:工作流迁移到 Node 24 运行时b57275be3:采用无 CLA + DCO 政策并修正版权条款62717d7bf、a6d6d9b02:内嵌 Console 升级到 2.1.0、再到 2.1.16bd9cf77e:按实际链接模块集合重新生成 CREDITS 并纳入 CI 守卫219670d31:LICENSE 与 NOTICE 装入每个软件包与镜像2ff594f4b:新增原生silo healthcheck子命令4c34d2309:新增 Distroless 镜像变体试点b6d47b739、9462cce16:加固健康检查与 Distroless 镜像;lint 清理16b78eb4e:捆绑 mcli 20260806 并将 Helm 默认值指向本版本062a91bee:将 CREDITS 模块闭包钉定到实际发布的 linux 目标467931455:统一 rpm 与 deb 的 release 段为1PGSTYb14ea22aa:镜像发布通道精确匹配校验和清单条目3be10fcc1:新增手动 finalize 通道,为已签名的 Draft 软件包刷新 SBOM 与校验和
致谢
已有四位贡献者的代码合入本分支,Git 历史中保留着他们的署名:@ZouhairCharef 修复了 go-jose 中的 CVE-2026-34986(#18),@mfredenhagen 修复了 OpenTelemetry 中的 CVE-2026-39883(#19),@pinginfo 为 trackingResponseWriter 实现了 Flush,修好了桶通知的流式输出(#34),@waterkip 将文档链接指向了 Silo 门户(#41)。
以新名字发布的第一个版本,也正是感谢所有为这个分支提交过 issue 的人的时刻——缺陷报告、兼容性发现与提案,无论已解决还是仍在处理:
@mosesdd(#1)、@Xavier-777(#2、#17)、@jiadzh(#3)、@TLINDEN(#4)、@AntonOfTheWoods(#5)、@zylpsrs(#6)、@nsanitate(#7)、@makinikm(#9)、@magicxor(#10)、@spaceg00se-r(#11、#14)、@heroes1412(#13)、@vampywiz17(#15)、@davinkevin(#20)、@chalukyaj(#30)、@cbornet(#31、#32)、@jvasile(#33)、@Kesavaambati(#35)、@redfoxfox(#38)、@kuldeep-link11(#39、#40)、@meesudzu(#42)、@pmezhuev(#43)、@kh0mka(#51)。
本版本的多项核心内容可以直接追溯到这些报告:内置客户端的保证来自 #4 与 #9,LDAP-over-TLS 修复来自 #15,软件包载荷补全来自 #33,RPM GPG 签名来自 #43,迁移指南来自 #42,distroless 的 /data 修复来自 #55。
仍在处理中的 PR 同样值得一提。@davinkevin 的 distroless 镜像 PR(#21)比本版本的试点早了数月——最终交付的变体以内置原生健康检查取代了该 PR,但方向是在那里首先提出的。@magicxor(#12)与 @ycjlin(#37)的一致性修复 PR 将在本版本发布后立即进入评审。
所有为本分支做出贡献的人都记录在 CONTRIBUTORS.md 中。GitHub 不为 fork 仓库生成贡献者图表,该文件即本项目的署名记录。
29 - Silo 20260804 发布
版本: RELEASE.2026-08-04T00-00-00Z · 提交: d88f46ccee345a9c2fabe2d221d9a9e56bc11aec
SILO 20260804 是 pgsty/minio 社区分支的一次安全、正确性与发布工程更新。该版本完成 CVE-2026-42600 所开启的节点间存储边界治理,阻止客户端输入冒充服务端计算出的 S3/IAM 策略条件值,恢复流式响应 flush 语义,修复多项 multipart 与版本控制边界问题,加固通知配置迁移,将构建基线升级到 Go 1.26.5,并接入由 SILO 维护的 Console、共享包与 mcli 版本。发布流水线经过重建,产出可复现的二进制与 GPG 签名的软件包。
本次发布覆盖 2026-06-18 前基线之后的 50 个提交,共修改 155 个文件,新增 9,241 行、删除 981 行。每一处改动都针对已打标签的提交进行审查,并在 macOS ARM64 与 Linux AMD64 上验证,GitHub CI 在已发布 HEAD 上全部通过。
版本亮点
- 节点间边界收尾: 在存储边界校验 storage-REST 消息体、storage Grid 帧与 peer-S3 Grid 请求,关闭移除
ReadMultiple后残留的路径、卷、纠删元数据、panic 与无界分配缺陷。 - S3/IAM 决策使用真实有效值: 客户端输入不再能遮蔽内部条件值;请求标签与既有对象标签被分离;
s3:signatureAge被限制在经过验证的预签名请求内;s3:versionid跟随服务端实际操作的版本。 - Bucket 与 Object 资源分离: 十二项敏感的 bucket 级写操作不再能通过仅对象的
bucket/*资源模式被授权。提供一个有文档记录的兼容开关用于迁移。 - Multipart 兼容性与正确性改进: 协议允许时,完整对象校验和补全无需逐分片校验和即可工作;零长度 multipart 对象的校验和被保留;重复的分片编号被拒绝,而不是拼装出重复数据。
- 流式可靠性恢复:
trackingResponseWriter现在正确实现Flush并记录隐式 HTTP 200 响应,修复了 20260618 发布中记录的继承回归所影响的mcli watch、bucket 通知监听器与 S3 Select keep-alive。 - 通知配置加固: 解析器与旧迁移读取的 NATS、AMQP 键被注册并正确往返;libpq 连接参数被安全引用;非法键错误不再回显 secret 值。
- 可复现、已签名的发布流水线: 二进制不再嵌入构建机路径,软件包安装到规范的 systemd 路径,RPM 经过 GPG 签名。容器入口现在在每条权限路径上都能优雅退出。
- 发布基线刷新: Go 1.26.5、
klauspost/compress1.18.7、Apache Thrift 0.24.0、SILO Console 2.0.0、silo-pkg3.11.0 与mcli20260804。
安全加固
节点间 storage 与 Grid 边界 — SN-2026-002
20260618 移除过时的 ReadMultiple 端点关闭了一条可达路径,但并未关闭底层缺陷类别。storage-REST 请求体与 Grid RPC 帧不经过 HTTP 查询校验中间件,而 peer-S3 RPC 可以完全绕过 storage-REST 包装层。
本次发布把边界收敛到存储层,在使用前校验每一个调用方可控的路径、卷、纠删参数、分片大小、shard 长度与分配长度。修复包括:
- 在路径与卷两个维度拒绝穿越,包括 Windows 卷根别名;
- 覆盖那些不经 storage-REST 包装层就触达磁盘的 peer-S3 bucket RPC;
- 在 shard 运算之前拒绝为零或不可用的 data/parity/block-size 组合;
- 拒绝负的分片大小与被截断的 shard,而不是把它们报告为健康;
- 将 storage-REST
ReadFile的分配上限设为 5 GiB; - 约束其他源自节点间声明的分配;
- 在不阻塞调用方的前提下遏制 deadline-bounded 存储任务中的 panic;
- 在 keep-alive 响应间保留
ReadParts错误,并避免空分片列表的 trace panic。
这些路由需要集群 root 或节点间凭据,且仅在分布式纠删部署中注册。单节点 S3 行为不变。协议面分析见 节点间路径边界审计。
策略条件绑定真实有效值 — SN-2026-003
策略条件映射历史上把服务端计算的值与原始请求条目混在一起。因此一个客户端可控的拼写可以遮蔽或合成一个内部条件值。SILO 20260804 将 silo-pkg 3.11.0 的精确键查找规则与服务端来源归一化配对:
- 内部条件名不能作为任意客户端值提供;
s3:prefix、s3:delimiter、s3:max-keys取自各自的有效查询输入;- 基于 Header 的
x-amz-*条件不接受无关的查询替代值; - 当存储类别或上传标签同时支持两种形式时,显式存在的 Header 胜出,包括空 Header;
s3:ExistingObjectTag/*仅来自已存储的对象元数据;s3:RequestObjectTag/*绑定到相关操作实际消费的标签输入;s3:signatureAge只在经过验证的 SigV4 预签名认证计算出它之后才暴露;s3:versionid在未指定版本时缺席,并在DeleteObjects中按条目重新绑定到实际解析出的有效版本。
版本 ID 行为关闭了一个"简单省略空值"式修复本会为 Multi-Delete 制造的 fail-open 陷阱。见 缺席不等于为空。
Bucket/Object 资源边界 — SN-2026-004
IAM 匹配器过去会给 bucket 级请求追加一个斜杠,使得像 arn:aws:s3:::bucket/* 这样仅对象的资源能授权部分 bucket 级操作。本次发布在 Allow 语句上,将这十二项敏感写操作从该模式中排除:
PutBucketPolicy、DeleteBucketPolicy、PutBucketObjectLockConfiguration、PutBucketVersioning、PutReplicationConfiguration、PutBucketLifecycle、DeleteBucket、ForceDeleteBucket、PutBucketCors、DeleteBucketCors、PutBucketQOS 与 PutInventoryConfiguration。
Deny 与 NotResource 行为不变。读取/列举操作、CreateBucket、bucket 标签、默认加密与通知配置保持兼容。内置策略使用 Resource: "*",不受影响。
自定义 bucket 授权需要迁移策略
如果某个自定义策略仅用 arn:aws:s3:::bucket/*(常常通过 s3:*)授予这十二项操作之一,请补上裸 bucket ARN:
MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on 在策略迁移期间恢复历史匹配器。它同时也恢复了历史上的过度授权,因此只应作为临时回滚控制使用。
可信客户端地址边界
MINIO_API_TRUSTED_PROXIES 为 aws:SourceIp、审计 remotehost、事件通知 Host 以及 mcli admin trace 显示的客户端地址提供了一个可强制执行、按需启用的边界:
- 设为地址/CIDR 列表,则仅信任来自这些对端的转发头,并从右向左遍历转发链;
- 设为
none,则忽略所有转发头; - 保持未设置,则完全维持历史行为。
旧的 _MINIO_API_XFF_HEADER=off 开关仍然只抑制 X-Forwarded-For,它不防护 X-Real-IP 或 RFC 7239 Forwarded。如果基于 IP 的策略是你安全边界的一部分,请显式配置可信代理,并阻止对 S3 API 端口的直接访问。多节点部署应当允许自己的节点地址。见 客户端源地址信任。
S3 与存储正确性
Multipart Upload
- 当补全请求不提供逐分片校验和、且上传元数据不要求它们时,CompleteMultipartUpload 接受 S3 完整对象校验和模式。
- 零长度 multipart 对象的校验和被保留,而不是作为空元数据丢弃。
- 分片编号必须严格递增。像
[1,1]这样的重复条目现在返回InvalidPartOrder,而不是消费掉上传并把同一分片拼装两次。带间隙或非 1 起始的合法分片列表仍被接受。见 重复分片编号。
对象读取与 Buffer 所有权
- 纠删读取仅在所有权允许复用时才池化 buffer;
- 更新下载返回调用方拥有的 buffer,而不是暴露返回后可能被覆盖的数据;
- 移除
ReadMultiple后遗留的旧 HTTP 流式辅助函数,在引用与平台 tag 检查后被删除。
HTTP Response Tracking 与 S3 Select
trackingResponseWriter.Flush()委托给底层 flusher 并正确提交响应状态;- 第一次隐式写入记录 HTTP 200,保持审计与指标准确;
- S3 Select 测试不再让客户端解析器与响应体所有权竞争;
- CSV、JSON、Parquet 选择路径保持覆盖,包括 range/错误与 keep-alive 行为。
因此 SILO 20260618 中指出的继承性静默 flush 回归在本次发布中得到修复。
IAM、版本控制与审计行为
- DeleteObject 以及 DeleteObjects 中的每个条目,都针对服务端选定的有效版本评估
s3:versionid。 - 请求标签在策略评估期间不再能冒充既有对象标签。
- 在发出悬垂对象删除记录时恢复
merrs标签,保持预期的审计分类。 - Bucket-policy 与 IAM 路径共享加固后的条件来源规则,同时保留各自既定的 S3 路由与错误行为。
通知配置
- 注册解析器读取的 NATS
user_credentials、nkey_seed、tls_handshake_first键; - 将旧 NATS 环境变量拼写与存储的配置键分离;
- 修复 NATS 迁移往返与 AMQP
immediate/internal映射; - 增加一项机械审计,把通知代码读写的键与各子系统注册的 schema 做比对;
- 引用 libpq 连接串参数,使空白、引号与反斜杠保持其预期取值;
- 阻止非法键诊断回显 secret 值。
见 通知键空间注册。
已知的旧迁移限制
继承的 Postgres 与 MySQL 旧迁移函数仍然写入未注册的 host、port、username、password、database 字段。因此迁移后的配置可能在下次加载时校验失败,而通知目标加载是跨子系统 fail-fast 的。此问题早于 20260804,但从连接串之前的数据库通知配置升级时,必须在重启前审查并转换。存储的 password 字段可能包含明文数据库密码。
组件与依赖
- Go 1.26.5: 包含
crypto/tls与os的安全修复,以及编译器、运行时、网络与 syscall 的修正。 klauspost/compress1.18.7: 刷新对象与归档路径使用的压缩栈。- Apache Thrift 0.24.0: 更新经由 Parquet 支持编译进来的依赖。
- go-systemd 22.6.0: 有意保留而非升级到 22.7.0,因为后者引入了与受支持交叉构建矩阵不兼容的 NetBSD 时钟依赖。
- SILO Console 2.0.0: 嵌入式 console 选自
pgsty/silo-console,同时保留兼容的github.com/minio/console导入路径。 silo-pkg3.11.0: 提供配套的策略、LDAP、证书、RNG 与时间格式修复,同时保留github.com/minio/pkg/v3模块路径。mcli20260804: 嵌入式客户端来自pgsty/mc;发布镜像将其暴露为mcli并保留mc兼容别名。
配套发布说明见 silo-pkg 3.11.0、mcli 20260804 与 SILO Console 2.0.0。
构建、CI 与软件包
本次发布为可复现性与供应链完整性重建了发布流水线:
- 每条路径都优雅退出。 入口脚本的自定义 UID/GID 分支现在
exec进入服务端,使其以 PID 1 运行并直接接收SIGTERM;此前这些分支把一个中间 shell 留作 PID 1,服务端会在容器停止超时后被强杀。一个 CI 烟测会构建发布运行时镜像,并在默认路径与降权路径上断言优雅退出。 - 可复现二进制。 发布二进制不再嵌入构建机的
GOPATH/GOROOT,因此-trimpath生效,第三方从标签重建可得到一致的字节。已发布的 Linux 二进制不含任何构建机路径。 - 加固的发布工作流。 发布标签通过环境传入并做白名单校验,而不是拼接进 shell;构建检出的是正在发布的那个标签;一个可能越过流程发布或移动
latest的、未跟踪的影子 GoReleaser 配置被移除。 - 诚实的门禁。 CI 对构建、vet、单元测试、lint、生成漂移、race 测试与交叉编译把关;交叉编译矩阵对齐到实际发布目标的精确集合;lint 与依赖安装步骤现在会在真实错误上失败,而不是掩盖它们。
- 签名的规范软件包。 RPM、DEB、APK 软件包以 PGSTY 身份用 nFPM 产出,systemd unit 安装到
/usr/lib/systemd/system/minio.service并使用Type=notify,RPM 由 PGSTY 维护者密钥离线 GPG 签名(指纹9592A7BC 7A682E73 33376E09 E7935D8D B9BD8B20)。 - 归档与容器镜像分步发布。 GoReleaser 产出平台归档、校验和与软件包;多架构容器镜像基于已完成的发布产物构建并发布。
兼容性与升级说明
- 集群滚动升级期间保持所有节点在同一发布版本。 节点间校验在 storage-REST 与 Grid 面上发生了改变;混合二进制未经生产测试。
- 审查自定义 IAM 策略。 为这十二项受保护的 bucket 写操作补上裸 bucket ARN。仅将
MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on作为临时迁移控制。 - 有意识地配置客户端地址信任。 如果
aws:SourceIp或审计归属重要,请设置MINIO_API_TRUSTED_PROXIES并封闭代理周围的直连网络路径。 - 审查旧的数据库通知设置。 在重启前把 Postgres/MySQL 的 host/user/password 字段转换为受支持的连接串格式。
- 预期重复的 multipart 补全条目会失败。 多次发送同一分片编号的客户端现在会收到
InvalidPartOrder,而不是一个损坏但成功的对象。 - 使用匹配的
mcli。 20260804 客户端禁用了自更新,必须通过软件包或 GitHub Releases 升级;mcli update保留为兼容命令但以非零码退出。 - RPM 用户可启用签名校验。 软件包用上述维护者密钥签名;在为 SILO 软件包启用
gpgcheck之前先导入该密钥。
已执行验证
针对已打标签提交执行的验证包括:
git diff --check、gofmt、模块校验以及 YAML/shell 语法;go build ./...、go vet ./...、项目 lint 与govulncheck ./...;- 完整的
go test ./...、完整 race 套件,以及针对存储、策略、通知、HTTP tracking 与 S3 Select 改动的重复 race 测试; - 生成器幂等性,加上刻意构造的陈旧源与未跟踪产物反例;
- 对每个发布目标的交叉编译;
- Linux AMD64 原生全量测试、定向 race 测试、真实 S3/
mcli冒烟测试(创建/上传/下载/复制、range、版本控制、删除标记、健康检查、优雅退出、重启持久化)与 systemd notify 行为; - 发布产物验证:GitHub CI 在已发布 HEAD 上全绿、可复现二进制不含构建机路径、systemd unit 安装到
/usr/lib/systemd/system、RPM 签名以rpmkeys --checksig校验通过。
govulncheck 未发现可从 Server 或 mcli 代码到达的漏洞。对无人维护的 golang.org/x/crypto/openpgp 包仍有一条模块级提示(GO-2026-5932);该包未被编译进这些二进制。
验证边界
原生执行测试在 Linux AMD64 与 macOS ARM64 上完成;Windows、Intel macOS 与 Linux ARM64 目标完成了交叉编译。本轮测试未连接外部在线 LDAP、OIDC、KMS、STS、Postgres、MySQL、NATS 与 AMQP 端点。
发布产物
- GitHub release
RELEASE.2026-08-04T00-00-00Z,含 Linux、Darwin、Windows 在 amd64 与 arm64 上带校验和的平台归档; - PGSTY 身份下的 RPM、DEB、APK 软件包,其中 RPM 经 GPG 签名;
docker.io/pgsty/minio:RELEASE.2026-08-04T00-00-00Z以及发布选定的latest标签,从发布按需产出;- 配套的 SILO Console 2.0.0、
silo-pkg3.11.0 与mcli20260804 引用。
重点提交
ca7baa670、80e8eaa42、b6f70ab08:校验节点间路径、纠删元数据与分配大小a36fd8fff:遏制 deadline-bounded 存储任务中的 panic2f55347f7:将 S3/IAM 策略条件绑定到真实请求值744a9dcd7:将s3:versionid绑定到有效对象版本97b7d2804:强制 bucket/object 资源边界fe6dc4780:新增可信代理客户端地址边界22c1e41fd:拒绝重复的 multipart 分片编号c8590413f、3e14733f1:恢复完整对象与零长度 multipart 校验和行为8069a32ac、65795ee1f:恢复响应提交与流式 flush 语义162ded343、0c14d8151:修复通知键注册与 libpq 引用924717926、89d346bf5:恢复安全的 buffer 池化与返回 buffer 所有权3b8a55dee:exec 进入降权进程使信号抵达服务端2ca4971d9:停止把构建机路径烧入二进制4c185d5a6、e064b5555:加固发布工作流并移除影子配置aa5139369:将 systemd unit 安装到/usr/lib11d79fddc、ca674a696、021110b45、d88f46cce:对构建、vet、测试、lint、生成、race 与交叉编译把关,并对发布镜像做烟测
30 - mcli 20260804 发布
发布日期: 2026-08-04 · 版本: RELEASE.2026-08-04T00-00-00Z
这是 pgsty/mc 社区分支自 20260417 以来的首次发布。本次更新修复了一处调试日志泄密问题,彻底切断了客户端与上游发布渠道之间的所有连接,将容器与软件包完全改由本分支自建,并把打包体系从 MinIO 的 pkger 迁移到标准 nFPM,同时首次为 RPM 包提供 GPG 签名。
上游 minio/mc 仓库已于 2026 年 7 月归档。其最后一个提交 77f82e18 正是本分支的基线,而上游从未发布过包含该提交的版本 —— 因此本次构建比历史上任何官方 mc 二进制都要新。
行为变更
mcli update 自更新功能在本分支中 已被禁用。命令本身保留(接受原有参数以维持脚本兼容),但不再联网检查、也不会替换自身二进制,执行时会打印明确的提示信息,并恒定以退出码 1 结束。上游 mc update 在已是最新版时返回 0,脚本中如有依赖其退出码的调用应予移除。请通过 Pigsty 软件仓库或 GitHub Releases 升级。
同时,每次执行命令时向上游发布源发起的 自动版本检查已完全移除,MC_UPDATE / MINIO_UPDATE 环境变量不再被读取。
主要变更
- 禁用自更新,切断上游发布渠道:移除
minio/selfupdate与aead.dev/minisign依赖及全部二进制替换逻辑,删除更新通知器与 FIPS/非 FIPS 更新分支。update命令保留为兼容壳,运行时辅助函数(Docker / DCOS / Kubernetes / 源码构建检测)迁移至独立的cmd/runtime-info.go。此前该客户端会在每次执行时静默访问上游发布源并提示升级,现已不再有任何出站发布探测。 - 容器与制品全部本地化:默认镜像改为从检出的分支源码构建,hotfix 二进制从本地构建上下文拷贝,不再下载任何上游预编译产物。移除上游发布用的
Dockerfile.release、Dockerfile.release.old_cpu与docker-buildx.sh,并禁用已失效的 MinIO hotfix 上传目标。 - 打包体系迁移至 nFPM:从 MinIO 的
pkger迁移到标准 nFPM。产物结构与安装路径保持完全一致(/usr/local/bin/mcli、包名mcli、版本方案YYYYMMDDHHMMSS.0.0),但供应商信息改为 PGSTY,许可证改用 SPDX 标识AGPL-3.0-or-later,DebianSection由空值改为utils。 - RPM 包首次提供 GPG 签名:RPM 由维护者主密钥在本地离线签名(密钥指纹
9592A7BC7A682E7333376E09E7935D8DB9BD8B20),签名前校验全部包元数据,签名后复验并重新生成校验和。DEB 与 APK 不做包级签名,其信任锚位于软件仓库层。 - 构建溯源加固:此前所有已发布二进制都被 Go 工具链标记为「来自被修改的工作树」(
vcs.modified=true),导致产物无法与其 Git 标签对应。本次修复该问题,并在发布与测试流水线中加入强制校验,确保每个二进制都能追溯到确切的提交。
安全修复
- SUBNET 调试日志凭据脱敏:启用
--debug时,SUBNET 相关的 HTTP 请求会打印完整报文。此前api-key/api_key查询参数、认证头以及响应体均以明文进入日志,而 SUBNET 的认证与注册端点会在响应中返回 API Key、License 与 Token。本次修复对两种参数拼写、重复参数值统一脱敏,屏蔽敏感响应头,并将 SUBNET 响应体整体排除在调试转储之外。该泄漏继承自上游,存在于包括上游mc在内的所有历史版本中:如果你曾对外分享过 SUBNET 相关命令(mcli license .../mcli support ...)的--debug输出,请将其中的 API Key 与 License 视为已泄露并及时轮换。 - 调试脱敏与调用方状态隔离:调试追踪改为转储请求与响应的 副本,确保脱敏动作不会污染调用方持有的对象;覆盖零长度、定长与未知长度三种响应体形态,且不影响调用方正常读取响应内容。
依赖更新
除 term / mod / sync / tools 四项常规刷新外,以下每一项升级都关闭了 Go 漏洞数据库中已发布的安全公告;govulncheck 对本次发布的代码报告 零个可达的已知漏洞。minio/mc、minio-go、madmin-go、minio/pkg 四个包本身无已公开的安全公告。
- Go 构建基线由
1.26.2升级至1.26.5(截至发布时 1.26 线最新版),纳入 1.26.3–1.26.5 各批安全修复,包括 GO-2026-4970(os包符号链接根逃逸)与 GO-2026-5856(crypto/tlsECH 隐私泄漏)—— 对一个通过 TLS 下载对象并写入本地文件的 S3 客户端而言最直接相关的两项。 github.com/klauspost/compress由v1.18.5升级至v1.18.7(关闭 GO-2026-5841)。github.com/prometheus/prometheus由v0.310.0升级至v0.311.3(关闭 GO-2026-5264、GO-2026-5381、GO-2026-5710)。google.golang.org/grpc由v1.79.3升级至v1.82.1(关闭 GO-2026-6061),同步刷新genproto系列。golang.org/x/*系列整体刷新:cryptov0.49.0→v0.53.0(GO-2026-5005…5033 共 14 项公告)、netv0.52.0→v0.56.0(GO-2026-5025…5030 及 GO-2026-5942)、sysv0.42.0→v0.46.0(GO-2026-5024)、textv0.35.0→v0.39.0(GO-2026-5970),term、mod、sync、tools同步升级。- 移除
aead.dev/minisign与github.com/minio/selfupdate,并同步更新第三方致谢清单。
工程与交付
- 集成测试依赖钉死:CI 不再从上游可变地址下载 MinIO 服务端,改用带 SHA-256 校验的
pgsty/minio版本化发布归档,Go 版本钉在1.26.5。 - 发布流水线校验:新增打包验证工作流,逐字节比对三种包格式内的二进制与构建产物是否一致,并校验包名、校验和、架构字段与全部元数据。RPM 元数据的期望值以签名脚本为唯一事实源,避免配置漂移导致发布中途签名失败。
- CI 供应链加固:全部 GitHub Actions 钉到 commit SHA 并接入 dependabot,工作流权限收敛为只读,移除指向上游组织项目板的失效工作流。
- 文档更新:README 中英文版本明确本分支的分发渠道与自更新策略,移除会导致误装上游
mc的安装指引。
已知问题
mcli watch(桶事件监听)在对接 任何已发布的 pgsty/minio 服务端版本时都无法收到事件。根因是服务端侧一处继承自上游的静默流式 flush 回归,与客户端无关,上一个 mcli 版本受影响的程度完全相同;修复已于 2026-07-29 合入服务端 master,但尚未随公开服务端版本交付。详见 SILO 20260618 发布说明 与 PR #34。
另外,本分支继承了上游未修复的历史缺陷;上游仓库已归档,这些问题今后只可能在本分支修复。其中最严重的是 minio/mc#5139:mirror --remove --watch 在源端删除对象的 非当前版本 时,可能误删目标端的现存对象。在版本化桶上组合使用 --remove --watch 时请务必谨慎。
关联提交
- 9603ee3:fix: redact SUBNET secrets in HTTP debug logs
- f6ae2b0:fix: disable self-update in Pigsty builds
- c05a6e4:build: update Go deps and toolchain to 1.26.5
- 1f105aa:build: use local fork artifacts for containers
- 1182da5:ci: pin fork integration test dependencies
- 9ee207f:docs: clarify Pigsty fork distribution channels
- 0686cd8:fix: isolate SUBNET debug redaction
- ad10a2a:build: complete local Docker context isolation
- 5f54221:docs: update mc README and cn version
- 02c0305:build: migrate release packaging to nFPM
- 4c4dcc4:build: harden release provenance and package metadata
31 - Silo 20260618 发布
发布日期: 2026-06-18 · 版本: RELEASE.2026-06-18T00-00-00Z
这是 pgsty/minio 社区分支的一次例行安全与依赖维护更新。该版本加固 LDAP STS 限流,补齐 S3 Select 超大记录限制,移除废弃的 ReadMultiple 节点间 storage-REST API,将 Go 构建基线升级到 1.26.4,并刷新 Go 模块依赖以吸收第三方安全修复。
说明
已知问题:本版本与自 RELEASE.2025-12-03T12-00-00Z 以来的所有早期社区版本一样,带有一个继承自上游的静默流式 flush 回归,会导致 mc watch / 桶事件通知监听以及 S3 Select keepalive 失效。修复(PR #34)已随 SILO 20260804 发布。
主要变更
- 移除废弃的
ReadMultiplestorage-REST API:旧的节点间/rmpl端点不再保留兼容路径,而是连同 route、handler、client wrapper、storage interface、xlStorage 方法、生成数据类型和相关 metric 一并移除。上游 multipart 处理迁移到ReadParts之后不应再有生产调用者,但滚动升级时仍应让集群运行一致版本。 - 补齐 S3 Select 超大记录限制:JSON Lines 输入现在走有界 reader 路径,因此在支持 SIMD 的 CPU 上也会一致拒绝超大记录,不再绕过限制。S3 Select stream error 现在会保留预期错误码,并将 JSON parser 错误包装为
JSONParsingError。 - 加固 LDAP STS 限流源地址分桶:限流现在仅按源 IP 分桶,避免按用户名共享的 bucket 被单一客户端耗尽并锁定合法用户。受信代理处理现在从右到左解析
X-Forwarded-For,拒绝全网段 trusted-proxy CIDR,忽略 RFC 7239Forwarded,并明确记录X-Real-IP的部署约定。 - 刷新 Go 运行时与模块基线:release、hotfix、goreleaser 与 old-CPU Docker 构建现在都使用
golang:1.26.4-alpine;go.mod更新到 Go1.26.4;依赖刷新覆盖 NATS、Prometheus、Azure SDK、Apache Thrift、gRPC、OpenTelemetry、Google API/auth、Gox/*以及相关间接依赖。
直接安全修复
- CVE-2026-42600:移除废弃的
ReadMultiplestorage-REST API,关闭/rmpl暴露的旧节点间文件读取路径。 - CVE-2026-39414:补齐 JSON Lines 输入的 S3 Select 超大记录限制,并保留正确的 S3 Select 错误语义。
- CVE-2026-33419:进一步强化 LDAP STS 限流记账与 trusted-proxy 源 IP 处理。
依赖安全更新
- 将
github.com/Azure/go-ntlmssp从v0.1.0升级到v0.1.1,修复 CVE-2026-32952,避免畸形 NTLM challenge 触发 Go 进程 panic。 - 将
github.com/apache/thrift从v0.22.0升级到v0.23.0,修复 GoTFramedTransport实现中的 CVE-2026-41602。 - 将
github.com/nats-io/nats-server/v2从v2.11.1升级到v2.11.15,吸收 NATS 2.11.x 安全补丁线。重点覆盖 pre-auth WebSocket 与 leafnode 拒绝服务、MQTT 授权、JetStream 管理 API 授权、凭据暴露和请求身份伪造等问题,包括 CVE-2026-27889、CVE-2026-29785、CVE-2026-33217、CVE-2026-33218、CVE-2026-33222 与 CVE-2026-33247。 - 将
github.com/prometheus/prometheus从v0.310.0升级到v0.311.3,吸收 Prometheus 关于 remote-read 拒绝服务、Web UI 存储型 XSS、remote-write 配置 secret 暴露等安全修复,包括 CVE-2026-42154、CVE-2026-44903、CVE-2026-42151 与 CVE-2026-40179。 - 将发布构建基线升级到 Go
1.26.4,并刷新golang.org/x/crypto、golang.org/x/net、golang.org/x/sys、golang.org/x/text、google.golang.org/grpc与 OpenTelemetry 等模块族。即便此前锁定版本已经越过特定公开 advisory 的修复范围,这些更新仍让社区分支继续贴近上游已修复依赖基线。
关联提交
32 - Silo 20260417 发布
发布日期: 2026-04-17 · 版本: RELEASE.2026-04-17T00-00-00Z
本次版本聚焦安全加固与兼容性收敛,集中修复了 OIDC、LDAP STS、S3 Select、对象复制元数据、unsigned-trailer、Snowball 上传链路,以及依赖与 Go 工具链相关的多项安全问题,并同步完成 LDAP TLS 回归修复与社区分叉文档整理。
主要变更
- 身份认证链路收紧:OIDC / WebIdentity 现在只接受来自 IdP
JWKS的非对称签名ID Token,HS256等对称签名 token 不再被接受;LDAP STS 统一隐藏“未知用户”和“密码错误”的区别,降低用户名枚举风险。 - LDAP STS 限流行为更新:限流现在同时按源 IP 与归一化用户名生效,成功请求不再错误消耗额度;默认仅使用 socket peer address 作为源地址,不再信任
X-Forwarded-For、X-Real-IP、Forwarded,如需按真实客户端 IP 限流,需显式配置MINIO_IDENTITY_LDAP_STS_TRUSTED_PROXIES。 - 上传与写入路径更严格:presigned query 参数不能再与
unsigned-trailer的PUT/ multipart 上传组合使用;Snowball auto-extract 在unsigned-trailer路径下也会执行完整签名校验,匿名或伪造签名请求将被拒绝。 - 复制元数据不再可伪造:普通
PUT/COPY请求夹带的X-Minio-Replication-*内部复制头现在会被拒绝或忽略,只有可信复制链路才能写入相关内部元数据。 - S3 Select 错误语义更明确:CSV 和 line-delimited JSON 遇到超大记录时会直接返回
OverMaxRecordSize,不再笼统返回InternalError;依赖旧错误码的客户端或告警规则需要同步调整。 - 运行时与依赖基线升级:修复
ldaps://未正确应用 TLS 配置的回归问题,替换minio/pkg/v3为pgsty/minio-pkg/v3,并锁定若干易引入 breaking changes 的关键依赖;同时升级go-jose、go.opentelemetry.io与 Go1.26.2,统一构建与发布基线。 - 文档与安全说明同步更新:刷新
SECURITY.md、VULNERABILITY_REPORT.md、docs/sts/ldap.md等文档,新增安全通告索引,并将安全说明中的上游minio/minio引用统一切换为pgsty/minio。
修复的 CVE
- CVE-2026-34986:升级
go-jose到v4.1.4,修复 JWT / JOSE 依赖中的已知安全问题。 - CVE-2026-39883:升级
go.opentelemetry.io依赖栈,修复 PATH hijacking 风险。 - CVE-2026-33322:恢复严格的 JWKS-only OIDC JWT 验证路径,阻断 keyring 注入与算法混淆风险。
- CVE-2026-33419:系统性强化 LDAP STS 认证、限流、源地址识别与记账逻辑,涉及 4 个后续修复提交。
- CVE-2026-34204:拒绝不可信请求注入
X-Minio-Replication-*元数据,防止对象被写入异常复制状态。 - CVE-2026-39414:提前拒绝超大 S3 Select 记录,避免异常数据持续缓冲和解析。
- GHSA-hv4r-mvr4-25vw:封堵 unsigned-trailer query auth 绕过。
- GHSA-9c4q-hq6p-c237:加固 Snowball auto-extract 场景中的 unsigned-trailer 认证与签名校验。
- CVE-2026-32280、CVE-2026-32281、CVE-2026-32283:升级 Go 到
1.26.2,吸收上游工具链与标准库安全修复。
关联提交
- ce1c537:fix: pin deps with breaking changes and fix LDAP TLS regression (#15)
- 68e0ba9:fix: upgrade go-jose to v4.1.4 to patch CVE-2026-34986
- 1869bd3:fix: CVE-2026-39883 upgrade go.opentelemetry.io
- ff58df9:merge: PR #18 upgrade go-jose to v4.1.4 for CVE-2026-34986
- e4fa063:merge: PR #19 upgrade go.opentelemetry.io for CVE-2026-39883
- d24f449:fix: CVE-2026-33322 restore JWKS-only OIDC JWT verification
- 3b950f8:fix: CVE-2026-33419 harden LDAP STS auth
- 56fa63b:fix: CVE-2026-34204 reject untrusted replication metadata
- 3252d5b:fix: CVE-2026-39414 reject oversized S3 Select records
- f444b6f37:fix: fake CVE-2026-40027 block unsigned-trailer query auth bypass
- efb6e5b00:fix: fake CVE-2026-40028 harden snowball unsigned-trailer auth
- db4c0fd:fix: CVE-2026-32280/CVE-2026-32281/CVE-2026-32283 upgrade Go to 1.26.2
- 18b712d:fix: CVE-2026-33419 preserve LDAP STS rate limits on success
- 9e10f6d:fix: CVE-2026-33419 harden LDAP STS rate-limit source IP
- f441108:fix: CVE-2026-33419 tighten LDAP STS rate-limit accounting
- f48dbe7:docs: refresh security guidance and fork references
33 - Silo 20260325 发布
发布日期: 2026-03-25 · 版本: RELEASE.2026-03-25T00-00-00Z
本版本重点改进容器镜像打包、修复 ldaps:// 连接的 TLS 配置透传回归,并同步锁定多项第三方依赖的安全更新版本。
主要变更
- 将
mcli(及兼容别名mc)内置到 Docker 镜像中并增加二进制校验,开箱即可直接执行管理命令。 - 修复
ldaps://场景下的 LDAP TLS 配置回归,确保自定义 CA 证书与MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY正确透传。 - 清理从上游继承但社区分支不再使用的历史 CI/CD 工作流。
- 锁定多项关键依赖版本,隔离上游非兼容变更并提供以下安全修复。
修复的 CVE
- CVE-2026-24051:将
go.opentelemetry.io/otel/sdk锁定至安全版本v1.42.0,消除 macOS 上因PATH劫持触发任意代码执行的风险。 - CVE-2025-10543:升级至
github.com/eclipse/paho.mqtt.golang v1.5.1,修复超长 UTF-8 字符串编码错误导致的 MQTT 数据包内容异常。 - CVE-2025-58181:升级至
golang.org/x/crypto v0.49.0,修复sshGSSAPI 认证请求可触发的无界内存消耗问题。
关联提交
34 - Silo 20260321 发布
发布日期: 2026-03-21 · 版本: RELEASE.2026-03-21T00-00-00Z
这是一次围绕 Go 1.26.1 与依赖收敛展开的维护版。除了适配更严格的编译与 lint 检查外,这个版本也完成了本轮最关键的一次安全依赖刷新。
主要变更
- 将构建环境从 Go
1.26.0升级到 Go1.26.1。 - 全面刷新直接与间接依赖,收敛新工具链下的兼容性问题。
- 修正 Go 1.26.1 更严格检查暴露出来的一批 lint 与测试问题。
修复的 CVE
- CVE-2026-27137:Go stdlib 从
1.26.0升级到1.26.1,修复crypto/x509对邮箱约束校验不完整的问题。 - CVE-2026-27138:Go stdlib 从
1.26.0升级到1.26.1,修复畸形证书触发crypto/x509panic 的问题。 - CVE-2026-25679:Go stdlib 从
1.26.0升级到1.26.1,修复net/url对 IPv6 host literal 解析不严格的问题。 - CVE-2026-27139:Go stdlib 从
1.26.0升级到1.26.1,修复os中FileInfo可逃逸Root边界的问题。 - CVE-2026-27142:Go stdlib 从
1.26.0升级到1.26.1,修复html/template在meta refresh场景下 URL 未正确转义的 XSS 风险。 - CVE-2026-26958:
filippo.io/edwards25519从v1.1.0升级到v1.2.0,修复MultiScalarMult可能产生错误结果或未定义行为的问题。 - CVE-2025-10543:
github.com/eclipse/paho.mqtt.golang从v1.5.0升级到v1.5.1,修复超长 UTF-8 字符串编码错误导致的 MQTT 报文异常。 - CVE-2026-24051:
go.opentelemetry.io/otel/sdk从v1.38.0升级到v1.42.0,修复 macOS 上通过 PATH hijacking 触发任意代码执行的风险。 - CVE-2026-33186:
google.golang.org/grpc从v1.77.0升级到v1.79.3,修复 HTTP/2:path缺少前导斜杠时的授权绕过问题。
关联提交
35 - Silo 20260314 发布
发布日期: 2026-03-14 · 版本: RELEASE.2026-03-14T12-00-00Z
这个版本完成了向社区维护 Console 分支的切换,并在切换过程中做了一轮较大幅度的依赖更新,为后续 Go 1.26.x 维护版打下基础。
主要变更
- 切换到社区维护的
georgmangold/console v1.9.1,替换不可持续维护的上游 Console 依赖。 - 大幅更新
go.mod中的直接与间接依赖,使 Console 与新工具链组合能够稳定构建。 - 修复
grid_test.go的go vet格式化指令问题,并调整部分测试以适配 Go 1.26 的 HTTP 行为变化。
修复的 CVE
- CVE-2025-47913:
golang.org/x/crypto从v0.37.0升级到v0.46.0,修复ssh/agent在处理异常响应时可能导致客户端 panic 的问题。 - CVE-2025-58181:
golang.org/x/crypto从v0.37.0升级到v0.46.0,修复sshGSSAPI 认证请求可触发无界内存消耗的问题。 - CVE-2025-47914:
golang.org/x/crypto从v0.37.0升级到v0.46.0,修复ssh/agent对畸形身份消息缺乏边界校验导致的 panic 问题。 - CVE-2025-47911:
golang.org/x/net从v0.39.0升级到v0.48.0,修复html.Parse在特制输入下的二次复杂度解析问题。 - CVE-2025-58190:
golang.org/x/net从v0.39.0升级到v0.48.0,修复golang.org/x/net/html可能陷入无限解析循环的问题。
关联提交
36 - Silo 20260214 发布
发布日期: 2026-02-14 · 版本: RELEASE.2026-02-14T12-00-00Z
这是社区分支早期的一个基础设施版本,除了恢复内嵌 Console 与建立 GitHub CI/CD 之外,也把 Go 运行时基线提升到 1.26.0,因此一并消化了上一代工具链中的一批安全问题。
主要变更
- 恢复内嵌 Console,并更新 README 以明确社区维护分支的定位。
- 新增 GitHub CI/CD 流水线,为后续自动构建和多平台分发建立基础。
- 补充文档、Docker、GitHub 仓库与
pig包管理器安装入口,完善发布入口。
修复的 CVE
这些问题随着 Go 从 1.25.5 升级到 1.26.0 一并被修复,包括:
- CVE-2025-68121:
crypto/tls在会话恢复时可能错误接受已变更 CA 配置。 - CVE-2025-61730:TLS 1.3 在跨加密级别 record 中可能错误处理握手消息。
- CVE-2025-61726:
net/url查询参数解析可导致内存耗尽。 - CVE-2025-61728:
archive/zip构建索引时可能触发过高 CPU 消耗。 - CVE-2025-68119:
cmd/go在调用外部 VCS 工具链时可能触发意外代码执行。 - CVE-2025-61731:
#cgo pkg-config:指令可导致任意文件写入。 - CVE-2025-61732:
cmd/cgo文档注释解析差异可能导致代码走私。
关联提交
- 8630937:Restore embedded console and update README for community fork
- 68521b3:add github ci/cd pipeline
历史说明:CI/CD 流水线证据链接维护主线的 68521b37f,保留原流水线文件并包含 README 调整。
37 - Silo 20251203 发布
发布日期: 2025-12-15 · 版本: RELEASE.2025-12-03T12-00-00Z
这是目前可追溯到的首个社区版发布,确立了社区维护分支的打包与分发基线。
主要变更
- 基于
minio/pkger建立社区版打包流程。 - 选择 MinIO 进入 maintenance mode 后的一版上游基线作为社区分支起点。
- 首次产出
apk、deb、rpm等多种平台包,为后续持续发布建立基础。
修复的 CVE
- 首个社区版发布基线,无相对前序社区版本的增量 CVE 列表。
关联提交
- d4cd4b4:RELEASE.2025-12-03T12-00-00Z with go 1.25.5