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