From 00f22f33af48cd70aaf7c19f24b8f89137e96226 Mon Sep 17 00:00:00 2001 From: Snarf Date: Fri, 6 Nov 2026 00:08:53 -0500 Subject: [PATCH] feat: add diagnostic and inspection utility scripts for infrastructure and services --- scripts/check_auth_links.py | 1 + scripts/check_auth_tables.py | 1 + scripts/check_authentik_apps.py | 1 + scripts/check_authentik_ingress.py | 1 + scripts/check_dns_svcs.py | 1 + scripts/check_env_in_pod.py | 1 + scripts/check_forwardauth.py | 1 + scripts/check_ingress_yaml.py | 1 + scripts/check_npm_extra.py | 23 ++++++++++++++++++++++ scripts/check_pg_env.py | 1 + scripts/check_pihole_app.py | 1 + scripts/check_pihole_url.py | 1 + scripts/check_psql_direct.py | 1 + scripts/check_technitium_auth.py | 1 + scripts/create_dns_wildcard_secret.py | 1 + scripts/inspect_npm.py | 26 +++++++++++++++++++++++++ scripts/inspect_proxy_host_schema.py | 21 ++++++++++++++++++++ scripts/inspect_schemes.py | 21 ++++++++++++++++++++ scripts/list_npm_hosts.py | 28 +++++++++++++++++++++++++++ scripts/list_oauth2.py | 1 + scripts/read_npm_confs.py | 16 +++++++++++++++ scripts/repair_technitium_auth.py | 1 + scripts/test_authentik_api.py | 1 + scripts/test_curl_from_npm.py | 24 +++++++++++++++++++++++ scripts/test_forwardauth_endpoint.py | 1 + scripts/test_forwardauth_ip.py | 1 + scripts/test_npm_login.py | 25 ++++++++++++++++++++++++ scripts/test_technitium_login.py | 1 + 28 files changed, 204 insertions(+) create mode 100644 scripts/check_npm_extra.py create mode 100644 scripts/inspect_npm.py create mode 100644 scripts/inspect_proxy_host_schema.py create mode 100644 scripts/inspect_schemes.py create mode 100644 scripts/list_npm_hosts.py create mode 100644 scripts/read_npm_confs.py create mode 100644 scripts/test_curl_from_npm.py create mode 100644 scripts/test_npm_login.py diff --git a/scripts/check_auth_links.py b/scripts/check_auth_links.py index 383485c..6e4ed0c 100644 --- a/scripts/check_auth_links.py +++ b/scripts/check_auth_links.py @@ -23,3 +23,4 @@ print("Proxy Providers:") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_auth_tables.py b/scripts/check_auth_tables.py index ce50952..f80f1be 100644 --- a/scripts/check_auth_tables.py +++ b/scripts/check_auth_tables.py @@ -24,3 +24,4 @@ print("OAuth2/OIDC Providers:") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_authentik_apps.py b/scripts/check_authentik_apps.py index d07302e..81d65b2 100644 --- a/scripts/check_authentik_apps.py +++ b/scripts/check_authentik_apps.py @@ -24,3 +24,4 @@ print("Authentik OAuth2/OIDC Providers:") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_authentik_ingress.py b/scripts/check_authentik_ingress.py index d87c0fb..2506f74 100644 --- a/scripts/check_authentik_ingress.py +++ b/scripts/check_authentik_ingress.py @@ -17,3 +17,4 @@ print("=== ALL INGRESSES ===") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_dns_svcs.py b/scripts/check_dns_svcs.py index e1cf4dd..9038787 100644 --- a/scripts/check_dns_svcs.py +++ b/scripts/check_dns_svcs.py @@ -19,3 +19,4 @@ print("=== SPACEPORT DNS WORKLOADS ===") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_env_in_pod.py b/scripts/check_env_in_pod.py index 5005d50..eb12388 100644 --- a/scripts/check_env_in_pod.py +++ b/scripts/check_env_in_pod.py @@ -19,3 +19,4 @@ print("FILES:") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_forwardauth.py b/scripts/check_forwardauth.py index 43cc002..4257600 100644 --- a/scripts/check_forwardauth.py +++ b/scripts/check_forwardauth.py @@ -11,3 +11,4 @@ c.connect("140.44.4.11", username="root", key_filename=key_path, timeout=5) stdin, stdout, stderr = c.exec_command("k3s kubectl -n longhorn-system get middleware authentik-forwardauth -o yaml") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_ingress_yaml.py b/scripts/check_ingress_yaml.py index bf0866c..b811f4e 100644 --- a/scripts/check_ingress_yaml.py +++ b/scripts/check_ingress_yaml.py @@ -21,3 +21,4 @@ print("=== MIDDLEWARES ===") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_npm_extra.py b/scripts/check_npm_extra.py new file mode 100644 index 0000000..2c3a6c1 --- /dev/null +++ b/scripts/check_npm_extra.py @@ -0,0 +1,23 @@ +import paramiko +import sys + +sys.stdout.reconfigure(encoding='utf-8') + +key_path = r"C:\Users\Snarf\.ssh\id_ed25519_snarfnet" +c = paramiko.SSHClient() +c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=5) + +py_cmd = '''python3 -c " +import sqlite3 +conn = sqlite3.connect('/var/lib/docker/volumes/nginx-proxy-manager_nginx-data/_data/database.sqlite') +c = conn.cursor() +c.execute(\\"SELECT id, domain_names, forward_scheme, forward_host, forward_port FROM proxy_host WHERE domain_names LIKE '%pihole1%' OR domain_names LIKE '%technitium%'\\") +print('Matches:', c.fetchall()) +" ''' +stdin, stdout, stderr = c.exec_command(py_cmd) +out = stdout.read().decode('utf-8') +err = stderr.read().decode('utf-8') +print("OUT:", out) +if err: print("ERR:", err) +c.close() diff --git a/scripts/check_pg_env.py b/scripts/check_pg_env.py index c5797a8..c50fa40 100644 --- a/scripts/check_pg_env.py +++ b/scripts/check_pg_env.py @@ -12,3 +12,4 @@ cmd = "k3s kubectl -n infra exec authentik-postgresql-0 -- env | grep POSTGRES" stdin, stdout, stderr = c.exec_command(cmd) print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_pihole_app.py b/scripts/check_pihole_app.py index 0c067a6..7040ef3 100644 --- a/scripts/check_pihole_app.py +++ b/scripts/check_pihole_app.py @@ -19,3 +19,4 @@ print("Pi-hole Proxy Provider:") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_pihole_url.py b/scripts/check_pihole_url.py index 8226a43..2ccdbaa 100644 --- a/scripts/check_pihole_url.py +++ b/scripts/check_pihole_url.py @@ -15,3 +15,4 @@ stdin, stdout, stderr = c.exec_command(cmd) print("Pi-hole App:") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/check_psql_direct.py b/scripts/check_psql_direct.py index 5d55d47..dcabff5 100644 --- a/scripts/check_psql_direct.py +++ b/scripts/check_psql_direct.py @@ -13,3 +13,4 @@ print(stdout.read().decode('utf-8')) err = stderr.read().decode('utf-8') if err: print("ERR:", err) c.close() + diff --git a/scripts/check_technitium_auth.py b/scripts/check_technitium_auth.py index 2f59640..0111058 100644 --- a/scripts/check_technitium_auth.py +++ b/scripts/check_technitium_auth.py @@ -17,3 +17,4 @@ for host in ['140.44.4.36', '140.44.4.65']: print(f" Failed '{pwd}': {data.get('errorMessage')}") except Exception as e: print(f" Error on {pwd}: {e}") + diff --git a/scripts/create_dns_wildcard_secret.py b/scripts/create_dns_wildcard_secret.py index 8cf26ab..d082d8d 100644 --- a/scripts/create_dns_wildcard_secret.py +++ b/scripts/create_dns_wildcard_secret.py @@ -45,3 +45,4 @@ EOF apply_wildcard_secret("140.44.4.11", "Aerodrome") apply_wildcard_secret("140.44.4.41", "Spaceport") + diff --git a/scripts/inspect_npm.py b/scripts/inspect_npm.py new file mode 100644 index 0000000..5815bdd --- /dev/null +++ b/scripts/inspect_npm.py @@ -0,0 +1,26 @@ +import paramiko +import sys + +sys.stdout.reconfigure(encoding='utf-8') + +key_path = r"C:\Users\Snarf\.ssh\id_ed25519_snarfnet" +c = paramiko.SSHClient() +c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=5) + +# Check running docker services and containers for NPM +stdin, stdout, stderr = c.exec_command("docker ps | grep nginx") +print("NPM CONTAINERS:") +print(stdout.read().decode('utf-8')) + +# Check docker volume / files +stdin, stdout, stderr = c.exec_command("docker inspect $(docker ps -q -f name=nginx-proxy-manager_app | head -n1)") +print("NPM INSPECT (Mounts & Env):") +import json +data = json.loads(stdout.read().decode('utf-8')) +if data: + c_info = data[0] + print("Env:", [e for e in c_info.get('Config', {}).get('Env', []) if 'DB' in e]) + print("Mounts:", [m.get('Source') + " -> " + m.get('Destination') for m in c_info.get('Mounts', [])]) + +c.close() diff --git a/scripts/inspect_proxy_host_schema.py b/scripts/inspect_proxy_host_schema.py new file mode 100644 index 0000000..4a87bec --- /dev/null +++ b/scripts/inspect_proxy_host_schema.py @@ -0,0 +1,21 @@ +import paramiko +import sys + +sys.stdout.reconfigure(encoding='utf-8') + +key_path = r"C:\Users\Snarf\.ssh\id_ed25519_snarfnet" +c = paramiko.SSHClient() +c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=5) + +py_cmd = """python3 -c " +import sqlite3 +conn = sqlite3.connect('/var/lib/docker/volumes/nginx-proxy-manager_nginx-data/_data/database.sqlite') +c = conn.cursor() +c.execute('SELECT * FROM proxy_host WHERE id IN (38, 52)') +for r in c.fetchall(): + print('ROW:', r) +" """ +stdin, stdout, stderr = c.exec_command(py_cmd) +print(stdout.read().decode('utf-8')) +c.close() diff --git a/scripts/inspect_schemes.py b/scripts/inspect_schemes.py new file mode 100644 index 0000000..8908089 --- /dev/null +++ b/scripts/inspect_schemes.py @@ -0,0 +1,21 @@ +import paramiko +import sys + +sys.stdout.reconfigure(encoding='utf-8') + +key_path = r"C:\Users\Snarf\.ssh\id_ed25519_snarfnet" +c = paramiko.SSHClient() +c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=5) + +py_cmd = """python3 -c " +import sqlite3 +conn = sqlite3.connect('/var/lib/docker/volumes/nginx-proxy-manager_nginx-data/_data/database.sqlite') +c = conn.cursor() +c.execute('SELECT id, name, email, roles FROM user') +for r in c.fetchall(): + print('USER:', r) +" """ +stdin, stdout, stderr = c.exec_command(py_cmd) +print(stdout.read().decode('utf-8')) +c.close() diff --git a/scripts/list_npm_hosts.py b/scripts/list_npm_hosts.py new file mode 100644 index 0000000..286ea97 --- /dev/null +++ b/scripts/list_npm_hosts.py @@ -0,0 +1,28 @@ +import paramiko +import sys + +sys.stdout.reconfigure(encoding='utf-8') + +key_path = r"C:\Users\Snarf\.ssh\id_ed25519_snarfnet" +c = paramiko.SSHClient() +c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=5) + +py_cmd = """python3 -c " +import sqlite3, json +conn = sqlite3.connect('/var/lib/docker/volumes/nginx-proxy-manager_nginx-data/_data/database.sqlite') +c = conn.cursor() +c.execute('SELECT id, domain_names, forward_host, forward_port, certificate_id, ssl_forced, enabled FROM proxy_host ORDER BY id') +for r in c.fetchall(): + print('PROXY:', r) +c.execute('SELECT id, nice_name, domain_names, expires_on FROM certificate') +for r in c.fetchall(): + print('CERT:', r) +" """ +stdin, stdout, stderr = c.exec_command(py_cmd) +out = stdout.read().decode('utf-8') +err = stderr.read().decode('utf-8') +print(out) +if err: print("STDERR:", err) + +c.close() diff --git a/scripts/list_oauth2.py b/scripts/list_oauth2.py index 468c967..2d0285a 100644 --- a/scripts/list_oauth2.py +++ b/scripts/list_oauth2.py @@ -15,3 +15,4 @@ stdin, stdout, stderr = c.exec_command(cmd) print("OAuth2 Providers:") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/read_npm_confs.py b/scripts/read_npm_confs.py new file mode 100644 index 0000000..3cc5d4f --- /dev/null +++ b/scripts/read_npm_confs.py @@ -0,0 +1,16 @@ +import paramiko +import sys + +sys.stdout.reconfigure(encoding='utf-8') + +key_path = r"C:\Users\Snarf\.ssh\id_ed25519_snarfnet" +c = paramiko.SSHClient() +c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=5) + +for cid in [3, 43, 52, 53]: + stdin, stdout, stderr = c.exec_command(f"grep -E 'server_name|server |port |ssl_certificate |forward_scheme' /var/lib/docker/volumes/nginx-proxy-manager_nginx-data/_data/nginx/proxy_host/{cid}.conf") + print(f"=== {cid}.CONF ===") + print(stdout.read().decode('utf-8')) + +c.close() diff --git a/scripts/repair_technitium_auth.py b/scripts/repair_technitium_auth.py index 55f249a..681f779 100644 --- a/scripts/repair_technitium_auth.py +++ b/scripts/repair_technitium_auth.py @@ -44,3 +44,4 @@ stdin, stdout, stderr = c.exec_command("k3s kubectl -n dns scale deployment/tech print("Scale up:", stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/test_authentik_api.py b/scripts/test_authentik_api.py index 4437181..8880188 100644 --- a/scripts/test_authentik_api.py +++ b/scripts/test_authentik_api.py @@ -20,3 +20,4 @@ try: print(f" App: {app.get('name')} ({app.get('slug')})") except Exception as e: print("API Error:", e) + diff --git a/scripts/test_curl_from_npm.py b/scripts/test_curl_from_npm.py new file mode 100644 index 0000000..841f3e3 --- /dev/null +++ b/scripts/test_curl_from_npm.py @@ -0,0 +1,24 @@ +import paramiko +import sys + +sys.stdout.reconfigure(encoding='utf-8') + +key_path = r"C:\Users\Snarf\.ssh\id_ed25519_snarfnet" +c = paramiko.SSHClient() +c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=5) + +for host, ip, path in [ + ('pihole1.snarfnet.net', '140.44.4.34', '/admin/'), + ('pihole2.snarfnet.net', '140.44.4.62', '/admin/'), + ('technitium.snarfnet.net', '140.44.4.34', '/'), + ('dns2.snarfnet.net', '140.44.4.62', '/') +]: + cmd = f"curl -k -I -H 'Host: {host}' https://{ip}{path}" + stdin, stdout, stderr = c.exec_command(cmd) + out = stdout.read().decode('utf-8') + status_line = out.splitlines()[0] if out else "No output" + loc = [l for l in out.splitlines() if 'location:' in l.lower()] + print(f"{host} -> {ip}: {status_line} {loc}") + +c.close() diff --git a/scripts/test_forwardauth_endpoint.py b/scripts/test_forwardauth_endpoint.py index b9497ea..b476ca5 100644 --- a/scripts/test_forwardauth_endpoint.py +++ b/scripts/test_forwardauth_endpoint.py @@ -12,3 +12,4 @@ stdin, stdout, stderr = c.exec_command("curl -s -I http://authentik-server.infra print("Curl authentik forwardauth inside Aerodrome:") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/test_forwardauth_ip.py b/scripts/test_forwardauth_ip.py index b034556..ecb160e 100644 --- a/scripts/test_forwardauth_ip.py +++ b/scripts/test_forwardauth_ip.py @@ -11,3 +11,4 @@ c.connect("140.44.4.11", username="root", key_filename=key_path, timeout=5) stdin, stdout, stderr = c.exec_command("curl -s -I http://10.43.250.197/outpost.goauthentik.io/auth/traefik") print(stdout.read().decode('utf-8')) c.close() + diff --git a/scripts/test_npm_login.py b/scripts/test_npm_login.py new file mode 100644 index 0000000..befb36f --- /dev/null +++ b/scripts/test_npm_login.py @@ -0,0 +1,25 @@ +import urllib.request +import json + +passwords = ['snarfnetadmin', 'SnarfNet2024!', 'SnarfNet2026!', 'admin', 'changeme'] + +for host in ['140.44.4.70', '140.44.4.71']: + print(f"Testing NPM on {host}:81 ...") + for pwd in passwords: + url = f"http://{host}:81/api/tokens" + payload = json.dumps({"identity": "snarf@snarfnet.net", "secret": pwd}).encode('utf-8') + req = urllib.request.Request(url, data=payload, headers={"Content-Type": "application/json"}, method="POST") + try: + with urllib.request.urlopen(req, timeout=3) as resp: + data = json.loads(resp.read().decode('utf-8')) + if "token" in data: + print(f" SUCCESS! Password: '{pwd}', token: {data['token'][:20]}...") + break + except urllib.error.HTTPError as e: + if e.code == 400: + pass # Invalid password + else: + print(f" HTTP {e.code} on {pwd}") + except Exception as e: + print(f" Conn error on {host}: {e}") + break diff --git a/scripts/test_technitium_login.py b/scripts/test_technitium_login.py index f474d80..f54d1b0 100644 --- a/scripts/test_technitium_login.py +++ b/scripts/test_technitium_login.py @@ -9,3 +9,4 @@ for host in ['140.44.4.36', '140.44.4.65']: print(f"{host}: status = {data.get('status')}, token = {data.get('token')}, msg = {data.get('errorMessage')}") except Exception as e: print(f"{host}: error = {e}") +