Files
SnarfCode/scripts/audit_zabbix_hosts.py

80 lines
3.4 KiB
Python

import json
import ssl
import urllib.request
ZABBIX_URL = "http://140.44.4.60:8888/api_jsonrpc.php"
ZABBIX_USER = "Admin"
ZABBIX_PASS = "zabbix"
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
def zbx_call(method, params, auth=None):
payload = {"jsonrpc": "2.0", "method": method, "params": params, "id": 1}
headers = {"Content-Type": "application/json-rpc"}
if auth:
headers["Authorization"] = f"Bearer {auth}"
req = urllib.request.Request(ZABBIX_URL, data=json.dumps(payload).encode("utf-8"), headers=headers, method="POST")
with urllib.request.urlopen(req, timeout=10, context=ctx) as r:
resp = json.loads(r.read().decode("utf-8"))
if "error" in resp:
raise RuntimeError(f"Zabbix error in {method}: {resp['error']}")
return resp["result"]
# 1. Login
auth_token = zbx_call("user.login", {"username": ZABBIX_USER, "password": ZABBIX_PASS})
print("Zabbix Auth OK!")
# 2. Get all hosts
hosts = zbx_call("host.get", {
"output": ["hostid", "host", "name", "status"],
"selectInterfaces": ["interfaceid", "ip", "port", "type", "main"],
"selectParentTemplates": ["templateid", "name"]
}, auth_token)
print(f"\nTotal Registered Hosts in Zabbix: {len(hosts)}")
registered_ips = {}
for h in sorted(hosts, key=lambda x: x["host"]):
ips = [i["ip"] for i in h.get("interfaces", []) if i.get("ip")]
ip_str = ", ".join(ips) if ips else "N/A"
status_str = "MONITORED" if h["status"] == "0" else "DISABLED"
templates = [t["name"] for t in h.get("parentTemplates", [])]
tpl_str = ", ".join(templates) if templates else "None"
print(f"[{status_str}] {h['host']} ({h['name']}) -> {ip_str} | Templates: {tpl_str}")
for ip in ips:
registered_ips[ip] = h["host"]
# Compare with our 28 target hosts
target_hosts = {
# Aerodrome (10)
"140.44.4.11": "sninfr2lnxctl01", "140.44.4.12": "sninfr2lnxctl02", "140.44.4.13": "sninfr2lnxctl03",
"140.44.4.21": "sninfr2lnxwrk01", "140.44.4.22": "sninfr2lnxwrk02", "140.44.4.23": "sninfr2lnxwrk03",
"140.44.4.24": "sninfr2lnxwrk04", "140.44.4.25": "sninfr2lnxwrk05", "140.44.4.26": "sninfr2lnxwrk06",
"140.44.4.27": "sninfr2lnxwrk07",
# Spaceport (10)
"140.44.4.41": "sninfr0lnxctl01", "140.44.4.42": "sninfr0lnxctl02", "140.44.4.43": "sninfr0lnxctl03", "140.44.4.44": "sninfr0lnxctl04",
"140.44.4.51": "sninfr0lnxwrk01", "140.44.4.52": "sninfr0lnxwrk02", "140.44.4.53": "sninfr0lnxwrk03",
"140.44.4.54": "sninfr0lnxwrk04", "140.44.4.55": "sninfr0lnxwrk05", "140.44.4.56": "sninfr0lnxwrk06",
# Shipyard (5)
"140.44.4.71": "snshpd4lnxswm01", "140.44.4.72": "snshpd4lnxswm02", "140.44.4.73": "snshpd4lnxswm03",
"140.44.4.74": "snshpd4lnxswm04", "140.44.4.75": "snshpd4lnxswm05",
# AI & NUT Master (3)
"140.44.4.7": "sninfr4lnxaih01", "140.44.4.8": "sninfr4lnxaih02", "14.4.4.44": "nutserver",
# Synology NAS (2)
"14.10.10.71": "SN-NAS", "14.10.10.72": "SnarfNAS"
}
print("\n=== COVERAGE AUDIT ACROSS 28 TARGET HOSTS ===")
missing = []
for ip, name in sorted(target_hosts.items()):
if ip in registered_ips:
print(f" [OK] {ip} -> {name} (Zabbix Host: {registered_ips[ip]})")
else:
print(f" [MISSING] {ip} -> {name}")
missing.append((ip, name))
print(f"\nTotal Missing from Target 28 Scope: {len(missing)}")
for ip, name in missing:
print(f" - {name} ({ip})")