fix(security): Dienst als Systemuser auf 127.0.0.1, TLS-Erneuerung per sudo
Security Audit / Python Dependency Audit (push) Canceled after 0s
Security Audit / Node.js Dependency Audit (push) Canceled after 0s
Security Audit / Frontend Build (tsc + vite) (push) Canceled after 0s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
patrickandClaude Sonnet 5.5 committed 2026-11-05 00:20:26 +01:00
1 parent 8a55e183fd
commit c02338eb7a
3 files changed
+15 -5

No files matched your search

+8 -3
View File
@@ -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:]
+5 -2
View File
@@ -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
+2
View File
@@ -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