mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-22 02:27:44 +08:00
feat(ql3): validate cluster credential key rotation
This commit is contained in:
@@ -23,7 +23,7 @@ ServiceAccount 和 Pod 都关闭自动 token 挂载,不创建 Role、RoleBindi
|
||||
|
||||
Secret volume 必须兼容 kubelet 的版本目录与 symlink 投影,默认 `0440` 以便固定的非 root group 读取;但 ADR-0500 的命令拒绝 symlink 和 group/world 权限。因此在既有 `@qinglong/cluster-admin/security-administration` 内增加专用 init stager,而不新建 package。
|
||||
|
||||
stager 只接受固定的 `command.json`、`assertion.jwt`、`keyset.json` 和 `pepper`,分别有 64 KiB、16 KiB、256 KiB 与 256 B 上限。它解析 kubelet symlink 后仍要求 realpath 留在投影 authority 内,以 `O_NOFOLLOW` 打开最终文件,复验类型、权限、大小和读前/读后 inode 状态,再清零源 Buffer。目标目录必须不存在,由 stager 创建为 `0700`;文件以 `0600`、`fsync` 和 hard-link no-replace 发布到 1 MiB memory-backed `emptyDir`。任何输入失败都清理已发布目标,主容器不会启动。
|
||||
stager 只接受固定的 `command.json`、`assertion.jwt`、`keyset.json` 和 `pepper-keyring.json`,分别有 64 KiB、16 KiB、256 KiB 与 2 KiB 上限。Kubernetes 路径以 D-407 keyring 为唯一 canonical 输入;旧单 pepper 只保留在通用 CLI 兼容桥,不形成第二套 Kubernetes 配置模式。stager 解析 kubelet symlink 后仍要求 realpath 留在投影 authority 内,以 `O_NOFOLLOW` 打开最终文件,复验类型、权限、大小和读前/读后 inode 状态,再清零源 Buffer。目标目录必须不存在,由 stager 创建为 `0700`;文件以 `0600`、`fsync` 和 hard-link no-replace 发布到 1 MiB memory-backed `emptyDir`。任何输入失败都清理已发布目标,主容器不会启动。
|
||||
|
||||
### 3. 数据库和进程权限保持最小化
|
||||
|
||||
@@ -57,7 +57,7 @@ Identity 变更、revoke 和 audit query 使用无 delivery 的 base。只有 `c
|
||||
|
||||
## 验证
|
||||
|
||||
- stager 聚焦测试覆盖真实 kubelet symlink 布局、`0700/0600` 收紧、持久 delivery 目录复验、realpath 逃逸、world-readable material、目标不可覆盖和 CLI 无敏感回显。
|
||||
- stager 聚焦测试覆盖真实 kubelet symlink 布局、2 KiB keyring 边界、`0700/0600` 收紧、持久 delivery 目录复验、realpath 逃逸、world-readable material、目标不可覆盖和 CLI 无敏感回显。
|
||||
- 部署审计冻结无 API token/RBAC、caller-driven/零重试/deadline/TTL、non-root/read-only/drop-all、资源上限、固定 CLI、内存私有输入、独立 admin credential、CloudNativePG egress、PVC delivery 和默认聚合不可达;失败注入覆盖权限扩大、非持久 delivery 与误入共享 aggregate。
|
||||
- `kubectl kustomize` 已分别渲染 base、CloudNativePG、credential-delivery 和 CloudNativePG + delivery 四个入口。
|
||||
- 18-package clean build/test 退出 0;当前 `cluster-admin` 为 456 total / 453 pass / 3 conditional skip / 0 fail,backend 为 1590 total / 1588 pass / 2 conditional skip / 0 fail。
|
||||
|
||||
@@ -17,7 +17,7 @@ QingLong 3.0 同时服务低配路由设备与集群节点。pepper rotation 只
|
||||
|
||||
`runtime-core` 提供 schema v1 keyring:一个 `activePepperKeyId` 和 1–2 个唯一 `{pepperKeyId,pepper}`。每个 ID 与 32-byte canonical base64url material 都使用既有 credential contract 校验,active ID 必须存在于 keys。原单 pepper 配置只通过显式 `legacy-v1` singleton bridge 保持兼容,不允许自动发现、环境合并或第三代历史 key。
|
||||
|
||||
Cluster Control 可从 `QL3_API_CREDENTIAL_PEPPER_KEYRING_FILE` 读取不超过 2 KiB 的 canonical 私有 JSON;它与旧 `QL3_API_CREDENTIAL_PEPPER` 必须二选一。文件必须是 canonical absolute regular file、不可为 symlink、不可向 group/world 开放,并在稳定 inode/mtime/size 下读取。运行时不安装 watcher;切换 keyring 后由部署系统执行受控滚动重启。
|
||||
Cluster Control 可从 `QL3_API_CREDENTIAL_PEPPER_KEYRING_FILE` 读取不超过 2 KiB 的 canonical 私有 JSON;它与旧 `QL3_API_CREDENTIAL_PEPPER` 必须二选一。文件必须是 canonical absolute regular file、不可为 symlink、不可向 group/world 写入,并在稳定 inode/mtime/size 下读取。Kubernetes 以只读 Secret volume 和 Pod 专属 fsGroup 提供该文件。运行时不安装 watcher;切换 keyring 后由部署系统执行受控滚动重启。
|
||||
|
||||
### 2. 认证严格按 durable key ID 选择
|
||||
|
||||
@@ -70,10 +70,12 @@ CLI 在 `--pepper` 与 `--pepper-keyring` 中必须精确选择一个。keyring
|
||||
- Cluster Control 覆盖 old/new overlap、stored key exact selection、unknown stored key fail-closed、旧环境变量 bridge、私有 keyring 文件与双来源拒绝;
|
||||
- Security Administration 覆盖新 credential 绑定 active key、keyring CLI、引用查询 exact command/result 与旧单 pepper bridge;
|
||||
- PostgreSQL repository 覆盖数据库时间、latest active/unexpired 过滤、limit+1、空引用与畸形行 fail-closed;
|
||||
- 当前 `cluster-admin` 完整回归为 458 total / 455 pass / 3 conditional skip / 0 fail,`cluster-control` 为 281 total / 279 pass / 2 conditional skip / 0 fail;D-407 聚焦构建与 33 项测试通过,`3.0.0-alpha.1` 身份下 18-package clean build/test 退出 0,backend 为 1592 total / 1590 pass / 2 conditional skip / 0 fail。
|
||||
- Kubernetes Security Administration 只投影 `pepper-keyring.json`,stager 以 2 KiB 边界私有化到 memory-backed `0700/0600` 目录;常驻 Cluster Control 同样只挂载 keyring 文件,不再从 Secret 注入旧单值环境变量;
|
||||
- overlap-old-active、activate-new、旧代引用 1→0 与 contract-new 的三节点 K3s/CloudNativePG live 合同已经编码;它在三次 rollout 中保持两个反亲和 Cluster Control 副本,并以真实 `/api/v3` 请求证明 old/new 在 overlap 期间认证成功但因无 Project role 返回 403、old 在 contract 后返回 401、new 仍返回 403。content-free schema 只记录状态码、引用计数、1 个旧代/3 个新代 durable version 与审计计数;远程 live 门通过前不得宣称该 ceremony 已验收;
|
||||
- 当前 `cluster-admin` 完整回归为 459 total / 456 pass / 3 conditional skip / 0 fail,`cluster-control` 为 281 total / 279 pass / 2 conditional skip / 0 fail;本轮 Kubernetes/report/stager 聚焦测试 23 项、相关共享 live fixture 静态测试 54 项以及三个部署审计通过,`3.0.0-alpha.1` 身份下 18-package clean build/test 完成(Worker Runtime 3 个 loopback 用例在沙箱外复验为 135/135),backend 为 1594 total / 1592 pass / 2 conditional skip / 0 fail。
|
||||
|
||||
## 影响与剩余门禁
|
||||
|
||||
D-407 关闭了“数据库记录 key ID、运行时却只能使用一个固定 pepper”的结构性缺口。Edge/Standalone package、依赖和常驻路径零变化;Cluster 每个认证请求仍只解析 record 并计算一个摘要,管理引用检查只在显式短命令中打开一个 admin connection。
|
||||
|
||||
D-406 Kubernetes stager/Job 仍只接受单 `pepper` 文件,不能用它执行双代 ceremony;在增加 keyring Secret 投影、失败注入和真实 K3s/CNPG overlap→activate→contract 验收前,Kubernetes 部署继续停留在 singleton bridge。远程管理 API/UI、双人复核/break-glass、material GC、audit retention/export/alert 和大规模引用查询计划也仍未完成。
|
||||
D-406 Kubernetes stager/Job 与常驻 Cluster Control manifest 已收敛为 keyring-only;旧单 pepper 只存在于通用 CLI/进程配置兼容桥。真实 K3s/CNPG overlap→activate→contract live 合同已实现但仍需在受审远程门中验收,因此当前不能把实现完成解释为 live ceremony 已关闭。远程管理 API/UI、双人复核/break-glass、material GC、audit retention/export/alert 和大规模引用查询计划也仍未完成。
|
||||
|
||||
Reference in New Issue
Block a user