Mit Version 256 hat systemd run0
eingeführt. Lennart Poettering beschreibt run0
als Alternative zu sudo und erklärt auf Mastodon zugleich, was in seinen Augen das Problem mit sudo ist.
In diesem Blogeintrag wollen wir aber nicht auf die Stärken oder Schwächen von sudo eingehen, sondern uns run0
einmal etwas genauer anschauen und es als sudo-Alternative verwenden.
Anders als sudo verwendet run0
weder die Konfigurationsdatei /etc/sudoers
, noch ein SUID-Bit zur Erweiterung der User-Berechtigungen. Im Hintergrund nutzt es systemd-run
zum Start neuer Prozesse, welches bereits seit einigen Jahren in systemd zu finden ist.
PolKit kommt zum Einsatz, wenn es darum geht zu prüfen, ob ein User auch entsprechende Berechtigungen besitzt, run0
zu verwenden. Hierbei können alle Regeln verwendet werden, die die Konfiguration von PolKit hergeben. In unserem Beispiel werden wir uns auf eine einfache Variante konzentrieren.
Versuchsaufbau
Für unser Beispiel verwenden wir eine t2.micro
EC2-Instanz mit Debian Bookworm. Da run0
erst in systemd Version 256 Einzug gehalten hat und Debian Bookworm zum aktuellen Zeitpunkt noch mit Version 252 ausgeliefert wird, müssen wir zunächst das Debian Testing Repository hinzufügen.
❯ ssh admin@2a05:d014:ac8:7e00:c4f4:af36:3938:206e … admin@ip-172-31-15-135:~$ sudo su - root@ip-172-31-15-135:~# cat < /etc/apt/sources.list.d/testing.list > deb https://deb.debian.org/debian testing main > EOF root@ip-172-31-15-135:~# apt update Get:1 file:/etc/apt/mirrors/debian.list Mirrorlist [38 B] Get:5 file:/etc/apt/mirrors/debian-security.list Mirrorlist [47 B] Get:7 https://deb.debian.org/debian testing InRelease [169 kB] Get:2 https://cdn-aws.deb.debian.org/debian bookworm InRelease [151 kB] … Fetched 41.3 MB in 6s (6791 kB/s) Reading package lists... Done Building dependency tree... Done Reading state information... Done 299 packages can be upgraded. Run 'apt list --upgradable' to see them. root@ip-172-31-15-135:~# apt-cache policy systemd systemd: Installed: 252.17-1~deb12u1 Candidate: 256.1-2 Version table: 256.1-2 500 500 https://deb.debian.org/debian testing/main amd64 Packages 254.5-1~bpo12+3 100 100 mirror+file:/etc/apt/mirrors/debian.list bookworm-backports/main amd64 Packages 252.22-1~deb12u1 500 500 mirror+file:/etc/apt/mirrors/debian.list bookworm/main amd64 Packages *** 252.17-1~deb12u1 100 100 /var/lib/dpkg/status root@ip-172-31-15-135:~# apt-get install systemd … root@ip-172-31-15-135:~# dpkg -l | grep systemd ii libnss-resolve:amd64 256.1-2 amd64 nss module to resolve names via systemd-resolved ii libpam-systemd:amd64 256.1-2 amd64 system and service manager - PAM module ii libsystemd-shared:amd64 256.1-2 amd64 systemd shared private library ii libsystemd0:amd64 256.1-2 amd64 systemd utility library ii systemd 256.1-2 amd64 system and service manager ii systemd-cryptsetup 256.1-2 amd64 Provides cryptsetup, integritysetup and veritysetup utilities ii systemd-resolved 256.1-2 amd64 systemd DNS resolver ii systemd-sysv 256.1-2 amd64 system and service manager - SysV compatibility symlinks ii systemd-timesyncd 256.1-2 amd64 minimalistic service to synchronize local time with NTP servers root@ip-172-31-15-135:~# reboot …
Zum initialen Login wird der User admin
verwendet. Dieser User wurde durch cloud-init
bereits in der Datei /etc/sudoers.d/90-cloud-init-users
hinterlegt und darf demnach ohne Passwortabfrage beliebige sudo-Kommandos ausführen.
sudo cat /etc/sudoers.d/90-cloud-init-users # Created by cloud-init v. 22.4.2 on Thu, 27 Jun 2024 09:22:48 +0000 # User rules for admin admin ALL=(ALL) NOPASSWD:ALL
Analog zu sudo wollen wir nun run0
für den User admin
freischalten.
Ohne weitere Konfiguration erhält der User admin
einen Login-Prompt, bei dem er nach dem root
-Passwort gefragt wird. Dabei handelt es sich um das Standardverhalten von PolKit.
admin@ip-172-31-15-135:~$ run0
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ==== Authentication is required to manage system services or other units. Authenticating as: Debian (admin) Password:
Da dies nicht dem von uns gewünschten Verhalten entspricht, müssen wir in Form einer PolKit-Regel ein wenig nachhelfen. Zusätzliche PolKit Regeln werden unter /etc/polkit-1/rules.d/
abgelegt.
root@ip-172-31-15-135:~# cat < /etc/polkit-1/rules.d/99-run0.rules polkit.addRule(function(action, subject) { if (action.id = "org.freedesktop.systemd1.manage-units") { if (subject.user === "admin") { return polkit.Result.YES; } } }); > EOF
Die verwendete Regel ist dabei wie folgt aufgebaut: Zunächst wird überprüft, ob es sich bei der aufgeführten action um org.freedesktop.systemd1.manage-units
handelt. Ist das der Fall, wird geprüft, ob es sich bei dem ausführenden User um den User admin
handelt. Sind beide Voraussetzungen erfüllt, gibt unsere Regel „YES“ zurück, was bedeutet, dass keine weitere Prüfung (z.B. Passwortabfrage) nötig ist.
Alternativ hierzu könnte auch geprüft werden, ob der ausführende User einer bestimmten Gruppe angehört, wie z.B. admin
oder sudo
(if (subject.isInGroup("admin")
). Auch wäre es denkbar, den Benutzer nach seinem eigenen Passwort zu fragen anstelle des root
-Passworts.
Die neue Regel wird von PolKit automatisch eingelesen und kann sofort verwendet werden. Via journalctl -u polkit
kann geprüft werden, ob es etwaige Fehler beim Einlesen der neuen Regeln gab. Nach der Konfiguration von PolKit darf der User admin
nun analog zu unserer initialen sudo-Konfiguration run0
ausführen.
Prozessaufbau
Im nachfolgenden Listing wird ersichtlich, worin der Unterschied des Call-Stacks zwischen sudo und run0
liegt. Während im Falle von sudo jeweils eigene Child-Prozesse gestartet werden, startet run0
einen neuen Prozess via systemd-run
.
root@ip-172-31-15-135:~# sudo su - root@ip-172-31-15-135:~# ps fo tty,ruser,ppid,pid,sess,cmd TT RUSER PPID PID SESS CMD pts/2 admin 1484 1514 1484 sudo su - pts/0 admin 1514 1515 1515 \_ sudo su - pts/0 root 1515 1516 1515 \_ su - pts/0 root 1516 1517 1515 \_ -bash pts/0 root 1517 1522 1515 \_ ps fo tty,ruser,ppid,pid,sess,cmd
admin@ip-172-31-15-135:~$ run0 root@ip-172-31-15-135:/home/admin# ps fo tty,ruser,ppid,pid,sess,cmd TT RUSER PPID PID SESS CMD pts/0 root 1 1562 1562 -/bin/bash pts/0 root 1562 1567 1562 \_ ps fo tty,ruser,ppid,pid,sess,cmd
Fazit und Anmerkung
Wie das oben stehende Beispiel gezeigt hat, kann run0
generell als einfache sudo-Alternative verwendet werden und bietet dabei einige sicherheitsrelevante Vorteile. Falls run0
sich gegenüber sudo durchsetzt, wird dies allerdings nicht innerhalb des nächsten Jahres geschehen. Einigen Distributionen fehlt stand jetzt schlicht eine ausreichend aktuelle systemd-Version. Hinzukommt, dass die Konfiguration von PolKit für einige Admins nicht zu den täglichen Aufgaben gehört und hier erst Know-How aufgebaut werden muss, um etwaige vorhandene sudo-„Konstrukte“ zu überführen.
Zudem sollte ein entscheidender Vorteil von run0
nicht außen vor bleiben: Standardmäßig färbt es den Hintergrund rot! 😉