the-bastion/bin/admin/setup-encryption.sh
2021-05-19 18:56:17 +02:00

213 lines
6.1 KiB
Bash
Executable file

#! /usr/bin/env bash
# vim: set filetype=sh ts=4 sw=4 sts=4 et:
set -e
umask 077
basedir=$(readlink -f "$(dirname "$0")"/../..)
# shellcheck source=lib/shell/functions.inc
. "$basedir"/lib/shell/functions.inc
action_doing "Checking whether the proper tools are installed"
if ! command -v rsync >/dev/null || ! command -v cryptsetup >/dev/null; then
action_error "Missing rsync or cryptsetup, aborting"
exit 1
else
action_done
fi
action_doing "Checking whether the install script has run"
if ! [ -f "/etc/bastion/luks-config.sh" ]; then
action_error "The '/etc/bastion/luks-config.sh' file doesn't exist, did you run the '$basedir/bin/admin/install' script before?"
exit 1
else
action_done
fi
action_doing "Checking whether /home is a separate partition"
home_block_device=$(awk '/ \/home / {print $1}' /proc/mounts)
if [ -n "$home_block_device" ] && [ -e "$home_block_device" ]; then
action_done "found $home_block_device"
else
action_error "No, aborting"
exit 1
fi
action_doing "Checking whether /home is in /etc/fstab"
if grep -qE '[[:space:]]/home[[:space:]]' /etc/fstab; then
action_done "$(grep '[[:space:]]/home[[:space:]]' /etc/fstab)"
else
action_error "No, aborting"
exit 1
fi
action_doing "Checking whether we can umount /home"
if umount /home; then
action_done
else
action_error "No, aborting"
exit 1
fi
action_doing "Checking whether we can remount /home"
if mount /home; then
action_done
else
action_error "No, aborting"
exit 1
fi
action_doing "Checking used space in /home"
home_used_mb=$(df -m /home | awk '{ print $3 }' | tail -n1)
if [ -n "$home_used_mb" ]; then
action_done "$home_used_mb MiB"
else
action_error "Couldn't get the /home used space"
exit 1
fi
action_doing "Checking available space in /"
slash_available_mb=$(df -m / | awk '{ print $4 }' | tail -n1)
if [ -n "$slash_available_mb" ]; then
action_done "$slash_available_mb MiB"
else
action_error "Couldn't get the / available space"
exit 1
fi
action_doing "Checking whether there is enough available space in / to hold /home contents temporarily"
if [ "$slash_available_mb" -gt "$home_used_mb" ]; then
action_done
else
action_error "Not enough free space in /"
exit 1
fi
action_doing "Creating temporary /tmphome"
# silently try to delete it just in case it exists but is empty
if [ -d /tmphome ]; then
rmdir /tmphome 2>/dev/null || true
fi
if [ -e /tmphome ]; then
action_error "/tmphome already exists! Aborting"
exit 1
else
mkdir /tmphome
if [ ! -d /tmphome ]; then
action_error "Couldn't create /tmphome!"
exit 1
else
action_done
fi
fi
action_doing "Rsyncing /home to /tmphome"
if rsync -vaPHAX --exclude='lost+found' /home/ /tmphome/; then
action_done
else
action_error "Rsync failed, aborting!"
rm -Rf /tmphome
exit 1
fi
action_doing "Rsync done, here are some details:"
action_detail "ls /home : $(cd /home ; find . | tr '\n' ' ')"
action_detail "ls /tmphome: $(cd /tmphome ; find . | tr '\n' ' ')"
action_detail "du -shc /home : $(du -shc /home | grep total)"
action_detail "du -shc /tmphome: $(du -shc /tmphome | grep total)"
action_detail ""
action_detail "Does this look reasonable? [CTRL+C if not]"
# shellcheck disable=SC2034
read -r _dummy
action_doing "Umounting /home"
if umount /home; then
action_done
else
action_error "Couldn't umount /home, aborting"
rm -Rf /tmphome
exit 1
fi
action_doing "Erasing /home block device and encrypting it (last chance to cancel!)"
action_detail "You should generate a strong password on your desk, with e.g. \`pwgen -s 10\`"
if cryptsetup luksFormat "$home_block_device"; then
action_done
else
action_error "Cryptsetup failed, aborting"
mount /home && rm -Rf /tmphome
exit 1
fi
action_doing "Opening newly encrypted block device"
if cryptsetup luksOpen "$home_block_device" home; then
action_done
else
action_error "Opening failed, aborting! Your /home partition is no longer valid, fix it manually! ($home_block_device)"
exit 1
fi
action_doing "Creating a new filesystem on top of the encrypted block device"
if mkfs.ext4 -T news -L home -M /home /dev/disk/by-id/dm-name-home; then
action_done
else
action_error "Filesystem creation failed, aborting! Your /home partition is no longer valid, fix it manually! ($home_block_device)"
exit 1
fi
action_doing "Setting up /etc/bastion/luks-config.sh with encrypted block device"
if sed -i -re "s;^DEV_ENCRYPTED=.*;DEV_ENCRYPTED=$home_block_device;" /etc/bastion/luks-config.sh; then
action_done
else
action_error "Couldn't modify /etc/bastion/luks-config.sh, please do it manually, continuing"
fi
action_doing "Setting up /etc/fstab with encrypted block device"
newfstab=$(mktemp)
grep -Ev "[[:space:]]/home[[:space:]]" /etc/fstab > "$newfstab"
echo "# added by $(basename "$0") on $(date)" >> "$newfstab"
echo "/dev/disk/by-id/dm-name-home /home ext4 defaults,errors=remount-ro,noauto,nosuid,noexec,nodev 0 0" >> "$newfstab"
cat "$newfstab" > /etc/fstab
rm -f "$newfstab"
action_done
action_doing "Remounting /home after encryption"
if mount /home; then
action_done
else
action_error "Error while remounting home, aborting!"
exit 1
fi
action_doing "Rsyncing back /home contents"
if rsync -vaPHAX --remove-source-files --exclude='lost+found' /tmphome/ /home/; then
action_done
else
action_error "Rsync failed, aborting!"
exit 1
fi
action_doing "Removing /tmphome"
if find /tmphome -depth -type d -empty -delete; then
action_done
else
action_error "Error while removing /tmphome, continuing anyway"
fi
action_doing "Testing whether we can properly unlock /home after boot"
if umount /home; then
if cryptsetup luksClose home; then
if /opt/bastion/bin/admin/unlock-home.sh; then
action_done
else
action_error "Error with unlock-home.sh, ignoring"
fi
else
action_error "Couldn't luksClose home, ignoring"
fi
else
action_error "Couldn't umount /home to run the test, ignoring"
fi
[ ! -e /root/unlock-home.sh ] && ln -s /opt/bastion/bin/admin/unlock-home.sh /root/