Start / Linux & Infrastructure / LUKS-Verschlüsselung: Automatisierung mit sudo & Polkit

LUKS-Verschlüsselung: Automatisierung mit sudo & Polkit

📢 LUKS automatisieren – Nahtlose Verschlüsselung & Der Kampf gegen sudo

Fun Fact – Ich habe ein Chat-Fenster mit ChatGPT genutzt, um diese Lösung zu finden. Am Ende habe ich ihn gebeten, das Ziel meiner Fragen zu verstehen, und die folgende Eingabe verwendet, um diesen Beitrag zu erstellen – wow (ich liebe es, wie er meine Rechtschreibfehler ignoriert ;.))


Das Problem

Ich war schon immer ein Fan von Automatisierung – keine unnötigen manuellen Schritte, keine Reibungsverluste, keine Überraschungen.
Beim Umgang mit LUKS-verschlüsseltem Speicher und Samba-Freigaben hatte ich ein klares Ziel:

✅ Das Ein- und Aushängen vollständig automatisieren, ohne manuell Passwörter eingeben zu müssen

Eigentlich habe ich ein anderes Skript, das das Passwort über eine HTTPS-Anfrage abruft, es handelt sich also um eine Fernverriegelung/-entriegelung. Das Skript ist ein einfacher Webserver, du weißt ja, wie das geht 🙂

Das klingt einfach? War es aber nicht.

Die erste Idee: Einfach udisksctl

Zunächst udisksctl schien es perfekt zu sein. Ein einfaches:

udisksctl unlock -b /dev/sdf2

würde mein LUKS-Volume entsperren, und:

udisksctl lock -b /dev/disk/by-uuid/XXXX

sollte es sperren. Kein Root, kein sudo.

Doch dann kam die erste Hürde: Es wurde nach einem Passwort gefragt – selbst bei Ausführung über ein Skript.
💬 „Moment mal, warum braucht udisksctl Root-Rechte, um ein Gerät zu sperren, aber nicht, um es zu entsperren?“

Willkommen bei Polkit & UDisks2 – einer Welt undokumentierter Sonderfälle.

Polkit: Das Kaninchenloch

Mein nächster Schritt? Polkit-Regeln.
Das sollte doch eine passwortlose Ausführung ermöglichen, oder?

polkit.addRule(function(action, subject) {
    if ((action.id == "org.freedesktop.udisks2.encrypted-unlock" ||
         action.id == "org.freedesktop.udisks2.lock-device") &&
        subject.isInGroup("disk")) {
        return polkit.Result.YES;
    }
});

Ergebnis? Es wird immer noch nach einem Passwort gefragt.
Beim Debuggen mit journalctl -f | grep polkit zeigte mir, dass einige Aktionen immer noch abgelehnt wurden.
Ein Schritt vorwärts, zwei Schritte zurück.

Das eigentliche Problem: fuser, Samba & belegte Geräte

Beim Aushängen eines LUKS-Volumes geht es nicht nur darum, E/A-Vorgänge zu stoppen – es geht darum, alle verbleibenden Verbindungen zu trennen.

  • Samba hielt immer noch offene Dateien auf meinem gemounteten LUKS-Laufwerk.
  • udisksctl lock schlug mit der Meldung „Gerät oder Ressource belegt“ fehl.
  • umount -l Das reichte nicht aus – denn smbd im Hintergrund lief.

Ich musste die Prozesse vor dem Aushängen zwangsweise beenden.

sudo smbcontrol smbd close-share LUKSShare
sudo fuser -km /data/check
sudo udisksctl unmount -b /dev/mapper/my_luks_drive

💡 Lektion gelernt: Beim Sperren eines LUKS-Geräts geht es nicht nur um die Festplatte – es geht um alle Dienste, die sie nutzen.

Der Kompromiss: Selektiv sudo

An diesem Punkt hatte ich die Wahl:

  1. Mich noch tiefer in Polkit einarbeiten und mich durch weitere Regeln hacken.
  2. Die Realität akzeptieren und sudo selektiv zulassen – aber auf kontrollierte Weise.

Ich entschied mich für Option 2.
Mit visudohabe ich nur die erforderlichen Befehle zugelassen, die ohne Passwort ausgeführt werden dürfen:

youruser ALL=(ALL) NOPASSWD: /usr/bin/udisksctl lock -b /dev/disk/by-uuid/*,                              /usr/bin/smbcontrol smbd close-share *,                              /usr/bin/fuser -km /data/check

Dadurch blieb die Sicherheit gewährleistet, während die Automatisierung reibungslos funktionierte.

Die endgültige Konfiguration

Am Ende dieser Reise hatte ich ein voll funktionsfähiges System, das:

  • LUKS automatisch mountet.
  • es aushängt und sperrt, ohne dass manuell sudo erforderlich ist.
  • Samba-Freigaben ordnungsgemäß schließt, um device busy-Fehler zu vermeiden.
  • sudo“ nur für das absolut Nötigste verwendet (jedoch ohne Passwortabfragen).

Letzte Änderungen

Nachfolgend findest du die endgültigen geänderten Dateien:

  • 📂 Skripte zum Ein- und Aushängen
    (Automatisierung des gesamten LUKS-Lebenszyklus)
  • 📂 Datei „sudoers
    (ermöglicht selektive passwortfreie sudo )
  • 📂 Polkit-Regeln
    (die notwendigen Anpassungen, damit es funktioniert)

🚀 Fazit

Hier ging es nicht nur darum, sudozu vermeiden. Es ging darum, Linux-Sicherheit, Prozessmanagement und Automatisierung zu verstehen.
Würde ich es wieder genauso machen? Wahrscheinlich.

Würde ich es jemand anderem empfehlen?
💡 „Nur, wenn du dich wirklich für das Debuggen von Linux-Interna begeisterst.“

🚀 Die endgültige Konfiguration findest du unten. Lass mich wissen, wenn du Möglichkeiten siehst, sie noch übersichtlicher zu gestalten.

💡 Dieser Beitrag richtet sich an alle, die echte, praktische Automatisierung wollen, ohne dabei Kompromisse bei der Sicherheit einzugehen.
Wenn du schon mal denselben Kampf ausgefochten hast, hinterlasse einen Kommentar. 🔥

Einbinden

 1 #!/bin/bash
 2
 3 # Check if password is provided
 4 if [ -z "$1" ]; then
 5     echo "Usage: $0 <password>"
 6     exit 1
 7 fi
 8
 9 password="$1"
10 device="/dev/sdx1"   # Your LUKS partition
12 luks_name="luks-xxx"  # Custom device name
13
14 # Unlock LUKS partition with a fixed name
15 udisksctl unlock --block-device "$device" --key-file <(echo -n "$password")
16
17 sleep 1
18 # Mount the unlocked LUKS volume
19 udisksctl mount -b "/dev/mapper/$luks_name"

Unmount

#!/bin/bash
 2
 3 # Configuration: Set your LUKS device details
 4 LUKS_UUID="luks-xxxx" 
 5 LUKS_MAPPER="/dev/mapper/luks-xxxx"
 6 MOUNT_PATH="//mount_point"  # Mount point
 7 SAMBA_SHARE_NAME="smb_share"  # Samba share name
 8 DEVICE="/dev/sdx1"
 9
10 # Close active Samba connections
11 echo "Closing Samba share: $SAMBA_SHARE_NAME..."
12 sudo smbcontrol smbd close-share "$SAMBA_SHARE_NAME"
13
14 sleep 1
15
16
17 # Unmount the LUKS volume
18 echo "Unmounting LUKS volume..."
19 sudo udisksctl unmount -b "$LUKS_MAPPER" || umount -l "$LUKS_MAPPER"
20
21
22 # Kill all processes using the mount point
23 #echo "Killing active processes on $MOUNT_PATH..."
24 #sudo fuser -km "$MOUNT_PATH"
25
26 # Wait for system to release resources
27 sleep 1
28
29 # Lock the LUKS device
30 echo "Locking LUKS device..."
31 sudo udisksctl lock -b "$DEVICE"
32
33 if [ $? -eq 0 ]; then
34     echo "LUKS device successfully locked!"
35     exit 0
36 else
37     echo "Failed to lock LUKS device."
38     exit 1
39 fi
40
41 sleep 1
42
43 echo "Set HD to sleep mode"
44 # sudo hdparm -y "$DEVICE

Sudo-Datei:

docbox ALL=(ALL) NOPASSWD: /usr/bin/udisksctl lock -b /dev/sdf2 , \
                            /usr/bin/udisksctl unmount -b /dev/mapper/*, \
                            /usr/bin/smbcontrol smbd close-share *, \
                            /usr/bin/fuser -km *, \
                            /usr/sbin/hdparm -y /dev/sdx1

Polkit-Dateien:

polkit.addRule(function(action, subject) {
    if ((action.id == "org.freedesktop.udisks2.encrypted-unlock" ||
         action.id == "org.freedesktop.udisks2.filesystem-mount" ||
         action.id == "org.freedesktop.udisks2.filesystem-unmount-others" ||
         action.id == "org.freedesktop.udisks2.unmount" ||
         action.id == "org.freedesktop.udisks2.lock-device" ||
         action.id == "org.freedesktop.udisks2.encrypted-unlock-other-seat") &&
        subject.isInGroup("disk")) {
        return polkit.Result.YES;
    }
});

Markiert: