#!/usr/bin/env python3 """ Provision Gotify Users, Broadcast Applications, and Device Client Tokens on Snarfnet (http://140.44.4.70:8090). """ import base64 import json import urllib.request import paramiko SWARM_MANAGER = "140.44.4.71" SSH_USER = "snarf" SSH_PASS = "Katzir476!" GOTIFY_URL = "http://140.44.4.70:8090" APPLICATIONS = [ (1, "A4uN4fEmErGeNcYtOkEn", 1, "UPS & Power Resilience", "NUT Master UPS power events and tiered shutdown broadcasts", 0, "", 9), (2, "A7zBx9InFrAaLeRtStOk", 1, "Zabbix Infrastructure Alerts", "Zabbix 7.0 infrastructure triggers, node health, and threshold alarms", 0, "", 7), (3, "A3hOmEaSsIsTaNtToKeN", 1, "Home Assistant Smart Home", "Home Assistant smart home alerts and automation broadcasts", 0, "", 5), (4, "A8aWxGiToPsAuToMaTiO", 1, "AWX & GitOps Automation", "Ansible AWX, Semaphore, and ArgoCD deployment & patching notifications", 0, "", 4), (5, "A6bAcKuPsAnDsToRaGeH", 1, "Backups & Storage Health", "NPM, Gotify, Homebox, and Longhorn NFS backup verification alerts", 0, "", 6), ] CLIENTS = [ (1, "C1dIsCoRdBrIdGeClIeN", 1, "Gotify-Discord Multi-Channel Bridge"), (2, "C2sNaRfMoBiLePhOnEcL", 1, "Snarf Primary Mobile Phone"), (3, "C3sNaRfTaBlEtDeViCeC", 1, "Snarf Tablet / Secondary Device"), (4, "C4hOmEpAgEdAsHbOaRdC", 1, "Homepage Dashboard & Workstation"), ] DB_PATHS = [ "/var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db", "/mnt/swarm_shared/legacy_volumes/gotify/gotify.db", "/mnt/swarm_shared/legacy_volumes/gotify/_data/gotify.db", ] def main(): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(SWARM_MANAGER, username=SSH_USER, password=SSH_PASS, timeout=10) remote_py = f"""echo '{SSH_PASS}' | sudo -S python3 -c ' import sqlite3, bcrypt pw_hash = bcrypt.hashpw(b"Katzir476!", bcrypt.gensalt(rounds=10)).replace(b"$2b$", b"$2a$") for db_path in {json.dumps(DB_PATHS)}: conn = sqlite3.connect(db_path) cur = conn.cursor() cur.execute("UPDATE users SET pass = ?, admin = 1 WHERE id = 1", (pw_hash,)) cur.execute("INSERT OR REPLACE INTO users (id, name, pass, admin) VALUES (2, ?, ?, 1)", ("snarf", pw_hash)) for app in {json.dumps(APPLICATIONS)}: cur.execute(\"\"\" INSERT OR REPLACE INTO applications (id, token, user_id, name, description, internal, image, default_priority) VALUES (?, ?, ?, ?, ?, ?, ?, ?) \"\"\", app) for cl in {json.dumps(CLIENTS)}: cur.execute(\"\"\" INSERT OR REPLACE INTO clients (id, token, user_id, name) VALUES (?, ?, ?, ?) \"\"\", cl) conn.commit() conn.close() print("Configured:", db_path) '""" stdin, stdout, stderr = ssh.exec_command(remote_py) print(stdout.read().decode("utf-8", errors="ignore")) err = stderr.read().decode("utf-8", errors="ignore") if err: print("STDERR:", err) ssh.close() # Verify via Gotify HTTP API b64 = base64.b64encode(b"admin:Katzir476!").decode("ascii") req = urllib.request.Request(f"{GOTIFY_URL}/application", headers={"Authorization": f"Basic {b64}"}) with urllib.request.urlopen(req, timeout=8) as r: apps_resp = json.loads(r.read().decode("utf-8")) print(f"Verified {len(apps_resp)} Gotify Applications via REST API:") for a in apps_resp: print(f" - [{a['id']}] {a['name']} (token={a['token']}, defaultPriority={a['defaultPriority']})") req_c = urllib.request.Request(f"{GOTIFY_URL}/client", headers={"Authorization": f"Basic {b64}"}) with urllib.request.urlopen(req_c, timeout=8) as r: clients_resp = json.loads(r.read().decode("utf-8")) print(f"Verified {len(clients_resp)} Gotify Clients via REST API:") for c in clients_resp: print(f" - [{c['id']}] {c['name']} (token={c['token']})") if __name__ == "__main__": main()