7.4 KiB
ADR-0241:Kubernetes Worker Credential TokenRequest Session
- 状态:Accepted
- 日期:2026-08-01
- 关联 RFC:QL-RFC-0001 D-23、D-58、D-175、D-224、D-225
- 关联 ADR:ADR-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() 必须按以下顺序执行:
- 先以 issuer 身份完成 1 条应允许与 8 条应拒绝的 SelfSubjectAccessReview;任何意外允许、 意外拒绝或 API 不可用均在 TokenRequest 前失败关闭;
- 只向 staging namespace 的 exact ServiceAccount 请求 600 秒 token;
- 对 API 响应施加 16 KiB 上限、canonical JWT 结构、非
none算法、exact ServiceAccount subject、iat/exp安全整数、30–600 秒 lifetime、API expiration 与 JWT expiration 一致性; - 只在内存中构造 restricted KubeConfig,立即清空 TokenRequest response 中的 token 引用;
- 以 delivery 身份完成 8 条应允许与 20 条应拒绝的 SelfSubjectAccessReview,确认与 ADR-0240 的 stage/target/Deployment 权限矩阵精确一致后才调用业务 operation;
- 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 自动完成。
验证
- GitNexus upstream impact:session 为 LOW,仅 1 个直接上游 KubeConfig wrapper,0 条已识别 production execution flow;
- strict TypeScript 与定向 6/6 通过,覆盖成功销毁、issuer/delivery 意外扩权、错误 subject、 畸形/超长/expiry 不一致响应、TokenRequest 错误和销毁错误的无敏感映射;
- deployment audit 与
kubectl kustomize验证 exactserviceaccounts/token+resourceNames=[ql3-worker-credential-admin],production subject 是外部 Group 而非 delivery ServiceAccount; - 固定
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→B;token 未从 session 返回,每次 restricted client 均销毁, 全部 gatepassed=true; - PostgreSQL 18.4 arm64 physical HA 随后重跑通过:
remote_apply、timeline 1→2、旧主 fencing、未确认分区提交排除、pg_rewind只读同步重入、两个 fresh control replica 及全部 domain COMMIT-response-loss gate 均为 true; - 成功/失败后的
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 低配设备资源证据。