diff --git a/README.md b/README.md index fa0cd1c..83eca70 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,10 @@ Dienst, siehe [ADR-0011](https://git.tuxflotte.de/admin/platform-docs/raw/branch - Läuft unter einem eigenen, unprivilegierten System-User `provisioning-server` (nicht root - siehe `provisioning-server.service` und [ADR-0027](https://git.tuxflotte.de/admin/platform-docs/raw/branch/main/adr/0027-provisioning-server-de-root-per-scoped-sudo.md)). - Der Self-Service-ISO-Bau (`run_iso_build()` in `app.py`) braucht für - `unsquashfs`/`mksquashfs` weiterhin echtes root (Datei-Eigentümer-Erhalt im - Squashfs) - dafür eskaliert genau dieser eine Aufruf per eng gefasster - sudo-Regel, siehe `provisioning-server-iso-build.sudoers`. + Seit 03.10.2026 braucht auch der Self-Service-ISO-Bau (`run_iso_build()` + in `app.py`) kein root mehr: `build_customer_iso.sh` legt die Kundendaten + als eigene Squashfs-Schicht auf das Boot-Medium. Die frühere sudo-Regel + (ADR-0027) ist entfallen, die Unit hat die volle Härtung. ## Setup (lokal) @@ -56,12 +56,10 @@ zusätzlich zum Code-Deploy nötig (einmalig, nicht Teil von `git pull`): diesem User gehörend. 2. `provisioning-server.service` nach `/etc/systemd/system/` kopieren, `systemctl daemon-reload && systemctl enable --now provisioning-server`. -3. `provisioning-server-iso-build.sudoers` nach - `/etc/sudoers.d/provisioning-server-iso-build` kopieren (Eigentümer - root:root, Modus 440), mit `visudo -cf` prüfen. -4. `tuxflotte-installer`-Repo an den Pfad aus `TUXFLOTTE_INSTALLER_DIR` - klonen (für den diese Sudo-Regel gilt - bei einem anderen Pfad die Regel - entsprechend anpassen). +3. `tuxflotte-installer`-Repo an den Pfad aus `TUXFLOTTE_INSTALLER_DIR` + klonen (für den Dienstbenutzer lesbar). +4. Arbeitsverzeichnis für den ISO-Bau `/srv/tuxflotte/build-tmp` dem + Dienstbenutzer übereignen (ohne dieses Verzeichnis `/var/tmp`). **Öffentliche Erreichbarkeit über Pangolin ist nicht Teil dieses Repos** — das ist ein separater Ops/DNS/Reverse-Proxy-Schritt. diff --git a/app.py b/app.py index 061f74e..b63ed42 100644 --- a/app.py +++ b/app.py @@ -3841,15 +3841,13 @@ def run_iso_build( golden_image_file = str(golden_image) try: - # De-Root-Umzug (07.09.2026): der Dienst selbst laeuft nicht mehr als - # root, aber build_customer_iso.sh braucht es weiterhin zwingend - # (unsquashfs/mksquashfs, CAP_MKNOD - siehe Kommentar dort). Statt den - # ganzen Prozess wieder privilegiert laufen zu lassen, nur dieser eine - # Aufruf per eng gefasster NOPASSWD-sudo-Regel (siehe - # /etc/sudoers.d/provisioning-server-iso-build). + # Laeuft seit 03.10.2026 ohne jede Privilegien-Eskalation: + # build_customer_iso.sh legt die Kundendaten als eigene kleine + # Squashfs-Schicht auf das Boot-Medium, statt das ganze Squashfs als + # root neu zu packen (vorher scoped sudo, ADR-0027 - abgeloest durch + # das Berechtigungskonzept, siehe platform-docs). result = subprocess.run( [ - "sudo", "bash", f"{TUXFLOTTE_INSTALLER_DIR}/scripts/build_customer_iso.sh", BOOT_MEDIUM_PATH, @@ -3857,8 +3855,8 @@ def run_iso_build( activation_code, wifi_ssid or "", # Geheimnisse per stdin statt als Argument (Kunden-ISO-Test - # 02.10.2026, Befund B6): Argumente landen ueber sudo im - # Klartext im Journal - siehe build_customer_iso.sh. + # 02.10.2026, Befund B6): Argumente stehen in der + # Prozessliste - siehe build_customer_iso.sh. "-", volid, ], diff --git a/provisioning-server-iso-build.sudoers b/provisioning-server-iso-build.sudoers deleted file mode 100644 index 24f95e8..0000000 --- a/provisioning-server-iso-build.sudoers +++ /dev/null @@ -1,8 +0,0 @@ -# Eng gefasste sudo-Ausnahme (De-Root-Umzug 07.09.2026, siehe ADR-0027): -# build_customer_iso.sh braucht root fuer unsquashfs/mksquashfs -# (CAP_CHOWN/CAP_FOWNER zum Erhalten der Datei-Eigentuemer im Squashfs, -# siehe Kommentar dort). Nur genau dieser Skriptpfad, keine anderen Befehle. -# -# Installation: nach /etc/sudoers.d/provisioning-server-iso-build kopieren, -# Eigentuemer root:root, Modus 440, danach mit `visudo -cf` pruefen. -provisioning-server ALL=(root) NOPASSWD: /usr/bin/bash /opt/tuxflotte-installer/scripts/build_customer_iso.sh * diff --git a/provisioning-server.service b/provisioning-server.service index 3c0a031..274f7ad 100644 --- a/provisioning-server.service +++ b/provisioning-server.service @@ -12,37 +12,20 @@ ExecStart=/opt/provisioning-server/.venv/bin/uvicorn app:app --host 0.0.0.0 --po Restart=always RestartSec=3 -# De-Root-Umzug (07.09.2026, siehe kundenplattform.service fuer das Vorbild -# und ADR-0011 fuer die urspruengliche root/non-root-Unterscheidung). Fast -# dieselbe Haertung wie dort, mit DREI bewussten Ausnahmen: NoNewPrivileges, -# CapabilityBoundingSet/AmbientCapabilities UND RestrictSUIDSGID bleiben -# HIER weg, weil run_iso_build() in app.py per scoped sudo (siehe -# provisioning-server-iso-build.sudoers) zu echtem root eskaliert - -# build_customer_iso.sh braucht das fuer CAP_CHOWN/CAP_FOWNER beim -# Wiederherstellen der Datei-Eigentuemer im Squashfs (NICHT fuer Mount/ -# Device-Operationen - die wurden schon am 01.09.2026 umgangen, /dev bleibt -# ein leeres Verzeichnis). NoNewPrivileges wuerde sudos Setuid-Eskalation -# kernelseitig blockieren, eine geleerte CapabilityBoundingSet wuerde dem -# eskalierten Root-Kind dauerhaft die Capabilities entziehen, die es fuer -# den Chown-Erhalt braucht - beides also unvereinbar mit diesem einen -# schmalen, sudo-basierten Privileg-Pfad. Siehe ADR-0027. -# -# RestrictSUIDSGID (08.09.2026 als echten Regressionsbug gefunden UND -# entfernt): wirkt wie NoNewPrivileges per Seccomp-Filter unterhalb der -# UID-Ebene und wird deshalb NICHT durch sudo-Eskalation umgangen - -# blockierte beim ersten echten ISO-Build nach dem De-Root-Umzug (Debian- -# Referenzdistribution, siehe platform-docs/roadmap/ -# multi-distro-merkmal-workspace-creator.md Phase 1) das Wiederherstellen -# der SUID-Bits von sudo/passwd/su/mount etc. beim unsquashfs-Schritt in -# build_customer_iso.sh ("set_attributes: ... Operation not permitted"), -# obwohl der Prozess ECHTES root war. Dieselbe Unvereinbarkeit wie bei -# NoNewPrivileges oben - war schlicht beim urspruenglichen De-Root-Umzug -# uebersehen worden, weil kein echter ISO-Build danach getestet wurde. +# Gleiche Haertung wie kundenplattform.service (ADR-0011). Bis 03.10.2026 +# fehlten hier NoNewPrivileges, CapabilityBoundingSet/AmbientCapabilities und +# RestrictSUIDSGID, weil der Kunden-ISO-Bau per scoped sudo zu root +# eskalierte (ADR-0027). Seit build_customer_iso.sh die Kundendaten als +# eigene Squashfs-Schicht anlegt, braucht er keinerlei Privilegien mehr. +NoNewPrivileges=true +CapabilityBoundingSet= +AmbientCapabilities= +RestrictSUIDSGID=yes PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/opt/provisioning-server -# Arbeitsverzeichnis von build_customer_iso.sh (laeuft per sudo, erbt diese +# Arbeitsverzeichnis von build_customer_iso.sh (Kindprozess, erbt diese # Abschottung) auf anodes Datenplatte (03.10.2026, Befund B5) - '-': Unit # startet auch auf Systemen ohne dieses Verzeichnis. ReadWritePaths=-/srv/tuxflotte/build-tmp