#!/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 [参数]") 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("未知操作")