feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,120 @@
# ADR-0241Kubernetes Worker Credential TokenRequest Session
- 状态:Accepted
- 日期:2026-08-01
- 关联 RFCQL-RFC-0001 D-23、D-58、D-175、D-224、D-225
- 关联 ADRADR-0060、ADR-0061、ADR-0124、ADR-0192、ADR-0234、ADR-0240
- 收窄:ADR-0240 的 TokenRequest 签发与销毁产品接线;不替代其双 namespace、prepared target 或 delivery RBAC 决策
## 背景
ADR-0240 已把 Kubernetes credential delivery 收窄到短期 ServiceAccount token 与双
namespace 最小 RBAC,但当时的 live fixture 仍直接执行 `kubectl create token`。该命令会把
bearer token 返回给 shell/caller;若产品入口沿用这种方式,token 可能进入终端滚屏、命令替换、
进程内长期变量或临时 kubeconfig,而且无法在真正写入 Secret 前证明 issuer 与 delivery
身份均没有意外扩权。
同时,TokenRequest issuer 和 delivery ServiceAccount 是两个不同 authority:前者只能为
一个预定 ServiceAccount 签发 token,后者才能访问 stage 与精确 target。把两者合并到
admin kubeconfig、常驻 control 或 Worker 会扩大凭据泄漏后的 blast radius,也让低配设备
承担不必要的 Kubernetes SDK、连接或后台生命周期。
## 决策
### 1. Token issuer 是外部、短生命周期管理身份
生产 manifest 将外部认证主体组
`qinglong:worker-credential-operators` 绑定到 staging namespace 中唯一 Role。该 Role 只允许
对 exact `ql3-worker-credential-admin``serviceaccounts/token` 执行 `create`;不得读取
Secret、Deployment、Pod、Namespace,也不得为其他 ServiceAccount 签发 token。
issuer kubeconfig 由部署者在受保护的管理工作站或受控管理作业中提供。它不是 Worker/control
Pod 的 Secret 或 volume,也不绑定 delivery ServiceAccount、普通 control 身份或广域管理员组。
### 2. 每次 delivery 创建一个有界 TokenRequest session
`cluster-admin` 既有 package 增加显式
`worker-credential-kubernetes-token-request` subpath。每次 `withDelivery()` 必须按以下顺序执行:
1. 先以 issuer 身份完成 1 条应允许与 8 条应拒绝的 SelfSubjectAccessReview;任何意外允许、
意外拒绝或 API 不可用均在 TokenRequest 前失败关闭;
2. 只向 staging namespace 的 exact ServiceAccount 请求 600 秒 token
3. 对 API 响应施加 16 KiB 上限、canonical JWT 结构、非 `none` 算法、exact ServiceAccount
subject、`iat/exp` 安全整数、30600 秒 lifetime、API expiration 与 JWT expiration 一致性;
4. 只在内存中构造 restricted KubeConfig,立即清空 TokenRequest response 中的 token 引用;
5. 以 delivery 身份完成 8 条应允许与 20 条应拒绝的 SelfSubjectAccessReview,确认与
ADR-0240 的 stage/target/Deployment 权限矩阵精确一致后才调用业务 operation;
6. callback 只得到既有 delivery adapter 和低敏计数证据,不返回 token、KubeConfig 或原始
Kubernetes clients;成功、业务失败、校验失败都在 `finally` 清空 token 并使 restricted
KubeConfig 失效。销毁失败同样失败关闭,但只暴露稳定、无敏感内容的领域错误。
该 session 不把 JWT payload 当成独立认证来源;Kubernetes API 仍是签发与鉴权事实源。本地
结构检查只用于拒绝错误主体、异常寿命和畸形响应,不能替代 API server 的签名验证。
### 3. 保持可选依赖与 Profile 边界
实现不新增 workspace package、生产依赖、timer、watcher、listener、sidecar 或数据库对象。
Kubernetes client 由调用方显式注入,只在短生命周期 Cluster Admin 路径加载;Edge、
Standalone、Worker 和未启用 Cluster 路径不导入该 SDK、不创建连接,也没有空闲成本。
### 4. TokenRequest session 不等于审批产品入口
本 ADR 只关闭“受批执行之后如何安全签发并消费短期 delivery capability”。正式产品命令仍须
先使用既有强 User principal、Project/Policy、separation-of-duty Approved Action、持久审计与
exact replay,再在执行阶段进入 session。测试中的 impersonated User 只是 RBAC fixture,不能
替代 OIDC/client certificate 身份认证、双人审批或 durable execution receipt。
## 不采用方案
### 继续调用 `kubectl create token`
拒绝。命令的正常输出就是 bearer token,调用者必须自行管理 stdout、变量、临时文件和销毁,
也无法把 issuer/delivery 两层权限校验与 adapter 生命周期封装成一个 fail-closed 边界。
### 将 TokenRequest authority 交给 delivery ServiceAccount
拒绝。这会允许受限 delivery token 自签新 token,并延长或复制 compromise authority。
issuer 必须是外部管理身份,delivery ServiceAccount 明确通过 deny matrix 证明不能自签。
### 复用 cluster-admin kubeconfig 完成 delivery
拒绝。广域 kubeconfig 绕过 exact-name RBAC,任何 adapter 缺陷都会升级为集群级 mutation。
### 常驻 controller 自动轮换
拒绝。它会把 issuer credential、Kubernetes SDK、连接、timer/watch 与 leader/retry 状态带入
常驻面,既扩大攻击面,也把路由设备无需承担的成本引入共同架构。
## 影响
- credential-admin deployment 资产新增一个 exact TokenRequest issuer Role/RoleBinding
- `cluster-admin` 新增一个显式 subpath 和内存 session,不新增 package 或第三方依赖;
- live Gate 不再读取、打印或返回 delivery token,也不再手工构造 restricted kubeconfig
- session 是一次性 callback scope,调用方不能缓存 adapter 跨 operation 使用;
- issuer/delivery 权限漂移会在 Secret/Deployment mutation 前被发现并失败关闭;
- durable approval 产品命令仍是后续独立切片,不因本 ADR 自动完成。
## 验证
1. GitNexus upstream impactsession 为 LOW,仅 1 个直接上游 KubeConfig wrapper0 条已识别
production execution flow
2. strict TypeScript 与定向 6/6 通过,覆盖成功销毁、issuer/delivery 意外扩权、错误 subject、
畸形/超长/expiry 不一致响应、TokenRequest 错误和销毁错误的无敏感映射;
3. deployment audit 与 `kubectl kustomize` 验证 exact
`serviceaccounts/token` + `resourceNames=[ql3-worker-credential-admin]`production subject
是外部 Group 而非 delivery ServiceAccount
4. 固定 `rancher/k3s:v1.34.3-k3s1` 的真实 arm64 Gate 创建 2 个独立 600 秒 session,完成
issuer 1 allow/8 deny、delivery 8 allow/20 deny、credential A→B、Recreate 顺序、PVC
强制 Pod 丢失恢复与 identity A→Btoken 未从 session 返回,每次 restricted client 均销毁,
全部 gate `passed=true`
5. PostgreSQL 18.4 arm64 physical HA 随后重跑通过:`remote_apply`、timeline 1→2、旧主
fencing、未确认分区提交排除、`pg_rewind` 只读同步重入、两个 fresh control replica 及全部
domain COMMIT-response-loss gate 均为 true
6. 成功/失败后的 `ql3-worker-rollout-live-*``ql3-ha-*` Docker 容器均无残留。
## 仍未完成
- 强 User 登录、双人批准、durable execution receipt 与该 session 的正式产品命令组合;
- production OIDC/client certificate issuer group 的真实外部 IdP ceremony、撤销与审计;
- 多节点 Kubernetes API/CSI、API partition、TokenRequest latency/expiry race 与控制面升级矩阵;
- production Worker image 的真实 360 秒 Session drain,以及固定 x64/arm64 低配设备资源证据。