-
Notifications
You must be signed in to change notification settings - Fork 0
/
remote-unlock.sh
executable file
·95 lines (83 loc) · 2.34 KB
/
remote-unlock.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/bin/bash
#
# Remotely unlock LUKS-encrypted disks.
#
# Meant for use together with dropbear-initramfs which spawns an SSH server in
# initramfs which can be used to unlock disks. This script reads passwords with
# `pass` (password-store) from paths in the form of `hardware/disks/$UUID`.
#
# UUIDs are automatically extraced from the crypttab, so it should be pretty
# simple to set up.
#
# It's adviced to set up SSH to use `ControlMaster auto` and `ControlPersist 2m`
# to avoid having to re-open the SSH connection on evey call. Alternatively this
# script could be improved to use the same SSH connection for all commands.
#
# Tested and working on Ubuntu 18.04 (remote) and Debian 9 (local).
#
# shellcheck disable=SC2029
function usage() {
cat >&2 <<EOF
Usage: ${0} [-p|--partial] [email protected]
EOF
}
declare -i partial=0
declare -i no_kill=0
declare disks_file
while [[ $1 =~ ^- ]]; do
case $1 in
--partial|-p)
partial=1
;;
--no-kill)
no_kill=1
;;
--disks)
shift
disks_file="${1}"
;;
*)
usage
exit 255
;;
esac
shift
done
host=$1
if [[ -n "${disks_file}" ]]; then
disks=$(cat "${disks_file}")
else
disks=$(ssh "$host" "cat /conf/conf.d/cryptroot")
fi
targets=()
for crypt in $disks; do
# extrance target and UUID
if [[ -n "${disks_file}" ]]; then
uuid="${crypt}"
target="disk-${crypt}"
else
[[ "$crypt" =~ ^target=([^,]+),source=UUID=([^,]+), ]]
target="${BASH_REMATCH[1]}"
uuid="${BASH_REMATCH[2]}"
fi
if ssh "$host" "test -b '/dev/mapper/$target'"; then
# disk already unlocked, continue
continue
fi
targets=("$target")
echo "Unlocking target: ${target} (${uuid})"
pass show "hardware/disks/$uuid" | head -n1 | head -c -1 | \
ssh "$host" "/sbin/cryptsetup --key-file - luksOpen /dev/disk/by-uuid/$uuid $target"
done
# ensure disks did get unlocked before killing cryptsetup and resuming boot
for target in ${targets[*]}; do
if test -b "/dev/mapper/$target"; then
>&2 echo "Failed to unlock disk '$target'"
[[ $partial -eq 0 ]] && exit 1
fi
done
if [[ $no_kill -eq 0 ]]; then
# find the pid for cryptroot so we can kill it and continue booting
cryptroot_pid=$(ssh "$host" ps | grep '{cryptroot} /bin/sh /scripts/local-top/cryptroot' | grep -v grep | sed -r 's/^ *([0-9]+) .*?/\1/')
ssh "$host" kill "$cryptroot_pid"
fi