7.8 KiB
7.8 KiB
JumpServer 自动化演进日志
概述
从 2026-06-21 到 2026-06-25,JumpServer 自动化经历了 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 |
Koko(Web 终端)的 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 跳转检测,进而误判登录失败。
修复:
- MFA 页面消失轮询:替代固定 5s 等待,改为 500ms × 40 次轮询(max 20s),检测
input[name="code"]消失 - OTP 错误检测:轮询中检测页面正文是否含 "验证码错误/OTP 错误/已过期/expired/Invalid" 关键字
- URL 跳转延长:workbench URL 检测从 15×1s=15s 延长到 60×500ms=30s
- 超时截图:30s 未跳转时自动截图留存(
v10_post_otp_stuck.png) - 代码安全:截图前确保
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 |