Files
wecom_it_smart_desk/jumpserver-webcli/CHANGELOG.md
T

167 lines
7.8 KiB
Markdown
Raw Normal View History

# JumpServer 自动化演进日志
## 概述
从 2026-06-21 到 2026-06-25JumpServer 自动化经历了 **5 种技术路线、17+ 个主要版本** 的迭代,最终选择了 Playwright Web CLI 方案作为生产方案。
## 时间线
```
2026-06-21 ─ 06-22 │ 06-22 ─ 06-23 │ 06-23 ─ 06-25
SSH 路线探索 │ Web CLI 路线验证 │ 生产化 + 部署实战
│ │
• plink.exe (v8) │ • webcli_probe │ • webcli_v4-v7 迭代
• Paramiko (v1-v7) │ • webcli_login_v1 │ • SFTP 文件上传
• wexpect (v11) │ • webcli_inspect │ • 分块 base64 传输
• API auth 探测 │ • webcli_v2-v3 │ • hotfix 实战部署
│ │ • SSH Key 方案探索
```
## 各路线详细记录
### 路线 1: plink.exe (PuTTY CLI) — 已废弃
| 版本 | 文件 | 发现 |
|------|------|------|
| v8 | `test_plink_v8.py` | plink 可以连接但输出捕获不稳定 |
| - | `test_plink_formats.py` | MFA 提示格式有 3 种变体 |
| - | `test_plink_verbose.py` | 详细日志模式可看到完整交互 |
**废弃原因**:中文编码问题、交互式菜单导航不可靠、plink 不支持 PTY 分配。
### 路线 2: Paramiko (Python SSH) — 已废弃
| 版本 | 文件 | 关键发现 |
|------|------|---------|
| v1-v5 | `test_paramiko_v1.py` ~ `v5.py` | 基本连接可行,但 OTP 流程脆弱 |
| v6-v7 | `test_paramiko_v6.py` ~ `v7.py` | 交互式 shell 模式可绕过部分菜单 |
| v8 | `jumpserver_paramiko_v8.py` | 尝试 channel.recv 非阻塞读取 |
| v9 | `jumpserver_paramiko_v9.py` | 尝试 expect 模式(timeout 可控) |
| v12 | `jumpserver_paramiko_v12.py` | SSH Gateway 方式(JumpServer → 目标) |
| v13 | `jumpserver_paramiko_v13.py` | PTY 分配尝试 |
| v14-v16 | `jumpserver_paramiko_v14.py` ~ `v16.py` | 多线程读写分离 |
**废弃原因**JumpServer 堡垒机菜单变化频繁(每次登录可能不同),Paramiko 的 expect 匹配无法适应。OTP 二次认证流程极其脆弱。
### 路线 3: wexpect (Windows expect) — 已废弃
| 版本 | 文件 | 发现 |
|------|------|------|
| v11 | `jumpserver_wexpect_v11.py` | 可以 spawn plink 进程并交互 |
| v2 | `jumpserver_wexpect_v2.py` | 中文输出匹配不稳定 |
| v3 | `jumpserver_wexpect_v3.py` | timeout 设置和重试逻辑优化 |
**废弃原因**wexpect 在 Windows 上不稳定,中文编码问题难以解决,且与 plink 有相同的基础问题。
### 路线 4: Web CLI (Playwright) — ✅ 当前生产方案
| 版本 | 文件 | 关键里程碑 |
|------|------|-----------|
| probe | `jumpserver_webcli_probe.py` | 成功探测 Luna 终端结构 |
| login | `jumpserver_webcli_login_v1.py` | 实现自动登录(密码+OTP) |
| inspect | `jumpserver_webcli_inspect.py` | 分析 Web 终端的 DOM 结构 |
| v2 | `jumpserver_webcli_v2.py` | 基本命令执行 |
| v3 | `jumpserver_webcli_v3.py` | 增加截图和输出保存 |
| v4 | `jumpserver_webcli_v4.py` | 文件上传探索 |
| v5 | `jumpserver_webcli_v5.py` | SFTP 界面自动化 |
| v6 | `jumpserver_webcli_v6.py` | 超时控制 + 错误重试 |
| **v7** | **`jumpserver_webcli_v7.py`** | **生产版本**:完整部署流程 |
**v7 核心能力**
- 自动登录 JumpServer(用户名 + 密码 + OTP
- 导航到目标服务器(税友集团 → hz-oa-ai-g-dataquery-90-5-110
- 在 Web 终端中执行任意命令
- 截图保存(用于验证)
- 输出日志保存
- SFTP 文件上传(set_input_files 方式)
**关键突破**:发现 `OTP 双回车`问题 — 发送验证码后需按 2 次 Enter 触发验证流程。
### 路线 5: SSH Key 认证 — 开发中
| 文件 | 状态 |
|------|------|
| `generate_ssh_keys.py` | 生成 RSA 密钥对 |
| `jumpserver_auto_v17_key_auth.py` | 尝试用密钥认证连接 |
| `ssh_keys/jumpserver_id_rsa` | 已生成的私钥 |
**目标**:绕过 OTP 流程,实现完全无人值守的自动化。
### 路线 6: JumpServer API Token — 探索中
| 文件 | 发现 |
|------|------|
| `create_connection_token.py` | 可通过 API 创建连接 Token |
| `test_connection_token.py` | Token 可用于 SSH 连接 |
| `probe_koko_token.py` | KokoWeb 终端)的 Token 格式不同 |
| `probe_terminal_api.py` | 终端 API 端点探测 |
### 2026-06-25 (下午): xterm.js 输出捕获分析 + probe_v2
- **创建 `probe_xterm_buffer_v2.py`**5 种方法探测 xterm.js 缓冲区
- 全局 Terminal 实例搜索
- DOM .xterm-rows 遍历
- helper-textarea 读取
- 渲染器类型检测(DOM vs Canvas
- React Fiber 组件树搜索
- **创建 `ANALYSIS.md`**:完整的能力-限制-优化分析
- 现有能力矩阵 + 已验证部署记录
- 输出捕获不可靠问题分析(3 种失败模式)
- v8 结构化捕获设计 + Monkey Patch 兜底方案
- 不适用的 6 种场景
- 短/中/长期优化路线图
- **发现**v7 的 `inner_html()` 输出捕获依赖 DOM 渲染器,Canvas 渲染器下失效
### 下一步
- [ ] 运行 probe_xterm_buffer_v2.py 确认 xterm.js 实例暴露方式
- [ ] 根据探测结果实现 webcli_v8.py(结构化缓冲区读取)
### 2026-06-25 (晚间): v10.16 OTP 等待时间修复
**问题**:用户反馈 `ensure_logged_in()` 中 OTP 提交后 `wait_for_timeout(5000)` 只有 5 秒,JumpServer 服务端 OTP 校验通常需要 8-15 秒,导致过早判定超时并进入 URL 跳转检测,进而误判登录失败。
**修复**
1. **MFA 页面消失轮询**:替代固定 5s 等待,改为 500ms × 40 次轮询(max 20s),检测 `input[name="code"]` 消失
2. **OTP 错误检测**:轮询中检测页面正文是否含 "验证码错误/OTP 错误/已过期/expired/Invalid" 关键字
3. **URL 跳转延长**workbench URL 检测从 15×1s=15s 延长到 60×500ms=30s
4. **超时截图**30s 未跳转时自动截图留存(`v10_post_otp_stuck.png`
5. **代码安全**:截图前确保 `OUTPUT_DIR` 存在
**影响范围**`jumpserver_webcli_v10_persistent.py``ensure_logged_in()` 函数 (lines 209-245)
**副作用**:正常流程下 MFA 页面通常在 3-5s 消失,轮询会在第 6-10 次检查(3-5s)时返回,不影响正常速度。仅在网络慢/服务器高负载时才会触发更长的等待。
## 成功部署记录
### Hotfix #116: 扫码获取 (2026-06-22)
- 使用 webcli v2-v4
- 部署 `auth_qrcode.py`
- 5 个部署诊断迭代(diag_v7 ~ diag7_v7
### Hotfix #120: 扫码自动确认 (2026-06-23)
- 使用 webcli v5 + v7
- 部署 `qrcode_service.py`29KB 源码)
- **首次使用 SFTP 分块上传**8 chunks
- 18 个 webcli 子脚本(part1/2、diag、verify、sub、tail、view
- 从 Part A SFTP 到 Part B 部署到 Part C 验证
### Hotfix #48: Nginx Upstream (2026-06-24)
- 使用 webcli v7
- 修复 nginx upstream 配置
- 包含 HTTPS/SSL 验证
### Hotfix SSO: 单点登录启用 (2026-06-25)
- 使用 webcli v7
- 部署 config.py + 环境变量注入
## 记录在案的错误与解决方案
| 错误 | 根因 | 解决方案 | 记录 |
|------|------|---------|------|
| OTP 验证失败 | 发送验证码后未按2次回车 | `test_double_enter.py` 确认需要 `\r\n` | 代码中固定加 `\n` |
| Web CLI 命令输入截断 | 输入框字符限制 ~20KB | 分2批次输入(16KB + 12.8KB | `upload_chunks_sftp.py` |
| Docker cp 路径错误 | 容器内路径与宿主机不同 | 使用 `docker exec` 确认后操作 | webcli_v5_part2.sh |
| 容器重启后立即 curl 失败 | 服务启动需要时间 | 加 `sleep 8` 等待 | webcli_v5_cmd.sh |
| Luna 终端编码乱码 | .sh 文件非 UTF-8 | 使用 `webcli_v3_cmd.utf8.sh` | webcli_v3 |
| SFTP 文件选择器不弹 | webkitdirectory 属性过滤 | v9.8 修复 set_input_files 跳过验证 | upload_chunks_sftp.py |