117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""
|
|||
|
|
门桥接 · Gate Bridge · ICE-GL-ZY-AGT-GATE-005
|
|||
|
|
|
|||
|
|
铸渊要连接服务器?桥接提供所有Gatekeeper的凭据和通道。
|
|||
|
|
不需要铸渊记住12台服务器的IP和密钥——桥接知道。
|
|||
|
|
|
|||
|
|
用法:
|
|||
|
|
python3 bridge.py list # 列出所有服务器
|
|||
|
|
python3 bridge.py connect BS-SG-001 # 获取连接信息
|
|||
|
|
python3 bridge.py exec BS-SG-001 "ls" # 通过Gatekeeper执行命令
|
|||
|
|
python3 bridge.py scan # 扫描所有服务器在线状态
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import json
|
|||
|
|
import os
|
|||
|
|
import sys
|
|||
|
|
import urllib.request
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
REPO_ROOT = Path(__file__).resolve().parent.parent.parent
|
|||
|
|
|
|||
|
|
def load_gatekeepers():
|
|||
|
|
"""加载所有Gatekeeper"""
|
|||
|
|
gk_path = REPO_ROOT / "brain" / "gatekeeper-deployment.json"
|
|||
|
|
if gk_path.exists():
|
|||
|
|
with open(gk_path) as f:
|
|||
|
|
data = json.load(f)
|
|||
|
|
return data
|
|||
|
|
return {"servers": []}
|
|||
|
|
|
|||
|
|
def list_servers():
|
|||
|
|
"""列出所有服务器(不暴露密钥)"""
|
|||
|
|
data = load_gatekeepers()
|
|||
|
|
servers = []
|
|||
|
|
for s in data.get("servers", []):
|
|||
|
|
servers.append({
|
|||
|
|
"code": s["code"],
|
|||
|
|
"name": s.get("name", ""),
|
|||
|
|
"ip": s["ip"],
|
|||
|
|
"port": s["port"],
|
|||
|
|
"domain": s.get("domain", ""),
|
|||
|
|
"spec": s.get("spec", {}),
|
|||
|
|
})
|
|||
|
|
return {
|
|||
|
|
"total": len(servers),
|
|||
|
|
"domains": list(set(s.get("domain", "") for s in data.get("servers", []))),
|
|||
|
|
"servers": servers
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def get_connection(server_code):
|
|||
|
|
"""获取指定服务器的完整连接信息(含密钥)"""
|
|||
|
|
data = load_gatekeepers()
|
|||
|
|
for s in data.get("servers", []):
|
|||
|
|
if s["code"] == server_code:
|
|||
|
|
return {
|
|||
|
|
"code": s["code"],
|
|||
|
|
"name": s.get("name"),
|
|||
|
|
"gatekeeper_url": f"http://{s['ip']}:{s['port']}/exec",
|
|||
|
|
"auth_header": f"Bearer {s['key']}",
|
|||
|
|
"curl_example": f'curl -X POST http://{s["ip"]}:{s["port"]}/exec -H "Authorization: Bearer {s["key"]}" -H "Content-Type: application/json" -d \'{{"cmd":"echo hello"}}\''
|
|||
|
|
}
|
|||
|
|
return {"error": f"未找到服务器: {server_code}"}
|
|||
|
|
|
|||
|
|
def exec_command(server_code, command):
|
|||
|
|
"""通过Gatekeeper在远程服务器上执行命令"""
|
|||
|
|
conn = get_connection(server_code)
|
|||
|
|
if "error" in conn:
|
|||
|
|
return conn
|
|||
|
|
|
|||
|
|
data = json.dumps({"cmd": command}).encode()
|
|||
|
|
req = urllib.request.Request(
|
|||
|
|
conn["gatekeeper_url"],
|
|||
|
|
data=data,
|
|||
|
|
headers={
|
|||
|
|
"Authorization": conn["auth_header"],
|
|||
|
|
"Content-Type": "application/json"
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
try:
|
|||
|
|
with urllib.request.urlopen(req, timeout=15) as resp:
|
|||
|
|
return json.loads(resp.read())
|
|||
|
|
except Exception as e:
|
|||
|
|
return {"error": str(e), "server": server_code}
|
|||
|
|
|
|||
|
|
def scan_all():
|
|||
|
|
"""扫描所有服务器在线状态"""
|
|||
|
|
data = load_gatekeepers()
|
|||
|
|
results = {}
|
|||
|
|
for s in data.get("servers", []):
|
|||
|
|
try:
|
|||
|
|
r = exec_command(s["code"], "echo ONLINE")
|
|||
|
|
results[s["code"]] = {
|
|||
|
|
"online": r.get("ok", False),
|
|||
|
|
"name": s.get("name", ""),
|
|||
|
|
"domain": s.get("domain", ""),
|
|||
|
|
}
|
|||
|
|
except:
|
|||
|
|
results[s["code"]] = {"online": False, "name": s.get("name", "")}
|
|||
|
|
return results
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
if len(sys.argv) < 2:
|
|||
|
|
print("用法: bridge.py <list|connect|exec|scan> [参数]")
|
|||
|
|
sys.exit(1)
|
|||
|
|
|
|||
|
|
action = sys.argv[1]
|
|||
|
|
|
|||
|
|
if action == "list":
|
|||
|
|
print(json.dumps(list_servers(), ensure_ascii=False, indent=2))
|
|||
|
|
elif action == "connect" and len(sys.argv) > 2:
|
|||
|
|
print(json.dumps(get_connection(sys.argv[2]), ensure_ascii=False, indent=2))
|
|||
|
|
elif action == "exec" and len(sys.argv) > 3:
|
|||
|
|
print(json.dumps(exec_command(sys.argv[2], sys.argv[3]), ensure_ascii=False, indent=2))
|
|||
|
|
elif action == "scan":
|
|||
|
|
print(json.dumps(scan_all(), ensure_ascii=False, indent=2))
|