mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
101 lines
6.3 KiB
Markdown
101 lines
6.3 KiB
Markdown
# ADR-0244:按管理能力绑定身份断言用途
|
||
|
||
- 状态:Accepted
|
||
- 日期:2026-08-01
|
||
- 关联 RFC:QL-RFC-0001 D-58、D-85、D-175、D-226、D-228
|
||
- 关联 ADR:ADR-0148、ADR-0242、ADR-0243
|
||
- 修正:Worker Credential 管理身份曾复用 Plugin Package 的 JWT `typ` 与 `ql3_purpose`
|
||
|
||
## 背景
|
||
|
||
Plugin Package 管理与 Worker Credential 管理已经拥有不同的 HTTPS 路径、PostgreSQL
|
||
角色、durable quota/identity ledger authority 和 JWT audience。Worker manager 进程却仍通过
|
||
Plugin Package keyset factory 的默认值校验:
|
||
|
||
- `typ=ql3-plugin-package-management+jwt`;
|
||
- `ql3_purpose=plugin-package-management`。
|
||
|
||
不同 audience 已阻止两条 token 直接互换,因此这不是一个已证明可利用的跨能力授权漏洞;但它使
|
||
断言自描述用途与实际 authority 不一致,要求外部 IdP 为 Worker 操作签发带 Plugin 语义的 token,
|
||
也让未来配置或审计错误更难被发现。仅靠 audience 区分两条高风险管理链不是 QingLong 3.0 应保留
|
||
的边界。
|
||
|
||
## 决策
|
||
|
||
1. 管理身份验证器接受一个严格、启动时审查的 assertion profile。profile 只含 `type` 与
|
||
`purpose`,对象必须 exact-shape;`type` 只接受 `ql3-<capability>+jwt`,`purpose` 只接受规范化
|
||
kebab-case,禁止任意 JWT 类型、控制字符、空白或大小写漂移。
|
||
2. Plugin Package profile 保持:
|
||
`ql3-plugin-package-management+jwt` / `plugin-package-management`。省略 profile 时仍使用该值,
|
||
使既有 Plugin caller 的语义不变。
|
||
3. Worker Credential profile 固定为:
|
||
`ql3-worker-credential-management+jwt` / `worker-credential-management`。Worker 进程只通过
|
||
`createClusterWorkerCredentialIdentityKeysetFile` 装配该 profile,调用方不能覆盖它。
|
||
4. 一条管理断言必须同时匹配 issuer、audience、JWT `typ`、`ql3_purpose`、签名、生命周期与
|
||
assurance mapping。三类能力标识中的任一项不一致都返回同一低敏认证失败,不提供探测细节。
|
||
5. keyset generation、digest、撤销集合与 PostgreSQL durable ledger 协议不变。此决策不新增
|
||
package、第三方依赖、migration、数据库角色、listener、Pool、timer、watcher、controller 或
|
||
sidecar;Edge/Standalone 不装配该能力,路由设备的安装闭包与常驻资源保持不变。
|
||
6. Kubernetes Worker management live fixture 必须生成 Worker 专属 `typ/purpose`。外部 IdP ceremony
|
||
在正式接受前还必须证明两名不同强 User 的 Worker-purpose token、申请者自批拒绝、reviewer
|
||
批准与撤销后的失败关闭;仓库内自签 fixture 不冒充该证据。
|
||
|
||
## 被拒绝的替代方案
|
||
|
||
### 只依赖 audience
|
||
|
||
拒绝。audience 是必要条件,但不能让 token 自描述它正在请求哪一种管理 authority;多入口共享
|
||
issuer/keyset 时,显式 `typ` 与 purpose 能把错误配置在认证边界失败关闭。
|
||
|
||
### 继续复用 Plugin purpose,并只在文档中解释
|
||
|
||
拒绝。它要求 IdP 签发语义错误的 token,日志、策略和撤销规则都无法准确表达 Worker 能力;文档
|
||
不能修复运行时 contract。
|
||
|
||
### 为 Worker 身份再建 workspace package 或独立常驻身份服务
|
||
|
||
拒绝。两条链共享相同的有界 keyset、签名、lifetime、assurance 和 durable rotation 协议,差异是
|
||
编译时 profile 与部署 authority。包内显式 factory 已能隔离语义;新 importer/daemon 只会增加
|
||
低配设备的安装、SBOM、内存、连接和运维成本。
|
||
|
||
### 让部署配置任意覆盖 Worker profile
|
||
|
||
拒绝。Worker caller 的用途是产品协议而非部署偏好。允许环境变量覆盖会把 confused-purpose 风险
|
||
移给每个部署者,并可能使副本间产生不一致认证语义。
|
||
|
||
## 影响
|
||
|
||
- 现有 Plugin Package token 与 keyset 不变;
|
||
- Worker IdP/client 必须改为签发 Worker 专属 `typ/purpose`,旧的 Plugin-purpose Worker token 会在
|
||
认证阶段失败;
|
||
- Worker keyset 的 issuer、audience、JWK、assurance mapping 与 rotation 流程不变;
|
||
- 共享实现仍位于既有 `cluster-admin` package 内,不增加 workspace importer;
|
||
- 此变更是有意的 3.0 alpha protocol correction,不提供接受旧 Worker token 的兼容窗口。
|
||
|
||
## 验证
|
||
|
||
1. verifier 单元测试证明 Plugin 与 Worker profile 分离;即使 issuer、key、audience 相同,两种
|
||
token 仍不能互换,并拒绝非规范 profile;
|
||
2. keyset 测试证明 Worker factory 接受 Worker token、拒绝同 audience 的 Plugin-purpose token;
|
||
3. 默认 Worker manager 进程以真实 Ed25519 keyset 和 PostgreSQL ledger 交互桩装配,证明生产 caller
|
||
选择 Worker factory,而不只是测试直接调用 verifier;定向 21/21 通过;
|
||
4. `cluster-admin` 完整测试为 177 pass、0 fail、1 条无真实 Kubernetes API 时的条件 skip;
|
||
5. PostgreSQL 18.4 arm64 physical-HA Docker 门再次通过:Worker quota 与 identity ledger 跨实例、
|
||
重启和 promotion 收敛,`remote_apply`、timeline 1→2、旧主 fence、`pg_rewind` 只读同步重入与
|
||
fresh control replicas 均为 true,最终 `gates.passed=true`;门退出后 `ql3-ha` Docker 资源为 0;
|
||
6. GitNexus 对当前已索引 tracked diff 报告 LOW、0 affected process;QL3 新文件尚未完整进入索引,
|
||
因此该结果不替代上述进程级、全包与真实 HA 证据;
|
||
7. 固定 `v1.34.3+k3s1` arm64 三节点 K3s live gate 已用新 profile 完成两个跨节点 manager
|
||
Pod、TLS 1.3 client、8 admitted/8 limited、identity generation 1→2→3 overlap/revoke、rollback
|
||
surge 失败关闭、数据库故障 availability fence、fresh activation 双副本恢复与一次性 client Job,
|
||
最终 `gates.passed=true`;退出后 `ql3-wcm` Docker 容器、网络、卷和临时镜像均为 0。fixture
|
||
仍使用仓库内确定性强 User 断言,不冒充外部 IdP 证据。
|
||
|
||
## 后续门禁
|
||
|
||
- ADR-0245 已增加外部 OIDC 两用户 ceremony 协议、runner 与离线审计器;仍需在真实外部 IdP 上
|
||
采集报告。requester plan/propose、自批失败、reviewer approve/inspect 均不得让 assertion、原始
|
||
subject/session 标识进入低敏结果或 durable plan;
|
||
- 将 identity 共享实现中历史性的 Plugin 命名作为单独重构评审项;只有能减少错误类型/公共
|
||
surface 且不制造兼容 facade 或新 package 时才执行。
|