Blame SOURCES/0008-Use-one-clevis-luks-askpass-per-device.patch

95204d
From 3250784e99016d9f920892dbb1438b9e76fb210b Mon Sep 17 00:00:00 2001
95204d
From: Sergio Correia <scorreia@redhat.com>
95204d
Date: Sun, 10 May 2020 15:57:23 -0300
95204d
Subject: [PATCH 8/8] Use one clevis-luks-askpass per device
95204d
95204d
This should improve the reliability of the boot unlocking, especially
95204d
when unlocking multiple devices upon boot.
95204d
95204d
It also greatly simplifies the configuration, as there is no need to
95204d
enable any systemd units manually nor add _netdev to either fstab or
95204d
crypttab.
95204d
---
95204d
 src/luks/clevis-luks-common-functions         |  8 ++
95204d
 src/luks/clevis-luks-unlockers.7.adoc         | 16 +---
95204d
 src/luks/systemd/clevis-luks-askpass          | 81 ++++++-------------
95204d
 src/luks/systemd/clevis-luks-askpass.path     | 10 ---
95204d
 .../systemd/clevis-luks-askpass.service.in    |  8 --
95204d
 src/luks/systemd/clevis-luks-askpass@.path    | 12 +++
95204d
 .../systemd/clevis-luks-askpass@.service.in   |  8 ++
95204d
 .../systemd/dracut/clevis/module-setup.sh.in  | 23 ++++++
95204d
 src/luks/systemd/meson.build                  |  6 +-
95204d
 9 files changed, 80 insertions(+), 92 deletions(-)
95204d
 delete mode 100644 src/luks/systemd/clevis-luks-askpass.path
95204d
 delete mode 100644 src/luks/systemd/clevis-luks-askpass.service.in
95204d
 create mode 100644 src/luks/systemd/clevis-luks-askpass@.path
95204d
 create mode 100644 src/luks/systemd/clevis-luks-askpass@.service.in
95204d
95204d
diff --git a/src/luks/clevis-luks-common-functions b/src/luks/clevis-luks-common-functions
95204d
index 5b515ad..c9d712a 100644
95204d
--- a/src/luks/clevis-luks-common-functions
95204d
+++ b/src/luks/clevis-luks-common-functions
95204d
@@ -555,3 +555,11 @@ clevis_luks_restore_dev() {
95204d
     fi
95204d
     return 0
95204d
 }
95204d
+
95204d
+# clevis_is_luks_device_by_uuid_open() checks whether the LUKS device with
95204d
+# given UUID is open.
95204d
+clevis_is_luks_device_by_uuid_open() {
95204d
+    local LUKS_UUID="${1}"
95204d
+    [ -z "${LUKS_UUID}" ] && return 1
95204d
+    test -b /dev/disk/by-id/dm-uuid-*"${LUKS_UUID//-/}"*
95204d
+}
95204d
diff --git a/src/luks/clevis-luks-unlockers.7.adoc b/src/luks/clevis-luks-unlockers.7.adoc
95204d
index 161b73a..e8d47ba 100644
95204d
--- a/src/luks/clevis-luks-unlockers.7.adoc
95204d
+++ b/src/luks/clevis-luks-unlockers.7.adoc
95204d
@@ -26,7 +26,7 @@ You can unlock a LUKS volume manually using the following command:
95204d
 
95204d
 For more information, see link:clevis-luks-unlock.1.adoc[*clevis-luks-unlock*(1)].
95204d
 
95204d
-== EARLY BOOT UNLOCKING
95204d
+== BOOT UNLOCKING
95204d
 
95204d
 If Clevis integration does not already ship in your initramfs, you may need to
95204d
 rebuild your initramfs with this command:
95204d
@@ -34,23 +34,13 @@ rebuild your initramfs with this command:
95204d
     $ sudo dracut -f
95204d
 
95204d
 Once Clevis is integrated into your initramfs, a simple reboot should unlock
95204d
-your root volume. Note, however, that early boot integration only works for the
95204d
-root volume. Non-root volumes should use the late boot unlocker.
95204d
+your clevis-bound volumes. Root volumes will be unlocked in early-boot, while the
95204d
+remaining volumes will be unlocked after dracut switch-root.
95204d
 
95204d
 Dracut will bring up your network using DHCP by default. If you need to specify
95204d
 additional network parameters, such as static IP configuration, please consult
95204d
 the dracut documentation.
95204d
 
95204d
-== LATE BOOT UNLOCKING
95204d
-
95204d
-You can enable late boot unlocking by executing the following command:
95204d
-
95204d
-    $ sudo systemctl enable clevis-luks-askpass.path
95204d
-
95204d
-After a reboot, Clevis will attempt to unlock all *_netdev* devices listed in
95204d
-*/etc/crypttab* when systemd prompts for their passwords. This implies that
95204d
-systemd support for *_netdev* is required.
95204d
-
95204d
 == DESKTOP UNLOCKING
95204d
 
95204d
 When the udisks2 unlocker is installed, your GNOME desktop session should
95204d
diff --git a/src/luks/systemd/clevis-luks-askpass b/src/luks/systemd/clevis-luks-askpass
95204d
index 9fea6aa..20294e5 100755
95204d
--- a/src/luks/systemd/clevis-luks-askpass
95204d
+++ b/src/luks/systemd/clevis-luks-askpass
95204d
@@ -19,96 +19,61 @@
95204d
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
95204d
 #
95204d
 
95204d
-UUID=cb6e8904-81ff-40da-a84a-07ab9ab5715e
95204d
+. clevis-luks-common-functions
95204d
 
95204d
 shopt -s nullglob
95204d
 
95204d
 path=/run/systemd/ask-password
95204d
-while getopts ":lp:" o; do
95204d
+while getopts ":lp:u:" o; do
95204d
     case "$o" in
95204d
     l) loop=true;;
95204d
     p) path="$OPTARG";;
95204d
+    u) device_uuid=$OPTARG;;
95204d
+    *) ;;
95204d
     esac
95204d
 done
95204d
 
95204d
-luks1_decrypt() {
95204d
-    luksmeta load "$@" \
95204d
-        | clevis decrypt
95204d
-
95204d
-    local rc
95204d
-    for rc in "${PIPESTATUS[@]}"; do
95204d
-        [ $rc -eq 0 ] || return $rc
95204d
-    done
95204d
-    return 0
95204d
-}
95204d
-
95204d
-luks2_jwe() {
95204d
-    # jose jwe fmt -c outputs extra \n, so clean it up
95204d
-    cryptsetup token export "$@" \
95204d
-        | jose fmt -j- -Og jwe -o- \
95204d
-        | jose jwe fmt -i- -c \
95204d
-        | tr -d '\n'
95204d
-
95204d
-    local rc
95204d
-    for rc in "${PIPESTATUS[@]}"; do
95204d
-        [ $rc -eq 0 ] || return $rc
95204d
-    done
95204d
-    return 0
95204d
-}
95204d
-
95204d
 while true; do
95204d
     todo=0
95204d
 
95204d
     for question in "$path"/ask.*; do
95204d
-        metadata=false
95204d
         unlocked=false
95204d
         d=
95204d
         s=
95204d
 
95204d
-        while read line; do
95204d
+        while read -r line; do
95204d
             case "$line" in
95204d
                 Id=cryptsetup:*) d="${line##Id=cryptsetup:}";;
95204d
                 Socket=*) s="${line##Socket=}";;
95204d
             esac
95204d
         done < "$question"
95204d
 
95204d
-        [ "$d" ] && [ "$s" ] || continue
95204d
+        [ -b "${d}" ] || continue
95204d
+        [ -S "${s}" ] || continue
95204d
 
95204d
-        if cryptsetup isLuks --type luks1 "$d"; then
95204d
-            # If the device is not initialized, sliently skip it.
95204d
-            luksmeta test -d "$d" || continue
95204d
-
95204d
-            while read -r slot state uuid; do
95204d
-                [ "$state" == "active" ] || continue
95204d
-                [ "$uuid" == "$UUID" ] || continue
95204d
-                metadata=true
95204d
-
95204d
-                if pt="$(luks1_decrypt -d "$d" -s "$slot" -u "$UUID")"; then
95204d
-                    echo -n "+$pt" | ncat -U -u --send-only "$s"
95204d
-                    unlocked=true
95204d
-                    break
95204d
-                fi
95204d
-            done < <(luksmeta show -d "$d")
95204d
-        elif cryptsetup isLuks --type luks2 "$d"; then
95204d
-            while read -r id; do
95204d
-                jwe="$(luks2_jwe --token-id "$id" "$d")" \
95204d
-                    || continue
95204d
-                metadata=true
95204d
+        if [ -n "${device_uuid}" ]; then
95204d
+            uuid="$(cryptsetup luksUUID "${d}")"
95204d
+            [ "${uuid}" != "${device_uuid}" ] && todo=1 && continue
95204d
+        fi
95204d
 
95204d
-                if pt="$(echo -n "$jwe" | clevis decrypt)"; then
95204d
-                    echo -n "+$pt" | ncat -U -u --send-only "$s"
95204d
-                    unlocked=true
95204d
-                    break
95204d
-                fi
95204d
-            done < <(cryptsetup luksDump "$d" | sed -rn 's|^\s+([0-9]+): clevis|\1|p')
95204d
+        if pt="$(clevis_luks_unlock_device "${d}")"; then
95204d
+            echo -n "+$pt" | ncat -U -u --send-only "$s"
95204d
+            unlocked=true
95204d
         fi
95204d
 
95204d
-        [ "$metadata" == true ] || continue
95204d
+        [ -n "${device_uuid}" ] && [ "${unlocked}" == true ] && break
95204d
         [ "$unlocked" == true ] && continue
95204d
         ((todo++))
95204d
     done
95204d
 
95204d
-    if [ $todo -eq 0 ] || [ "$loop" != true ]; then
95204d
+    if [ -n "${device_uuid}" ]; then
95204d
+        [ ! -b /dev/disk/by-uuid/"${device_uuid}" ] && break
95204d
+        if clevis_is_luks_device_by_uuid_open "${device_uuid}"; then
95204d
+            break
95204d
+        fi
95204d
+    fi
95204d
+
95204d
+    if [ "$todo" -eq 0 ] || [ "$loop" != true ]; then
95204d
         break;
95204d
     fi
95204d
 
95204d
diff --git a/src/luks/systemd/clevis-luks-askpass.path b/src/luks/systemd/clevis-luks-askpass.path
95204d
deleted file mode 100644
95204d
index a4d01ba..0000000
95204d
--- a/src/luks/systemd/clevis-luks-askpass.path
95204d
+++ /dev/null
95204d
@@ -1,10 +0,0 @@
95204d
-[Unit]
95204d
-Description=Clevis systemd-ask-password Watcher
95204d
-Before=remote-fs-pre.target
95204d
-Wants=remote-fs-pre.target
95204d
-
95204d
-[Path]
95204d
-PathChanged=/run/systemd/ask-password
95204d
-
95204d
-[Install]
95204d
-WantedBy=remote-fs.target
95204d
diff --git a/src/luks/systemd/clevis-luks-askpass.service.in b/src/luks/systemd/clevis-luks-askpass.service.in
95204d
deleted file mode 100644
95204d
index 2c6bbed..0000000
95204d
--- a/src/luks/systemd/clevis-luks-askpass.service.in
95204d
+++ /dev/null
95204d
@@ -1,8 +0,0 @@
95204d
-[Unit]
95204d
-Description=Clevis LUKS systemd-ask-password Responder
95204d
-Requires=network-online.target
95204d
-After=network-online.target
95204d
-
95204d
-[Service]
95204d
-Type=oneshot
95204d
-ExecStart=@libexecdir@/clevis-luks-askpass -l
95204d
diff --git a/src/luks/systemd/clevis-luks-askpass@.path b/src/luks/systemd/clevis-luks-askpass@.path
95204d
new file mode 100644
95204d
index 0000000..3f23665
95204d
--- /dev/null
95204d
+++ b/src/luks/systemd/clevis-luks-askpass@.path
95204d
@@ -0,0 +1,12 @@
95204d
+[Unit]
95204d
+Description=Clevis systemd-ask-password Watcher for %i
95204d
+DefaultDependencies=no
95204d
+Conflicts=shutdown.target
95204d
+Before=basic.target shutdown.target
95204d
+
95204d
+[Path]
95204d
+DirectoryNotEmpty=/run/systemd/ask-password
95204d
+MakeDirectory=yes
95204d
+
95204d
+[Install]
95204d
+WantedBy=basic.target
95204d
diff --git a/src/luks/systemd/clevis-luks-askpass@.service.in b/src/luks/systemd/clevis-luks-askpass@.service.in
95204d
new file mode 100644
95204d
index 0000000..4165ec5
95204d
--- /dev/null
95204d
+++ b/src/luks/systemd/clevis-luks-askpass@.service.in
95204d
@@ -0,0 +1,8 @@
95204d
+[Unit]
95204d
+Description=Clevis LUKS systemd-ask-password Responder for luks-%i
95204d
+DefaultDependencies=no
95204d
+Conflicts=shutdown.target
95204d
+Before=shutdown.target
95204d
+
95204d
+[Service]
95204d
+ExecStart=@libexecdir@/clevis-luks-askpass -u %i
95204d
diff --git a/src/luks/systemd/dracut/clevis/module-setup.sh.in b/src/luks/systemd/dracut/clevis/module-setup.sh.in
95204d
index abc79b3..1a0d6f7 100755
95204d
--- a/src/luks/systemd/dracut/clevis/module-setup.sh.in
95204d
+++ b/src/luks/systemd/dracut/clevis/module-setup.sh.in
95204d
@@ -23,6 +23,24 @@ depends() {
95204d
     return 255
95204d
 }
95204d
 
95204d
+configure_passwd_watchers() {
95204d
+    if ! command -v systemctl >/dev/null; then
95204d
+        return 1
95204d
+    fi
95204d
+
95204d
+    find /etc/systemd/system/ -name "clevis-luks-askpass*" -exec rm -f {} \;
95204d
+
95204d
+    local uuid
95204d
+    for dev in $(lsblk -p -n -s -r \
95204d
+                 | awk '$6 == "crypt" { getline; print $1 }' | sort -u); do
95204d
+        uuid=$(cryptsetup luksUUID "${dev}")
95204d
+
95204d
+        if clevis luks list -d "${dev}" >/dev/null 2>/dev/null; then
95204d
+            systemctl enable "clevis-luks-askpass@${uuid}.path" 2>/dev/null
95204d
+        fi
95204d
+    done
95204d
+}
95204d
+
95204d
 install() {
95204d
     inst_hook initqueue/online 60 "$moddir/clevis-hook.sh"
95204d
     inst_hook initqueue/settled 60 "$moddir/clevis-hook.sh"
95204d
@@ -30,6 +48,10 @@ install() {
95204d
     inst_multiple \
95204d
 	/etc/services \
95204d
         @libexecdir@/clevis-luks-askpass \
95204d
+        clevis-luks-common-functions \
95204d
+        head \
95204d
+        grep \
95204d
+        sed \
95204d
         clevis-decrypt \
95204d
         cryptsetup \
95204d
         luksmeta \
95204d
@@ -38,5 +60,6 @@ install() {
95204d
         jose \
95204d
         ncat
95204d
 
95204d
+    configure_passwd_watchers
95204d
     dracut_need_initqueue
95204d
 }
95204d
diff --git a/src/luks/systemd/meson.build b/src/luks/systemd/meson.build
95204d
index 369e7f7..334e84c 100644
95204d
--- a/src/luks/systemd/meson.build
95204d
+++ b/src/luks/systemd/meson.build
95204d
@@ -6,13 +6,13 @@ if systemd.found()
95204d
   unitdir = systemd.get_pkgconfig_variable('systemdsystemunitdir')
95204d
 
95204d
   configure_file(
95204d
-    input: 'clevis-luks-askpass.service.in',
95204d
-    output: 'clevis-luks-askpass.service',
95204d
+    input: 'clevis-luks-askpass@.service.in',
95204d
+    output: 'clevis-luks-askpass@.service',
95204d
     install_dir: unitdir,
95204d
     configuration: data,
95204d
   )
95204d
 
95204d
-  install_data('clevis-luks-askpass.path', install_dir: unitdir)
95204d
+  install_data('clevis-luks-askpass@.path', install_dir: unitdir)
95204d
   install_data('clevis-luks-askpass', install_dir: libexecdir)
95204d
 else
95204d
   warning('Will not install systemd support due to missing dependencies!')
95204d
-- 
95204d
2.18.4
95204d