Dev News Daily ENDE

Kubernetes 1.37 erlaubt endlich noexec beim Volume — das Problem war die Voreinstellung

Zwei Alpha-Funktionen in Kubernetes v1.37 schließen eine Lücke, die jahrelang offen sichtbar war: Bisher konnte ein Pod nicht verlangen, dass seine Volumes mit genau den Flags eingehängt werden, die jeder Härtungsleitfaden voraussetzt — noexec, nosuid, nodev. Container-Runtime und kubelet hängten Volumes ohne sie ein, und es gab kein Feld, um etwas anderes zu verlangen.

Die Folge sollte man deutlich aussprechen, denn sie untergräbt eine Kontrolle, die viele Teams für erledigt halten. Man kann readOnlyRootFilesystem: true setzen und behält trotzdem eine beschreibbare, ausführbare Fläche: jedes eingehängte Volume. Ein kompromittierter Prozess legt dort eine Datei ab, macht sie ausführbar und startet sie. emptyDir ist der schärfste Fall, weil es das mit Abstand häufigste beschreibbare Volume in echten Manifesten ist — und die Lücke steht in Kubernetes' eigener Prüfspur, unter anderem als Befund aus dem Sicherheitsaudit zu 1.24, ohne dass es ein Feld zur Abhilfe gegeben hätte.

Kubernetes 1.37 erlaubt endlich noexec beim Volume — das Problem war die Voreinstellung
Kubernetes 1.37 erlaubt endlich noexec beim Volume — das Problem war die Voreinstellung — Dev News Daily

Was jetzt tatsächlich im Manifest steht

VolumeBindMountOptions ergänzt bindMountOptions am Volume-Mount: Ein /tmp auf Basis von emptyDir lässt sich mit [noexec, nosuid] einhängen und hört auf, eine Startrampe zu sein. EmptyDirVolumeMode ergänzt einen Rechte-Modus am Volume selbst — mit mode: 0750 lesen und schreiben nur der vorgesehene Nutzer und dessen Gruppe, statt aller Sidecars im selben Pod. Beides ist in v1.37 Alpha und muss an API-Server und kubelet aktiviert werden.

Was das bedeutet

Interessant ist das Verhalten im Fehlerfall — und da widersprechen sich die beiden Funktionen. Lässt sich der Modus für emptyDir nicht umsetzen, fällt das kubelet auf 0777 zurück, also auf den freizügigsten Wert, und zwar stillschweigend. Bei bindMountOptions ist es umgekehrt: Der Scheduler nutzt die vom Knoten gemeldeten Fähigkeiten, um den Pod von Knoten fernzuhalten, deren Runtime die Flags nicht kennt, und ein kubelet, das so einen Pod doch bekommt, weist ihn ab, statt ihn ungeschützt zu starten.

Dieser Unterschied wiegt schwerer als beide Funktionen zusammen. Eine Sicherheitskontrolle, die sich leise selbst abschaltet, ist schlechter als gar keine: Das Manifest liest sich danach gehärtet, das Review geht durch, und nichts verrät, welche Knoten sie ignoriert haben. Wer den Rechte-Modus einsetzt, sollte ihn bis zur Reifung als Wunsch und nicht als Zusicherung behandeln — und auf dem Knoten nachsehen, nicht im YAML.

Zweitens: „Read-only root filesystem" verspricht weniger, als der Name nahelegt. Es betrifft die Image-Schichten, nicht die Volumes — und die Volumes sind der beschreibbare Raum, von Entwurf wegen. Erst die Mount-Flags machen daraus Daten statt Code.

Drittens die übliche Alpha-Rechnung. Beide Gates sind standardmäßig aus, ein Cluster braucht also eine kubelet-Änderung und nicht nur eine Manifest-Änderung — in verwalteten Clustern ist das die Entscheidung des Anbieters, nicht Ihre. Der praktische Schritt in diesem Monat: jedes beschreibbare Volume in den eigenen Namespaces auflisten und festhalten, welches davon noexec bräuchte, sobald das Flag verfügbar ist. Diese Inventur ist die eigentliche Arbeit, und sie hängt an keinem Feature-Gate.

Getrieben von SIG Node und SIG Storage.