#!/usr/bin/env bash # https://www.freedesktop.org/software/systemd/man/systemd.generator.html#Output%20directories normal_dir=$1 early_dir=$2 late_dir=$3 CONFIG="${4:-/etc/fido2luks.conf}" GENERATOR_NORMAL_DIR=${1:-/run/systemd/system} TARGET="fido2luks.target" SYSTEMD_CRYPTSETUP="/usr/lib/systemd/systemd-cryptsetup" error() { printf "$1" 1>&2 [ -e /dev/kmsg ] && printf "$1" > /dev/kmsg exit 1 } make_service() { local config="$1" local service_dir="${2:-.}" source "$config" if [ -z "$FIDO2LUKS_CREDENTIAL_ID" ] && [ -z "$FIDO2LUKS_USE_TOKEN" ]; then error "Config is missing credential_id" fi if [ -z "$FIDO2LUKS_DEVICE" ]; then error "Config is missing device" fi if [ -z "$FIDO2LUKS_MAPPER_NAME" ]; then error "Config is missing mapper_name" fi #local uuid="$(blkid -o value -s UUID '$FIDO2LUKS_DEVICE')" #if [ $? -ne 0 ]; then # error "Failed to get UUID for \"%s\"" "$FIDO2LUKS_DEVICE" #fi local escaped_path=$(systemd-escape -p "$FIDO2LUKS_DEVICE") local escaped_name=$(systemd-escape -p "$FIDO2LUKS_MAPPER_NAME") local service_file="$service_dir/fido2luks@$escaped_name.service" local device_unit="$escaped_path.device" local cryptsetup_service="systemd-cryptsetup@$escaped_name.service" cat > $service_file <<- EOM [Unit] Description="fido2luks setup for ${FIDO2LUKS_DEVICE}" After=${device_unit} cryptsetup-pre.target systemd-journald.socket Before=${cryptsetup_service} umount.target ${TARGET} BindsTo=$device_unit Conflicts=umount.target [Service] Type=oneshot Environment=FIDO2LUKS_PASSWORD_HELPER="/usr/bin/systemd-ask-password 'FIDO2 password salt for $FIDO2LUKS_DEVICE'" EnvironmentFile="$config" Restart=on-failure RestartSec=3 RemainAfterExit=yes ExecStartPre=-${FIDO2LUKS_BOOT_PRE:-/bin/true} ExecStart=fido2luks open ExecStop=${SYSTEMD_CRYPTSETUP} detach "${FIDO2LUKS_MAPPER_NAME}" EOM mkdir -p "$service_dir/$cryptsetup_service.d" "$service_dir/$cryptsetup_service.wants" cat > $service_dir/$cryptsetup_service.d/fido2luks-$escaped_name.conf <<- EOM [Unit] ConditionPathExists=!/dev/mapper/$FIDO2LUKS_MAPPER_NAME EOM ln -sf $service_file "$service_dir/$cryptsetup_service.wants/" } service_generator() { local config="$1" if [ ! -e "$config" ]; then printf "Config does not exist" 1>&2; return 1 fi source "$config" local escaped_name=$(systemd-escape -p "$FIDO2LUKS_MAPPER_NAME") make_service "$config" $normal_dir } generate_services() { if [ -e "$CONFIG" ]; then service_generator "$CONFIG" fi if [ -e $CONFIG.d ]; then for config in $CONFIG.d/*; do service_generator "$config" done fi } if [ ! -z "$PRINT_SERVICE_FILE" ]; then make_service "$1" else generate_services fi