import urllib.request import ssl import json import sys sys.stdout.reconfigure(encoding='utf-8') ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE token = "SnarfNetPermanentAutomationToken2026" headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" } def api_call(url, method="GET", payload=None): data = json.dumps(payload).encode('utf-8') if payload else None req = urllib.request.Request(url, headers=headers, data=data, method=method) try: with urllib.request.urlopen(req, context=ctx, timeout=8) as resp: return json.loads(resp.read().decode('utf-8')) except urllib.error.HTTPError as e: err = e.read().decode('utf-8') print(f"API Error {e.code} on {method} {url}: {err}") return None print("1. Creating OAuth2 Provider for Technitium DNS 2...") p25_payload = { "name": "Technitium DNS 2 SSO (Spaceport)", "authorization_flow": "38a86ef3-f43a-4756-8f54-ca008a8eef6e", "invalidation_flow": "7a8145b8-2476-4636-9901-825f826df805", "client_type": "confidential", "client_id": "technitium2-dns-oidc", "client_secret": "SnarfNetTechnitiumOIDC2026!", "redirect_uris": [ {"url": "https://dns2.snarfnet.net/sso/callback", "matching_mode": "strict"}, {"url": "https://dns2.snarfnet.net/", "matching_mode": "strict"} ], "signing_key": "6d48ba88-4b51-428f-903c-93334988a941", "property_mappings": [ "f521356c-080d-4bd6-b19a-68ab159a5aef", # openid "8395b909-8e8d-4fc1-a620-5592e10df8fe", # email "85b89b43-92d8-425c-b9cc-8e00038cad37", # profile "d2248142-6be2-4833-94f8-e02f5d293b02" # groups ], "sub_mode": "hashed_user_id", "issuer_mode": "per_provider", "include_claims_in_id_token": True } prov = api_call("https://authentik.snarfnet.net/api/v3/providers/oauth2/", method="POST", payload=p25_payload) if not prov: # Check if exists res = api_call("https://authentik.snarfnet.net/api/v3/providers/oauth2/?search=Technitium+DNS+2") prov_pk = res['results'][0]['pk'] else: prov_pk = prov['pk'] print(f"Provider created/found: PK {prov_pk}") print("\n2. Creating Application 'Technitium DNS 2 (Spaceport)'...") app2_payload = { "name": "Technitium DNS 2 (Spaceport)", "slug": "dns2", "provider": prov_pk, "group": "Networking & Edge", "meta_launch_url": "https://dns2.snarfnet.net", "meta_description": "Authoritative & Recursive DNS Server with DoH & Local Resolution (Spaceport Secondary)", "meta_icon": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/technitium.png", "open_in_new_tab": True } app = api_call("https://authentik.snarfnet.net/api/v3/core/applications/", method="POST", payload=app2_payload) if app: print(f"Created Application: {app.get('name')} (slug: {app.get('slug')})") else: api_call("https://authentik.snarfnet.net/api/v3/core/applications/dns2/", method="PATCH", payload=app2_payload) print("Updated Application dns2") print("\n3. Listing all DNS applications in Authentik App Library:") final_apps = api_call("https://authentik.snarfnet.net/api/v3/core/applications/?page_size=100") for a in sorted(final_apps.get('results', []), key=lambda x: x['name']): if a['slug'] in ['pihole1', 'pihole2', 'dns1', 'dns2']: print(f" [{a['group']}] {a['name']}") print(f" Slug: {a['slug']} | URL: {a['meta_launch_url']} | Provider PK: {a['provider']}")