78f60c6857
P0 修复: - /api/ready import 错误 (_get_engine + settings.create_redis_client) - 删 agent.otp_secret/otp_enabled 双字段 (migration 026) - 重建 021_rbac migration (IF NOT EXISTS 兼容) P1 新增: - 企微 SSO (auth_wecom_sso.py, useWeChatWorkSSO composable, PortalSelect UA 检测) - RBAC 5 角色 × 4 资源 × 4 操作 × 3 范围 (rbac_service + seed_rbac + require_permission) - audit_log 模型 + migration 027 + 服务 + API - 管理后台 RBAC 权限矩阵 UI (PermissionsMatrix.vue) 质量: - pytest 405 passed / 33 pre-existing failed / 4 xfailed (v0.7.1 引入失败 = 0) - conftest GBK patch 强制 UTF-8 读 .env - .gitignore 排除 *.b64 (含 admin token 凭据) - DEPLOY-v0.7.1.md 7 步 runbook + 4 坑 + 回滚预案
90 lines
3.1 KiB
Python
90 lines
3.1 KiB
Python
"""
|
|
准备分段 base64 payload,让 jumpserver 终端拼装并写入 /tmp/xxx.py
|
|
|
|
策略:
|
|
1. 在本机把 2 个 .py 转 base64
|
|
2. 按 N=400 字符一段切分(终端粘贴安全长度)
|
|
3. 生成一段 shell 脚本,内容是:
|
|
cat > /tmp/auth_qrcode.py.b64 << 'B64_EOF'
|
|
段1
|
|
段2
|
|
...
|
|
B64_EOF
|
|
base64 -d /tmp/auth_qrcode.py.b64 > /tmp/auth_qrcode.py
|
|
(同理 qrcode_service.py)
|
|
4. 把这个脚本写到 webcli_output 目录,用 jumpserver 终端 cat 出来
|
|
"""
|
|
import base64
|
|
import re
|
|
from pathlib import Path
|
|
|
|
UPLOAD_DIR = Path(r"C:\Users\simon\.workbuddy\skills\jumpserver-automation-shareable\scripts\webcli_output")
|
|
|
|
files = [
|
|
(UPLOAD_DIR / "auth_qrcode.py", "auth_qrcode.py"),
|
|
(UPLOAD_DIR / "qrcode_service.py", "qrcode_service.py"),
|
|
]
|
|
|
|
# jumpserver terminal 一次粘贴安全长度: ~500 字符
|
|
# 留余量,按 400 字符切
|
|
CHUNK_SIZE = 400
|
|
|
|
def shell_escape(s):
|
|
"""shell 单引号字符串转义"""
|
|
return s.replace("'", "'\\''")
|
|
|
|
def make_upload_script(src_path: Path, dest_name: str, chunk_size=CHUNK_SIZE) -> str:
|
|
"""生成上传用的 shell 脚本: base64 分段 + 拼装 + 解码"""
|
|
content = src_path.read_bytes()
|
|
b64 = base64.b64encode(content).decode("ascii")
|
|
chunks = [b64[i:i+chunk_size] for i in range(0, len(b64), chunk_size)]
|
|
|
|
lines = []
|
|
# 1. 清空
|
|
lines.append(f"rm -f /tmp/{dest_name}.b64 /tmp/{dest_name}")
|
|
# 2. 写 base64 分段(每段用 echo >> 追加,避免 heredoc 卡住)
|
|
for i, chunk in enumerate(chunks):
|
|
lines.append(f"echo -n '{chunk}' >> /tmp/{dest_name}.b64")
|
|
# 3. base64 -d 还原
|
|
lines.append(f"base64 -d /tmp/{dest_name}.b64 > /tmp/{dest_name}")
|
|
# 4. 验证大小
|
|
lines.append(f"ls -la /tmp/{dest_name} && wc -c /tmp/{dest_name} && head -c 100 /tmp/{dest_name}")
|
|
# 5. 清理 b64
|
|
lines.append(f"rm -f /tmp/{dest_name}.b64")
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
# 生成每个文件的上传脚本
|
|
combined = []
|
|
combined.append("#!/bin/bash")
|
|
combined.append("# Auto-generated upload script (copy each line to jumpserver terminal)")
|
|
combined.append(f"# Generated at: {Path(__file__).name}")
|
|
combined.append("")
|
|
combined.append("set -e")
|
|
combined.append("")
|
|
|
|
for src, name in files:
|
|
if not src.exists():
|
|
print(f"❌ {src} not found")
|
|
continue
|
|
combined.append(f"\n# ===== {name} ({src.stat().st_size} bytes) =====")
|
|
script = make_upload_script(src, name)
|
|
combined.append(script)
|
|
|
|
combined.append("")
|
|
combined.append('echo ""')
|
|
combined.append('echo "=== All files uploaded ==="')
|
|
combined.append("ls -la /tmp/auth_qrcode.py /tmp/qrcode_service.py")
|
|
|
|
output_path = UPLOAD_DIR / "upload_files.sh"
|
|
output_path.write_text("\n".join(combined), encoding="utf-8")
|
|
print(f"✅ Generated: {output_path}")
|
|
print(f" Total lines: {len(combined)}")
|
|
print(f" Total bytes: {output_path.stat().st_size}")
|
|
print()
|
|
print("📋 用法:")
|
|
print(" 1. 在 jumpserver 终端跑: cd /tmp/")
|
|
print(" 2. 把 upload_files.sh 内容逐行粘贴(用 jumpserver 终端 '粘贴'功能)")
|
|
print(" 3. 或者更稳: 复制整个脚本内容到 jumpserver 终端(右键粘贴),回车执行")
|