diff --git a/backend/app/services/tls_service.py b/backend/app/services/tls_service.py index 2113cd4..57d17f3 100644 --- a/backend/app/services/tls_service.py +++ b/backend/app/services/tls_service.py @@ -9,6 +9,7 @@ Erkennt drei Modi: - "certbot" – öffentliches Let's-Encrypt-Zertifikat (setup-tls.sh) - "internal" – eigene interne CA (setup-tls-internal.sh) """ +import os import re import subprocess from pathlib import Path @@ -23,6 +24,10 @@ _DOMAIN_RE = re.compile(r"^[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(?:\.[a _IP_RE = re.compile(r"^\d{1,3}(\.\d{1,3}){3}$") +def _priv(args: list[str]) -> list[str]: + return args if os.geteuid() == 0 else ["sudo", "-n", *args] + + def _cert_enddate(cert_path: Path) -> str | None: try: out = subprocess.run( @@ -71,7 +76,7 @@ def renew_certbot(domain: str) -> str: if not SETUP_TLS_SCRIPT.exists(): raise RuntimeError("setup-tls.sh nicht gefunden") result = subprocess.run( - [str(SETUP_TLS_SCRIPT), domain], + _priv([str(SETUP_TLS_SCRIPT), domain]), capture_output=True, text=True, timeout=120, ) if result.returncode != 0: @@ -89,8 +94,8 @@ def renew_internal(hostname: str, ip: str | None) -> str: args = [str(SETUP_TLS_INTERNAL_SCRIPT), hostname] if ip: args.append(ip) - result = subprocess.run(args, capture_output=True, text=True, timeout=60) + result = subprocess.run(_priv(args), capture_output=True, text=True, timeout=60) if result.returncode != 0: raise RuntimeError(result.stderr[-2000:] or result.stdout[-2000:]) - subprocess.run(["systemctl", "reload", "nginx"], capture_output=True, timeout=10) + subprocess.run(_priv(["systemctl", "reload", "nginx"]), capture_output=True, timeout=10) return result.stdout[-4000:] diff --git a/timemaster.service b/timemaster.service index 37de888..c2544cd 100644 --- a/timemaster.service +++ b/timemaster.service @@ -4,10 +4,13 @@ After=network.target postgresql.service [Service] Type=simple -User=root +User=timemaster +Group=timemaster +PrivateTmp=true +ProtectHome=true WorkingDirectory=/opt/timemaster/backend Environment=PATH=/opt/timemaster/backend/venv/bin -ExecStart=/opt/timemaster/backend/venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips=127.0.0.1 +ExecStart=/opt/timemaster/backend/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000 --proxy-headers --forwarded-allow-ips=127.0.0.1 Restart=on-failure RestartSec=5 diff --git a/timemaster.sudoers b/timemaster.sudoers new file mode 100644 index 0000000..e95b902 --- /dev/null +++ b/timemaster.sudoers @@ -0,0 +1,2 @@ +# /etc/sudoers.d/timemaster – TLS-Erneuerung aus der App (tls_admin) ohne Root-Prozess +timemaster ALL=(root) NOPASSWD: /opt/timemaster/setup-tls.sh *, /opt/timemaster/setup-tls-internal.sh *, /usr/bin/systemctl reload nginx