78 lines
4.3 KiB
Python
78 lines
4.3 KiB
Python
"""跨机器的真实链路验证:Windows 上的 Probe(NativeAOT exe)→ WSL2 里的 Agent 和 Backend(真实的虚拟网络、不同的单调时钟原点)。
|
||
|
||
前提:WSL 里有 Debian(root)、tc(netem 注入丢包/延迟/黑洞用);已经用 scripts/publish.sh 发布了 linux-x64 的 agent、backend、fleet-enroll,
|
||
并且 Windows 上发布了 probe(dotnet publish backend/probe/src/Monitor.Probe -c Release -r win-x64 -p:PublishAot=true -o backend/artifacts/aot-probe)。
|
||
把 linux-x64 的产物复制到 WSL 的 /root/mon/,在 WSL 里用 setsid -f nohup 启动 monitor-backend(监听 0.0.0.0:29181),再运行本脚本。
|
||
故障注入见 docs/deployment.md 第 3 节。
|
||
"""
|
||
import json, os, subprocess, sys, time, urllib.request, urllib.error
|
||
|
||
# 要连的是本机的虚拟网络(WSL),不能走环境变量里的 HTTP(S)_PROXY
|
||
OPENER = urllib.request.build_opener(urllib.request.ProxyHandler({}))
|
||
|
||
ROOT = r"C:\Users\JustMe\Desktop\monitor-proj"
|
||
PROBE_EXE = os.path.join(ROOT, "backend", "artifacts", "aot-probe", "monitor-probe.exe")
|
||
WORK = r"C:\Users\JustMe\AppData\Local\Temp\realnet"
|
||
PORT = 29181
|
||
|
||
|
||
def wsl(cmd, check=True):
|
||
r = subprocess.run(["wsl", "-d", "Debian", "-u", "root", "-e", "bash", "-c", cmd], capture_output=True, text=True)
|
||
if check and r.returncode != 0:
|
||
print("WSL FAILED:", cmd, r.stdout, r.stderr)
|
||
raise SystemExit(1)
|
||
return r.stdout.strip()
|
||
|
||
|
||
WSLIP = wsl("ip -4 addr show eth0 | grep -oP '(?<=inet )[0-9.]+'")
|
||
BASE = f"http://{WSLIP}:{PORT}"
|
||
|
||
|
||
def req(method, path, body=None, headers=None, ctype="application/json"):
|
||
data = None if body is None else json.dumps(body).encode()
|
||
h = {"Content-Type": ctype}
|
||
h.update(headers or {})
|
||
r = urllib.request.Request(BASE + path, data=data, method=method, headers=h)
|
||
try:
|
||
with OPENER.open(r, timeout=30) as resp:
|
||
text = resp.read().decode()
|
||
return resp, (json.loads(text) if text else None)
|
||
except urllib.error.HTTPError as e:
|
||
print("HTTP", e.code, e.read().decode())
|
||
raise
|
||
|
||
|
||
def main():
|
||
os.makedirs(WORK, exist_ok=True)
|
||
print("wsl ip", WSLIP)
|
||
resp, login = req("POST", "/api/admin/auth/login", {"username": "admin", "password": os.environ.get("MONITOR_ADMIN_PASSWORD", "correct horse battery")})
|
||
cookie = resp.headers["Set-Cookie"].split(";")[0]
|
||
_, tok = req("POST", "/api/admin/api-tokens", {"name": "net", "scope": "admin"}, {"Cookie": cookie, "X-CSRF-Token": login["csrf_token"]})
|
||
auth = {"Authorization": "Bearer " + tok["plaintext"]}
|
||
json.dump({"base": BASE, "token": tok["plaintext"], "wslip": WSLIP}, open(WORK + r"\state.json", "w"))
|
||
_, join = req("POST", "/api/admin/join-tokens", {"auto_approve": True, "max_uses": 1, "expires_in_hours": 1}, auth)
|
||
|
||
wsl("pkill monitor-agent; cd /root/mon && rm -rf id agent.json")
|
||
print(wsl(f"cd /root/mon && ./fleet-enroll --server http://127.0.0.1:{PORT} --join {join['plaintext']} --name wsl-agent --identity-dir /root/mon/id"))
|
||
cfg = {"fleet": {"server": f"http://127.0.0.1:{PORT}", "identity_dir": "/root/mon/id"}, "listen": {"bind": "0.0.0.0"}}
|
||
wsl("cat > /root/mon/agent.json <<'EOF'\n" + json.dumps(cfg) + "\nEOF")
|
||
wsl("cd /root/mon && (setsid nohup ./monitor-agent --config /root/mon/agent.json > agent.log 2>&1 < /dev/null &)")
|
||
time.sleep(3)
|
||
_, agents = req("GET", "/api/admin/agents", None, auth)
|
||
agent = agents["items"][0]
|
||
print("agent", agent["id"], agent["status"], "online", agent.get("online"))
|
||
# the backend only sees 127.0.0.1 as the agent's address: the panel needs the address the probe can reach
|
||
req("PATCH", "/api/admin/agents/" + agent["id"], {"public_host": WSLIP}, auth, "application/merge-patch+json")
|
||
_, ident = req("POST", "/api/admin/probes", {"name": "home"}, auth)
|
||
print("bootstrap", ident["bootstrap"])
|
||
os.makedirs(WORK + r"\probe", exist_ok=True)
|
||
json.dump(ident, open(WORK + r"\probe\probe.json", "w"))
|
||
json.dump({"base": BASE, "token": tok["plaintext"], "wslip": WSLIP, "agent_id": agent["id"]}, open(WORK + r"\state.json", "w"))
|
||
log = open(WORK + r"\probe.log", "w")
|
||
p = subprocess.Popen([PROBE_EXE, "--config", WORK + r"\probe\probe.json"], stdout=log, stderr=subprocess.STDOUT)
|
||
open(WORK + r"\probe.pid", "w").write(str(p.pid))
|
||
print("probe pid", p.pid)
|
||
|
||
|
||
main()
|