155 lines
5.3 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""
密钥猎手 · Key Hunter · ICE-GL-ZY-AGT-KEY-001
铸渊叫一声猎手去找密钥
不需要铸渊知道密钥在哪里猎手知道
用法:
python3 hunt.py search NOTION_TOKEN # 搜索指定密钥
python3 hunt.py list BS-SG-001 # 列出服务器上的密钥
python3 hunt.py scan-all # 扫描所有服务器
"""
import json
import os
import sys
import urllib.request
import base64
# Gatekeeper密钥映射从brain/gatekeeper-deployment.json加载
def load_gatekeepers():
"""加载所有Gatekeeper连接信息"""
repo_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
gk_path = os.path.join(repo_root, "brain", "gatekeeper-deployment.json")
if os.path.exists(gk_path):
with open(gk_path) as f:
data = json.load(f)
return {s["code"]: s for s in data.get("servers", [])}
return {}
def gatekeeper_exec(server_code, command, timeout=15):
"""通过Gatekeeper在远程服务器上执行命令"""
servers = load_gatekeepers()
if server_code not in servers:
return {"error": f"未知服务器: {server_code}"}
srv = servers[server_code]
url = f"http://{srv['ip']}:{srv['port']}/exec"
headers = {
"Authorization": f"Bearer {srv['key']}",
"Content-Type": "application/json"
}
data = json.dumps({"cmd": command}).encode()
try:
req = urllib.request.Request(url, data=data, headers=headers)
with urllib.request.urlopen(req, timeout=timeout) as resp:
return json.loads(resp.read())
except Exception as e:
return {"error": str(e)}
def search_key(server_code, key_name):
"""在指定服务器上搜索密钥"""
# 搜索常见位置
search_cmd = f"""
for path in /opt/zhuyuan/guanghulab/.env /opt/juzi/*/.env /etc/environment ~/.gk/secret; do
if [ -f "$path" ]; then
result=$(grep -E "^{key_name}=" "$path" 2>/dev/null | head -1)
if [ -n "$result" ]; then
echo "FOUND:$path:$result"
fi
fi
done
# 也搜索PM2环境变量
pm2 env 0 2>/dev/null | grep "{key_name}=" | head -1 | sed 's/^/FOUND:pm2:/'
"""
result = gatekeeper_exec(server_code, search_cmd)
if result.get("ok") and result.get("stdout"):
for line in result["stdout"].strip().split("\n"):
if line.startswith("FOUND:"):
parts = line.split(":", 2)
return {
"found": True,
"key_name": key_name,
"server": server_code,
"location": parts[1] if len(parts) > 1 else "unknown",
"value": parts[2].split("=", 1)[1].strip() if len(parts) > 2 and "=" in parts[2] else parts[2] if len(parts) > 2 else "unknown"
}
return {"found": False, "key_name": key_name, "server": server_code}
def search_all_servers(key_name, priority_domains=None):
"""在所有服务器上搜索密钥,优先搜索指定域"""
servers = load_gatekeepers()
if not priority_domains:
priority_domains = ["ice-core"]
results = []
# 优先搜索ice-core域
for code, srv in servers.items():
if srv.get("domain") in priority_domains:
r = search_key(code, key_name)
results.append(r)
if r.get("found"):
return r # 找到了就返回
# 搜索其他域
for code, srv in servers.items():
if srv.get("domain") not in priority_domains:
r = search_key(code, key_name)
results.append(r)
if r.get("found"):
return r
return {"found": False, "key_name": key_name, "searched": len(results), "results": results}
def list_server_keys(server_code):
"""列出服务器上的所有密钥名称"""
result = gatekeeper_exec(server_code, """
for path in /opt/zhuyuan/guanghulab/.env /opt/juzi/*/.env 2>/dev/null; do
if [ -f "$path" ]; then
echo "=== $path ==="
grep -E '^[A-Z_]+=' "$path" | cut -d'=' -f1
fi
done
""")
if result.get("ok"):
return {"server": server_code, "output": result.get("stdout", "")}
return {"server": server_code, "error": result.get("error", "unknown")}
def scan_all():
"""扫描所有服务器状态"""
servers = load_gatekeepers()
results = {}
for code in servers:
result = gatekeeper_exec(code, "echo ONLINE && hostname")
results[code] = {
"online": result.get("ok", False),
"hostname": result.get("stdout", "").strip() if result.get("ok") else "OFFLINE"
}
return results
if __name__ == "__main__":
if len(sys.argv) < 2:
print("用法: hunt.py <search|list|scan-all> [参数]")
sys.exit(1)
action = sys.argv[1]
if action == "search" and len(sys.argv) > 2:
key_name = sys.argv[2]
result = search_all_servers(key_name)
print(json.dumps(result, ensure_ascii=False, indent=2))
elif action == "list" and len(sys.argv) > 2:
result = list_server_keys(sys.argv[2])
print(json.dumps(result, ensure_ascii=False, indent=2))
elif action == "scan-all":
result = scan_all()
print(json.dumps(result, ensure_ascii=False, indent=2))
else:
print("未知操作")