diff options
| author | Josh Rahm <joshuarahm@gmail.com> | 2023-02-25 12:06:25 -0700 |
|---|---|---|
| committer | Josh Rahm <joshuarahm@gmail.com> | 2023-02-25 12:06:25 -0700 |
| commit | 1a669da23bea9bb8c74cafd92e0819249ff13493 (patch) | |
| tree | 65bca35b435ed68de7defe509f5697a782fb6d0d | |
| parent | 10c1fe4071f248e976d920b3ca29971670893f33 (diff) | |
| download | acquire-key-over-ssh-1a669da23bea9bb8c74cafd92e0819249ff13493.tar.gz acquire-key-over-ssh-1a669da23bea9bb8c74cafd92e0819249ff13493.tar.bz2 acquire-key-over-ssh-1a669da23bea9bb8c74cafd92e0819249ff13493.zip | |
Add ability to acquire the key from a separate drive and shred the key when finished.
| -rw-r--r-- | example.conf | 45 | ||||
| -rwxr-xr-x | module-setup.sh | 6 | ||||
| -rwxr-xr-x | poll-ssh-acquire.sh | 86 | ||||
| -rwxr-xr-x | start-ssh-acquire.sh | 2 |
4 files changed, 129 insertions, 10 deletions
diff --git a/example.conf b/example.conf new file mode 100644 index 0000000..cacf0f1 --- /dev/null +++ b/example.conf @@ -0,0 +1,45 @@ +# This is an example configuration for the acquire-key-over-ssh module + +# This is the interface the keyserver will be on. This script should +# wait until this interface is up before trying to connect to the keyserver. +keyserver_interface=eno2 + +# This is the host that contains the ssh server with the key. +keyserver_host=192.168.12.34 + +# The host's ssh port. +keyserver_port=22 + +# Username to ssh into. +keyserver_user=keyper + +# Uncomment the following if the key is stored on a block device. +# +# This device will be mounted before the key is retrieved. +# +# client_ssh_keys_device='/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + +# The mountpoint to mount the ssh-key drive on (from above). +# Uncomment if using the above configuration for keys stored on a device. +# This is where the script will mount the block device to. +# +# client_ssh_keys_mountpoint="/mnt/boot/" + +# The location of the identity file (after mounting). +# This defaults to /root/.ssh/id_rsa +# +# client_identity_file="/mnt/boot/ghost_key" + +# Shred the keys after use. This is useful to minimize the time an unencrypted +# private key is on disk. Only really makes sense if the keys are on disk. +# +# One can set up a systemd service that places the identity key on the drive +# during a routine shutdown, where it will be picked up, used to acquire the +# decryption key, and shredded. +# +# Assuming the drive can be mounted, the script will always shred the keys +# if this is set even if authentication failed. +# +# shred_keys_after_use=1 + +add_dracutmodules+=" acquire-key-over-ssh " diff --git a/module-setup.sh b/module-setup.sh index fd0bb5d..8708778 100755 --- a/module-setup.sh +++ b/module-setup.sh @@ -22,8 +22,12 @@ install() { echo "keyserver_host='$keyserver_host'" >> "$genconf" echo "keyserver_user='$keyserver_user'" >> "$genconf" echo "keyserver_port='$keyserver_port'" >> "$genconf" + echo "client_ssh_keys_device='${client_ssh_keys_device}'" >> "$genconf" + echo "client_ssh_keys_mountpoint='$client_ssh_keys_mountpoint'" >> "$genconf" + echo "client_identity_file='$client_identity_file'" >> "$genconf" + echo "shred_keys_after_use='$shred_keys_after_use'" >> "$genconf" - inst_hook pre-udev 99 "$moddir/start-ssh-acquire.sh" + inst_hook initqueue/settled 99 "$moddir/start-ssh-acquire.sh" inst_script "$moddir/poll-ssh-acquire.sh" "/bin/poll-ssh-acquire.sh" inst_simple "/root/.ssh/known_hosts" inst_simple "/root/.ssh/id_rsa.pub" diff --git a/poll-ssh-acquire.sh b/poll-ssh-acquire.sh index 225287c..ffa4672 100755 --- a/poll-ssh-acquire.sh +++ b/poll-ssh-acquire.sh @@ -5,6 +5,7 @@ # This is useful because my system motherboard does not save the system time # for some reason. +lockfile=/tmp/acquire-ssh-key-lock timeout=600 count=0 @@ -25,30 +26,99 @@ while ! ( ip route list dev "$keyserver_interface" &>/dev/null ) ; do done echo -e "\ndone" +# Amount of tries tries=10 -count=0 +# If the ssh-key is on a device, we have to mount that device before +# we can do anything. +mounted=0 + +if [[ ! -z "$client_ssh_keys_device" ]] ; then + if [[ -z "$client_ssh_keys_mountpoint" ]] ; then + echo "client_ssh_keys_device requires client_ssh_keys_mountpoint to be set!" + return 1 + fi + + count=0 + while true ; do + if [[ "$count" -eq "$tries" ]] ; then + echo "Failed to mount $client_ssh_keys_device on $client_ssh_keys_mountpoint after $tries tries" + exit 1 + fi + mkdir -p "$client_ssh_keys_mountpoint" + echo "mounting $client_ssh_keys_device on $client_ssh_keys_mountpoint" + mount "$client_ssh_keys_device" "$client_ssh_keys_mountpoint" + ec="$?" + if [[ "$ec" -eq 0 ]] ; then + break + fi + sleep 1 + count=$((count + 1)) + done + count=0 + + mounted=1 +fi + +# Default identity file is root's identity file. +if [[ -z "$client_identity_file" ]] ; then + client_identity_file=/root/.ssh/id_rsa +fi + +if [[ ! -f "$client_identity_file" ]] ; then + echo "$client_identity_file does not exist." + exit 1 +fi + +# The main loop. This is going to try repeatedly 10 times to acquire the +# decryption key. If it fails each time, it will give up and someone +# will have to manually unlock the device. +count=0 +acquired=0 while /bin/true ; do if [[ "$count" -eq "$tries" ]] ; then echo "Unable to connect to $keyserver_user@$keyserver_host after 10 tries." - exit 1 + break; fi echo "Trying $keyserver_user@$keyserver_host ..." - ssh "$keyserver_user@$keyserver_host" -p "$keyserver_port" > /tmp/enc-key + echo ssh -i "$client_identity_file" "$keyserver_user@$keyserver_host" -p "$keyserver_port" - if [[ "$?" -eq 0 ]] ; then + ssh -i "$client_identity_file" "$keyserver_user@$keyserver_host" -p "$keyserver_port" > /tmp/enc-key + + ec="$?" + if [[ "$ec" -eq 0 ]] ; then + acquired=1 break; + else + echo "Non-zero exit code ec=$ec" fi sleep 1 count=$((count + 1)) done -echo "Passphrase acquired. Stored in /tmp/enc-key." +# Shred the keys and unmount the filessystems if needed. +if [[ "$shred_keys_after_use" -eq 1 ]] ; then + echo "shred $client_identity_file" + shred -u "$client_identity_file" +fi + +if [[ "$mounted" -eq "1" ]] ; then + echo "unmount client_ssh_keys_mountpoint" + umount "$client_ssh_keys_mountpoint" +fi + +# If the key was acquired, send it to systemd. +if [[ "$acquired" -eq 1 ]] ; then + echo "Key acquired. Stored in /tmp/enc-key." -socket_file=$(cat /run/systemd/ask-password/ask.* | grep -E '^Socket' | cut -d'=' -f2) -echo "running: /lib/systemd/systemd-reply-password 1 $socket_file < /tmp/enc-key" -/lib/systemd/systemd-reply-password 1 "$socket_file" < /tmp/enc-key + socket_file=$(cat /run/systemd/ask-password/ask.* | grep -E '^Socket' | cut -d'=' -f2) + echo "running: /lib/systemd/systemd-reply-password 1 $socket_file < /tmp/enc-key" + /lib/systemd/systemd-reply-password 1 "$socket_file" < /tmp/enc-key +else + echo "Failed to acquire key." +fi +# Shred the encryption key for good measure. Probably not necessary. shred /tmp/enc-key diff --git a/start-ssh-acquire.sh b/start-ssh-acquire.sh index 1b3b684..06c4be5 100755 --- a/start-ssh-acquire.sh +++ b/start-ssh-acquire.sh @@ -1,3 +1,3 @@ #!/bin/sh -nohup /bin/poll-ssh-acquire.sh "eno2" &>/var/log/ssh-acquire.log & +nohup /bin/poll-ssh-acquire.sh 2>&1 >> /var/log/ssh-acquire.log & |