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" } provider_payload = { "name": "Technitium DNS Server", "authorization_flow": "38a86ef3-f43a-4756-8f54-ca008a8eef6e", "invalidation_flow": "7a8145b8-2476-4636-9901-825f826df805", "client_type": "confidential", "client_id": "technitium-dns-oidc", "client_secret": "SnarfNetTechnitiumOIDC2026!", "redirect_uris": [ {"url": "https://technitium.snarfnet.net/sso/callback", "matching_mode": "strict"}, {"url": "https://dns1.snarfnet.net/sso/callback", "matching_mode": "strict"}, {"url": "https://dns2.snarfnet.net/sso/callback", "matching_mode": "strict"}, {"url": "https://technitium.snarfnet.net/", "matching_mode": "strict"}, {"url": "https://dns1.snarfnet.net/", "matching_mode": "strict"}, {"url": "https://dns2.snarfnet.net/", "matching_mode": "strict"}, {"url": "https://.*\\.snarfnet\\.net/sso/callback", "matching_mode": "regex"} ], "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 } print("1. Creating OAuth2 Provider in Authentik...") req = urllib.request.Request( "https://authentik.snarfnet.net/api/v3/providers/oauth2/", headers=headers, data=json.dumps(provider_payload).encode('utf-8'), method="POST" ) try: with urllib.request.urlopen(req, context=ctx, timeout=8) as resp: prov_data = json.loads(resp.read().decode('utf-8')) prov_pk = prov_data.get('pk') print(f"Provider created successfully! PK: {prov_pk}") except urllib.error.HTTPError as e: err_body = e.read().decode('utf-8') print(f"Provider creation failed ({e.code}): {err_body}") # Check if it already exists req_check = urllib.request.Request( "https://authentik.snarfnet.net/api/v3/providers/oauth2/?search=Technitium", headers=headers ) with urllib.request.urlopen(req_check, context=ctx, timeout=8) as resp_c: existing = json.loads(resp_c.read().decode('utf-8')) if existing.get('results'): prov_pk = existing['results'][0]['pk'] print(f"Using existing provider PK: {prov_pk}") else: sys.exit(1) print("2. Creating Application in Authentik...") app_payload = { "name": "Technitium DNS Server", "slug": "technitium", "provider": prov_pk, "group": "Infrastructure & Hypervisors", "meta_launch_url": "https://technitium.snarfnet.net", "meta_description": "Authoritative & Recursive DNS Server with Ad Blocking and Split-Horizon", "meta_icon": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/technitium.png", "open_in_new_tab": True } req_app = urllib.request.Request( "https://authentik.snarfnet.net/api/v3/core/applications/", headers=headers, data=json.dumps(app_payload).encode('utf-8'), method="POST" ) try: with urllib.request.urlopen(req_app, context=ctx, timeout=8) as resp: app_data = json.loads(resp.read().decode('utf-8')) print(f"Application created successfully! Slug: {app_data.get('slug')}") except urllib.error.HTTPError as e: err_body = e.read().decode('utf-8') print(f"Application creation ({e.code}): {err_body}") print("\nOIDC Setup Details:") print(f" Issuer / Metadata: https://authentik.snarfnet.net/application/o/technitium/.well-known/openid-configuration") print(f" Client ID: technitium-dns-oidc") print(f" Client Secret: SnarfNetTechnitiumOIDC2026!")