From ed501e676b06072b62e2aad0a96c1bb5f2b9990f Mon Sep 17 00:00:00 2001 From: sascha Date: Sat, 8 Aug 2026 14:11:24 +0200 Subject: [PATCH 1/2] fix: allow authenticated one-shot DNS token fallback --- app.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index b012cd4..d6bed00 100644 --- a/app.py +++ b/app.py @@ -920,6 +920,7 @@ def _validate_proxy_route(domain: str, upstream: str) -> tuple[str, str, str, st class ProxyRouteRequest(BaseModel): domain: str upstream: str + dns_token: str | None = None def _remote_python(script: str, timeout: int = 30) -> tuple[int, str, str]: @@ -995,8 +996,8 @@ def _get_hetzner_dns_token() -> str: return token -async def _upsert_dns_records(zone: str, name: str) -> dict: - token = await asyncio.to_thread(_get_hetzner_dns_token) +async def _upsert_dns_records(zone: str, name: str, token_override: str | None = None) -> dict: + token = token_override or await asyncio.to_thread(_get_hetzner_dns_token) headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} api = "https://api.hetzner.cloud/v1" async with httpx.AsyncClient(timeout=30) as client: @@ -1027,7 +1028,7 @@ async def vps_proxy_route(req: ProxyRouteRequest, _=Depends(_verify)): raise HTTPException(400, str(exc)) from exc caddy = await asyncio.to_thread(_configure_caddy_route, domain, upstream) try: - dns = await _upsert_dns_records(zone, name) + dns = await _upsert_dns_records(zone, name, req.dns_token) except Exception: await asyncio.to_thread(_restore_caddy_backup, caddy["backup"]) raise -- 2.49.1 From 3239f54e5dd8d475b9d14f748d91fb71d9515b45 Mon Sep 17 00:00:00 2001 From: sascha Date: Sat, 8 Aug 2026 14:11:24 +0200 Subject: [PATCH 2/2] test: verify DNS token fallback forwarding --- tests/test_app.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_app.py b/tests/test_app.py index 7d1e3ee..b8adbfe 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -290,8 +290,8 @@ def test_proxy_route_endpoint_configures_caddy_and_dns(monkeypatch): calls.append(("caddy", domain, upstream)) return {"status": "reloaded", "backup": "/app-config/caddy/Caddyfile.bak-test"} - async def fake_dns(zone, name): - calls.append(("dns", zone, name)) + async def fake_dns(zone, name, token_override=None): + calls.append(("dns", zone, name, token_override)) return {"zone_id": 123, "records": ["A", "AAAA"]} monkeypatch.setattr(app, "_configure_caddy_route", fake_caddy) @@ -300,14 +300,14 @@ def test_proxy_route_endpoint_configures_caddy_and_dns(monkeypatch): response = client.post( "/vps/proxy-route", headers={"Authorization": "Bearer test-token"}, - json={"domain": "speed.guck.tv", "upstream": "127.0.0.1:8080"}, + json={"domain": "speed.guck.tv", "upstream": "127.0.0.1:8080", "dns_token": "test-dns-token"}, ) assert response.status_code == 200 assert response.json()["status"] == "configured" assert calls == [ ("caddy", "speed.guck.tv", "127.0.0.1:8080"), - ("dns", "guck.tv", "speed"), + ("dns", "guck.tv", "speed", "test-dns-token"), ] -- 2.49.1