mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
6.0 KiB
6.0 KiB
ADR-0246:Worker 管理持久审计的独立只读证据
- 状态:Accepted(collector、离线审计器与权限门已实现;真实外部报告待采集)
- 日期:2026-08-01
- 关联 RFC:QL-RFC-0001 D-58、D-226、D-228、D-229、D-230
- 关联 ADR:ADR-0148、ADR-0242、ADR-0244、ADR-0245
背景
ADR-0245 的外部 OIDC ceremony 已证明 requester 自批得到 HTTP 403、不同 reviewer 可完成决定,且 最终 inspect 没有 dispatch/consume。但仅凭 HTTP 响应不能独立证明 PostgreSQL 中的 immutable plan、 approved request 和 security audit 彼此一致,也不能证明 self-decision 没有留下允许审计。
让 ceremony runner 使用 ql3_worker_credential_manager 查询数据库会把现场身份客户端与数据库写
authority 合并。新增常驻 evidence service、数据库连接池或 workspace package 又会把一次性发布证据
变成运行时成本,并把无关依赖带给路由设备。
决策
- 新增 caller-driven
ql3-worker-credential-management-durable-audit-evidence.cjs,它只接受 mode 0600 ceremony report、原始 ceremony definition、libpq service file、service 名和 unused output path。连接凭据不允许通过 DSN、CLI 值或报告传入。 - 数据库连接必须是部署侧临时创建的登录角色。collector 在一个显式
READ ONLY事务内验证:- 非 superuser、非 create database/role、非 replication、非 bypass RLS;
- 不能
MEMBER/SET ROLE到 migration、runtime、admin、package、Worker ingress、Worker manager 或 executor 角色; ql3中只能 SELECTworker_credential_management_plans、approval_requests、security_audit_events三张表;- 对所有
ql3表均没有 INSERT/UPDATE/DELETE/TRUNCATE/REFERENCES/TRIGGER。
- collector 精确关联 ceremony action/project/approval/decision/audit identity:plan digest、preview digest、requester/reviewer subject、approved@v2、reviewer decision、proposal audit 和 reviewer decision audit 必须一致。self-decision event 必须不存在,dispatch/consumption 必须为空。
separation_of_duty的 self-decision 在decideApprovalRequest内、数据库 update/audit insert 前 抛出,因此正确持久事实是两条审计而不是三条:approval.request/approval_required和approval.decide/allowed。HTTP 403 与 self event 缺失共同 构成负证据;禁止伪造一条 denied audit 来凑数。- v1 report 只保留两个输入文件的原始 SHA-256、角色/identifier/subject/authentication ID 的域分离 摘要、plan/preview digest、两条低敏 audit 事实和全真 gate。禁止原始 User、Worker、Project、 approval、authentication ID、DSN、password、token、JWT、Secret 或 private key。
- 独立 audit CLI exact-validate 报告并扫描敏感材料。报告以 mode 0600、no-replace 写入;collector 完成后应撤销并删除临时证据角色。
- 此能力不新增 migration、内建数据库角色、workspace package、第三方依赖、镜像、listener、 controller、timer、watcher、Pool 或常驻连接。Edge/Standalone/Worker artifact 不导入这些脚本。
失败与恢复
- 输入权限、角色权限、PostgreSQL 18.4+ 且仍属于受审 18.x major、计划、审批、审计基数或任一 digest 不匹配时不写报告;
psql仅通过PGSERVICEFILE和固定 service name 连接,SQL 从 stdin 提交,业务 identifier 不进入 process argv;事务、statement、lock 与 idle-in-transaction 均有界;- collector 失败不会回滚或修改 ceremony 已创建的事实。operator 必须只读检查原因,禁止用 manager 角色替代 evidence role 绕过门禁;
- 输出不可覆盖。重新采集必须使用新路径,并保留旧失败证据的外部变更记录。
被拒绝的替代方案
复用 Worker manager 角色查询
拒绝。该角色拥有 plan/audit insert 和 approval update,无法证明证据采集本身无 mutation authority。
在 schema migration 中新增常驻 evidence role
拒绝。证据采集不是运行时能力;把一次性登录 credential 变成所有部署的长期角色会扩大 credential inventory 和攻击面。部署侧短期角色可在收集后完整撤销。
要求三条 durable audit
拒绝。self-decision 在领域职责分离检查处失败,事务在 insert 前回滚。第三条记录既不是当前 contract, 也会把 HTTP 负路径误描述为成功 mutation。
把数据库原始行写进报告
拒绝。原始 subject、authentication/request/audit ID 对离线 gate 非必要。域分离摘要可关联同一现场, 同时降低人员身份与基础设施标识泄漏。
验证
- collector/audit 7/7:只读 happy path、PostgreSQL version floor/major、写权限、特权继承、额外表读取、 self audit、dispatch、错误 reviewer、审计缺失、ceremony/report 错配、widened/false/sensitive report、path-only CLI 与 SQL no-mutation;
- 独立 PostgreSQL 18.4 Docker smoke 已用真实临时 login 执行 production SQL,返回精确三表 SELECT、 零 writable table、零 privileged membership、两条 audit 与 self event=0;临时容器/卷零残留;
- ADR-0245 ceremony 回归 7/7;输出均为 mode 0600,离线 audit 子进程
compatible=true; - PostgreSQL 18.4 arm64 physical HA 已重新通过:
remote_apply、timeline 1→2、旧主 fence、pg_rewindrejoin、双 fresh control replica 和最终gates.passed=true;Docker 容器/卷零残留; - 未新增 package、依赖、migration 或运行时资源。
尚未完成
- 在生产等价外部 OIDC/manager/PostgreSQL 上顺序采集 ADR-0245 ceremony report 和本 ADR durable report,并由两个离线 audit CLI 通过;
- 外部 client certificate 的运行时/客户端/Kubernetes 协议已由 ADR-0247 补齐;生产 PKI/ingress、 certificate 或 IdP/assertion 撤销后的新请求拒绝以及证据保留/签名策略仍是更高层发布门,不能由本报告推导。