Merge pull request 'fix: WireGuard-Kandidat korrekt validieren' (#53) from fix/sascha-media-tunnel-validation-20260905 into main

This commit is contained in:
sascha 2026-09-05 13:02:48 +02:00
commit 02762cc651
2 changed files with 24 additions and 3 deletions

25
app.py
View file

@ -12,7 +12,7 @@ from contextlib import asynccontextmanager
from contextvars import ContextVar
log = logging.getLogger("butler")
VERSION = "2.3.7"
VERSION = "2.3.8"
API_DIR = os.environ.get("API_KEY_DIR", "/data/api")
VAULT_CACHE_DIR = os.environ.get("VAULT_CACHE_DIR", "/data/vault-cache")
@ -2409,7 +2409,7 @@ def _media_tunnel_install_command(role: Literal["vps", "emby"], peer_public_key:
+lines.extend(["", "[Peer]", "PublicKey = {peer_public_key}", "AllowedIPs = {settings['peer']}"])
+if {settings['endpoint']!r}: lines.append("Endpoint = " + {settings['endpoint']!r})
+if {settings['keepalive']!r}: lines.append("PersistentKeepalive = " + str({settings['keepalive']!r}))
+candidate = root / "wg-media.conf.candidate"
+candidate = root / "wg-media-candidate.conf"
+candidate.write_text("\\n".join(lines) + "\\n")
+os.chmod(candidate, 0o600)
+check = subprocess.run(["wg-quick", "strip", str(candidate)], text=True, capture_output=True)
@ -2485,6 +2485,22 @@ def _media_tunnel_rollback_command(remove_keys: bool) -> str:
return f'sudo -n python3 -c "import base64;exec(base64.b64decode(\'{encoded}\'))"'
def _media_tunnel_key_cleanup_command() -> str:
script = '''import json
+from pathlib import Path
+root = Path("/app-config/wireguard-media")
+if not (root / "wg-media.conf").exists():
+ (root / "private.key").unlink(missing_ok=True)
+ (root / "public.key").unlink(missing_ok=True)
+ status = "new_keys_removed"
+else:
+ status = "kept_for_existing_config"
+print(json.dumps({"status": status}))
+'''.replace("\n+", "\n")
encoded = base64.b64encode(script.encode()).decode()
return f'sudo -n python3 -c "import base64;exec(base64.b64decode(\'{encoded}\'))"'
def _media_host_target(name: str) -> str:
inventory = _find_inventory_host(name)
if not inventory:
@ -2531,6 +2547,11 @@ def _deploy_sascha_media_tunnel() -> dict:
for target, created in reversed(configured):
try: _ssh_json(target, _media_tunnel_rollback_command(created), 60)
except Exception: pass
installed_targets = {target for target, _created in configured}
for target, key in ((vps, vps_key), (emby, emby_key)):
if target not in installed_targets and key.get("created"):
try: _ssh_json(target, _media_tunnel_key_cleanup_command(), 30)
except Exception: pass
raise

View file

@ -43,7 +43,7 @@ def test_health_exposes_current_version():
with TestClient(app.app) as client:
response = client.get("/health")
assert response.status_code == 200
assert response.json()["version"] == app.VERSION == "2.3.7"
assert response.json()["version"] == app.VERSION == "2.3.8"
def test_media_handoff_proxies_strict_category_contract(monkeypatch):