123 lines
10 KiB
Markdown
123 lines
10 KiB
Markdown
# Round 5V-7 — 旧客户端路径阻断与受管QA签署
|
||
|
||
日期:2026-10-15(Asia/Shanghai)。输入提交:`65c567152e4f57bd25af03da52cc7078ea264984`。
|
||
分支:`fix/iot-safety-hardening`。本轮只改归档工程的本地QA工具、工具测试、CI验证发现范围及文档。
|
||
没有修改原工程、实验工程、旧进程配置、数据库账号权限、路由、Tailscale或共享服务。
|
||
没有迁移、恢复、纠正sync_time、创建授权、发Mock业务控制命令或真实设备控制。
|
||
登录会正常产生自身认证审计;它不是零数据库写入,但没有授权/命令变更。
|
||
|
||
## 1. 结论与边界
|
||
|
||
| 标识 | 结论 | 实际范围 |
|
||
| --- | --- | --- |
|
||
| SOFTWARE_FUNCTIONAL_QA_PASSED | YES | 保留11项真实Kingbase、86项选定回归、12项工具、Chrome15路由及住宿Mock闭环的历史通过;未重跑完整矩阵 |
|
||
| SOFTWARE_FINAL_SIGNOFF | PASS_MANAGED_QA_SCOPE | 本轮受管隧道、旧端点拒绝守卫、新后端最小读冒烟、数据稳定观察和故障退出通过 |
|
||
| REAL_HARDWARE_VERIFIED | NO | 真实门锁/MQTT/人脸/DMS均未放行,未做现场硬件验收 |
|
||
|
||
此签署是当前受管QA运行/退出工作流的可交付候选,不是生产上线、永久数据库访问控制或硬件签署。
|
||
脱离工具手工重开14321、修改旧进程配置或共享同一账号,仍可能恢复旧访问;这些不在通过范围。
|
||
不得把手工SSH隧道或未绑定租约的应用启动替代本流程。
|
||
|
||
## 2. 旧进程和原访问路径的只读复核
|
||
|
||
- 旧Java PID51901,出生时间`2026-10-13 15:35:08`,cwd=`boot4-iot-fusion-test`;
|
||
实际JAR位于该工程的`RuoYi-Vue-master/ruoyi-admin/target/ruoyi-admin.jar`,不是归档工作树。
|
||
- 从进程环境只输出非秘密字段:DB_HOST=127.0.0.1、DB_PORT=14321、QA_DB_USER=fusion_qa_app。
|
||
实际运行JAR内application-druid.yml固定数据库`railwaysystem_fusion_qa_20261013`,默认Host/Port与环境一致。
|
||
- 另一Java PID53305,出生时间`2026-10-12 12:46:15`,属于另一工程;其JAR数据源模板是localhost:54321/iotlocks,
|
||
不是上述旧端点。本轮两个Java进程均未停止或修改。
|
||
- 开始时14321没有监听者,不存在可归属/可关闭的现有该端口隧道。其他既有SSH进程未发现14321转发参数,未操作它们。
|
||
- 旧任务`initialDelay=30000ms / fixedDelay=60000ms`,允许补偿时会按失败/待发状态扫描;失败分支可写sync_time。
|
||
实际调度间隔还包含数据库连接等待/失败处理,不能把60秒当作每分钟一定完成一次。
|
||
- 原归档`qa.py`不自动建14321隧道,但允许任意同名QA URL,且只检查新应用监听端口,未防止旧客户端借用新转发。
|
||
已证明的两条旧记录来源仍见[Round 5V-6](ROUND5V6_FINAL_SIGNOFF.md),不是正常Mock回执。
|
||
|
||
## 3. 实际采用的最小隔离
|
||
|
||
新增`scripts/qa/qa_isolation.py`,正常前台运行,认证只走既有合法SSH入口、Agent/密钥或交互提示。
|
||
它不接受或保存SSH密码,不改SSH/Tailscale/系统代理配置,不依赖停止旧进程或修改账号。
|
||
|
||
| 客户端/审计 | 本轮端点 | 隔离行为 |
|
||
| --- | --- | --- |
|
||
| 旧PID51901及其他14321客户端 | 127.0.0.1:14321 | 本任务守卫独占,连接立即关闭;没有数据库协议响应、没有任何上游 |
|
||
| 新归档后端PID35238 | 127.0.0.1:14327 | 仅归本任务SSH PID34187所有的loopback转发,经wzbmatebook到目标127.0.0.1:4321 |
|
||
| 独立只读指纹核验 | 经诊断SSH执行容器本地ksql | 只读事务/ROLLBACK,不通过14321,不恢复备份、不执行DDL |
|
||
|
||
守卫owner PID34164;同一租约绑定Redis35236、后端35238、前端35269。
|
||
其PID/出生时间/cwd/命令、监听IP与归属、固定QA库、心跳及新端点Java客户端依赖都被核验。
|
||
未发现其他Java客户端依赖14327;实际TCP连接只见新后端与自建SSH,旧PID51901未连接它。
|
||
14321已有未知监听者、新端点冲突、PID重用、心跳过期或所有权不匹配均安全拒绝,不清理未知资源。
|
||
|
||
不是只换端口:旧14321被拒绝守卫占住,实际bind测试得到占用错误,实际连接不返回数据库响应;
|
||
新启动器同时拒绝14321 URL、没有活动租约的start以及与租约不匹配的数据源。
|
||
前端也必须绑定同租约后端及对应端口,不能用旧8096后端冒充本版本。
|
||
看门狗持续检查;临时隧道失效时仅清理同租约应用,先关自己的SSH,最后释放拒绝守卫。
|
||
退出后的账本保留审计,不自动重用旧账本或信号未知PID。
|
||
|
||
### SSH继承配置的额外发现和修复
|
||
|
||
现有SSH目标和跳板配置均含与QA无关的RemoteForward17897。
|
||
首次受管试运行因该继承转发冲突失败,未启动应用;对应STOPPED账本保留。
|
||
本轮诊断会话也意外继承同一转发;单独cancel不足,因为后续mux命令客户端可能再次继承并申请转发。
|
||
已按确切归属退出本轮诊断ControlMaster,再以ClearAllForwardings和禁用ControlMaster的单次只读SSH复核:17897监听数为0。
|
||
没有修改持久SSH配置或取消其他会话的转发。
|
||
最终工具用独立目标配置和显式ProxyCommand复用既有跳板,跳板清除继承转发/本地命令;
|
||
目标只设置批准的HostName/User/22端口及唯一-L,StrictHostKeyChecking=yes,不复用ControlMaster,不发布远程端口。
|
||
此后正式运行没有继承无关转发。不要将失败的首次尝试隐去或算作成功启动。
|
||
|
||
## 4. 实际验证及数据证据
|
||
|
||
证据根:受保护且Git忽略的`.qa-runtime/round5v7/`;所有业务行仅在数据库内计算排序完整行指纹,未导出人员资料。
|
||
浏览器截图位于`output/playwright/round5v7-*-headers.png`,数据行和头像遮罩。
|
||
|
||
- 新工具的29项定向本机测试通过(原12项工具测试及17项隔离测试),不连接真实服务或数据库。
|
||
覆盖无租约拒绝、禁止旧URL、PID/监听者/心跳/来源端点拒绝、非本租约进程不被停止、真实本机拒绝socket等。
|
||
其中28项在启动前通过,补充前端错误端口防护后最终29项通过;不假称重跑86项后端测试。
|
||
- 正式受管租约创建于2026-10-15 01:52:49;应用在01:53:12启动。
|
||
实测Java21.0.2 / Boot4.1.0,fusion_qa_app,数据源仅目标QA库,独立Redis16389,前端18088/后端18096均loopback。
|
||
强制CLI保持MQTT enabled=false/mock=true、real-device-write-enabled=false、空白名单、自动补偿关闭、
|
||
Face HTTP/OpenAPI/QA危险入口/DMS/Quartz关闭;实际日志出现MOCK-MQTT,未见08001/SQL错误。
|
||
- 实际Chrome155最小冒烟:管理员登录/getInfo/getRouters成功;Student查询与Auth查询均HTTP200/业务200,JS错误0。
|
||
Auth页实际组件和45条总数正确,不是登录页/404;没有点击授权、撤权、入住或回执操作。
|
||
- 隔离前、运行中、退出前后共四次真实Kingbase只读采样。前后窗口1432秒(约23分52秒),
|
||
是名义60秒补偿周期的多倍;两表完整数据指纹均不变:
|
||
lock_auth45条:`af7e6a797bebef91a7d5570697265b5e`;lock_command83条:`271d15e2d0721015d3b020433c549c7c`。
|
||
包含所有字段,而不只是排除sync_time后的指纹。两表REAL行数均0。
|
||
- 两条脱敏旧记录sync_time分别保持`2026-10-14 16:51:29`与`16:51:30`,仍LEGACY/QUARANTINED/version0,
|
||
sync_status3、status0,没有纠正性UPDATE;其余原始记录也包含在完整指纹中。
|
||
- 正式守卫累计拒绝507次连接(含一次明确的本机负向验证,不把全部次数硬归给单个PID)。
|
||
旧日志完整追加窗口读取约1.1MB,发现2个补偿失败事件、0个成功updateSyncStatus UPDATE;未复制原日志正文。
|
||
这证明旧任务仍可能运行,但在受管窗口内无法通过旧端点获得QA连接,不是把任务静默禁用。
|
||
|
||
### 自建SSH异常退出演练
|
||
|
||
验证租约与PID身份后,仅向本轮自建SSH PID34187发送SIGTERM。
|
||
看门狗检测到监听者丢失,自动停止同租约前端/后端/Redis,随后关闭自己的资源;
|
||
终态STOPPED、cleanup_ok=true,故障检测按预期非零退出,退出证据保留。
|
||
14321、14327、18096、18088、16389均不再监听,旧两个Java的PID/出生时间不变。
|
||
退出后源QA只剩本次ksql只读会话,无fusion_qa_app残留连接,完整指纹仍一致。
|
||
随后实际`qa.py start`在无租约时拒绝,未连接数据库或再启动进程。
|
||
没有测试SIGKILL、主机断电或恶意绕过,也不把本测试写成这些保证。
|
||
|
||
## 5. 归档状态和剩余风险
|
||
|
||
共享Kingbase/GitLab容器ID、2026-10-06启动时间、restart0/OOM=false均未变;GitLab healthy。
|
||
临时恢复容器仍停止,本轮未启动或修改它。没有共享部署或真实硬件操作。
|
||
|
||
本轮只读远端仍为`feat/boot4-iot-fusion@373921447fa4727c20aed7b28c5d1519fe26fa78`,修复分支远端不存在。
|
||
该融合基线是修复分支祖先;本地保留此前七笔提交,本轮再追加工具/文档提交,不改写历史。
|
||
GitLab使用默认CI文件,项目Hook=0、非项目Hook=0、相关活跃Integration=0。
|
||
CI仍仅显式web+RUN_FUSION_VALIDATION=true可运行,只有验证无部署;新增隔离测试已纳入工具测试发现范围。
|
||
没有Push、MR、Merge或触发Runner;不把静态配置审核写成已执行远程CI。
|
||
|
||
本轮对已有七笔提交和新增暂存范围合计142个blob/路径版本完成扫描,未检出已知本机凭据值、
|
||
私钥正文、Token形态高风险项或新增备份/日志/照片/二进制文件;通用赋值命中已区分环境变量、占位符、
|
||
合成测试及禁用账号哨兵,不将扫描写成对继承历史的绝对无秘密保证。
|
||
原始备份、0600凭据、运行账本/日志/截图未被跟踪,扫描摘要保存在受保护忽略目录。
|
||
继承的测试密钥素材、历史凭据轮换、既有账号过宽授权、Vue2依赖及长期Kingbase许可仍保留风险,未自动处置。
|
||
|
||
在**必须使用受管入口**的前提下,当前软件候选不再因旧端点隔离而挂起;本轮最后仅需用户决定GitLab归档。
|
||
可另行批准后推送`fix/iot-safety-hardening`的精确本地HEAD,不Force Push、不覆盖融合基线,再经MR评审合入。
|
||
这不放行部署/生产/真实硬件;若要永久关闭旧服务、改旧配置、撤销账号权限或允许手工转发,仍须对应批准。
|
||
对恶意同用户进程/管理员主动绕过不提供系统级隔离保证;如运行场景要求该等级,应维持该场景PENDING并另行设计权限隔离。
|