ISO-Bau ohne sudo, Unit wieder voll gehaertet

build_customer_iso.sh braucht seit der Squashfs-Schicht kein root mehr:
sudo-Aufruf und sudoers-Datei entfallen, NoNewPrivileges,
CapabilityBoundingSet/AmbientCapabilities und RestrictSUIDSGID wieder an
(Ausnahmen aus ADR-0027 zurueckgenommen).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-03 16:19:43 +02:00
1 parent b8015567f3
commit 16d2de6c3a
4 files changed
+25 -54

No files matched your search

+8 -10
View File
@@ -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.
+7 -9
View File
@@ -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,
],
-8
View File
@@ -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 *
+10 -27
View File
@@ -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