dracut + systemd + LUKS + usbflash = sbloccare automaticamente

A storia hà cuminciatu assai tempu fà, quandu Centos 7 (RHEL 7) hè stata liberata. Se avete utilizatu criptografia in unità cù Centos 6, ùn ci era micca prublemi cù unlocking automaticu di unità quandu avete cunnessu una unità flash USB cù e chjave necessarie. Tuttavia, quandu 7 hè stata liberata, di colpu tuttu ùn hà micca travagliatu cum'è tù era abituatu. Allora era pussibule di truvà una soluzione per rinvià dracut à sysvinit usendu una linea simplice in a cunfigurazione: echo 'omit_dracutmodules+=" systemd "'> /etc/dracut.conf.d/luks-workaround.conf
Chì ci hà privatu immediatamente di tutta a bellezza di systemd - lanciamentu rapidu è parallelu di servizii di u sistema, chì riduce significativamente u tempu di startup di u sistema.
E cose sò sempre quì: 905683
Senza aspittà una suluzione, aghju fattu per mè stessu, è avà l'aghju sparte cù u publicu, chì hè interessatu, leghje.
dracut + systemd + LUKS + usbflash = sbloccare automaticamente

Introduzione

Systemd, quandu aghju cuminciatu à travaglià cù Centos 7, ùn hà micca causatu emozioni, postu chì fora di un cambiamentu minore in a sintassi di a gestione di u serviziu, ùn aghju micca sentitu assai differenza in prima. In seguitu, mi piaceva systemd, ma a prima impressione era un pocu spoiled, postu chì i sviluppatori di dracut ùn anu micca passatu assai tempu per sustene u prucessu di boot usendu systemd in cunjunzione cù a criptografia di discu. In generale, hà travagliatu, ma inserisce a password di u discu ogni volta chì u servitore principia ùn hè micca u più interessante.
Dopu avè pruvatu una mansa di cunsiglii è studiatu u manuale, aghju capitu chì in a cunfigurazione di u modu systemd cù USB hè pussibule, ma solu cù l'associazione manuale di ogni discu cù una chjave in un discu USB, è u discu USB stessu pò esse assuciatu solu da u so discu. UUID, LABEL ùn hà micca travagliatu. Ùn era micca assai cunvenutu per mantene questu in casa, cusì à a fine aghju immersi in l'aspittà è, dopu aspittendu quasi 7 anni, aghju capitu chì nimu avia da risolve u prublema.

Problemi

Di sicuru, quasi tutti ponu scrive u so propiu plugin per dracut, ma fà u travagliu ùn hè più cusì faciule. Hè risultatu chì, per via di a natura parallela di l'iniziu di systemd, ùn hè micca cusì faciule d'include u vostru codice è cambià u prugressu di carica. A documentazione per dracut ùn hà micca spiegatu tuttu. Tuttavia, dopu à longu esperimenti, aghju pussutu risolve u prublema.

Cumu funziona

Hè basatu annantu à trè unità:

  1. luks-auto-key.service - cerca unità cù chjave per LUKS
  2. luks-auto.target - agisce cum'è una dipendenza per unità systemd-cryptsetup integrate
  3. luks-auto-clean.service - pulisce i schedari tempuranee creati da luks-auto-key.service

È luks-auto-generator.sh hè un script chì hè lanciatu da systemd è genera unità basate nantu à i paràmetri di u kernel. Generatori simili sò creati da unità fstab, etc.

luks-auto-generator.sh

Utilizendu drop-in.conf, u cumpurtamentu di systemd-cryptsetup standard hè cambiatu aghjunghjendu luks-auto.target à a so dipendenza.

luks-auto-key.service è luks-auto-key.sh

Questa unità eseguisce l'script luks-auto-key.sh, chì, basatu annantu à i chjavi rd.luks.*, trova i media cù e chjavi è li copia in un repertoriu tempurale per un usu più. Dopu chì u prucessu hè cumpletu, i chjavi sò sguassati da u repertoriu temporale da luks-auto-clean.service.

Fonti:

/usr/lib/dracut/modules.d/99luks-auto/module-setup.sh

#!/bin/bash

check () {
        if ! dracut_module_included "systemd"; then
                "luks-auto needs systemd in the initramfs"
                return 1
        fi
        return 255
}

depends () {
        echo "systemd"
        return 0
}

install () {
        inst "$systemdutildir/systemd-cryptsetup"
		inst_script "$moddir/luks-auto-generator.sh" "$systemdutildir/system-generators/luks-auto-generator.sh"
		inst_script "$moddir/luks-auto-key.sh" "/etc/systemd/system/luks-auto-key.sh"
		inst_script "$moddir/luks-auto.sh" "/etc/systemd/system/luks-auto.sh"
		inst "$moddir/luks-auto.target" "${systemdsystemunitdir}/luks-auto.target"
		inst "$moddir/luks-auto-key.service" "${systemdsystemunitdir}/luks-auto-key.service"
		inst "$moddir/luks-auto-clean.service" "${systemdsystemunitdir}/luks-auto-clean.service"
		ln_r "${systemdsystemunitdir}/luks-auto.target" "${systemdsystemunitdir}/initrd.target.wants/luks-auto.target"
		ln_r "${systemdsystemunitdir}/luks-auto-key.service" "${systemdsystemunitdir}/initrd.target.wants/luks-auto-key.service"
		ln_r "${systemdsystemunitdir}/luks-auto-clean.service" "${systemdsystemunitdir}/initrd.target.wants/luks-auto-clean.service"
}

/usr/lib/dracut/modules.d/99luks-auto/luks-auto-generator.sh


#!/bin/sh
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh

. /lib/dracut-lib.sh

SYSTEMD_RUN='/run/systemd/system'
CRYPTSETUP='/usr/lib/systemd/systemd-cryptsetup'
TOUT=$(getargs rd.luks.key.tout)
if [ ! -z "$TOUT" ]; then
	mkdir -p "${SYSTEMD_RUN}/luks-auto-key.service.d"
	cat > "${SYSTEMD_RUN}/luks-auto-key.service.d/drop-in.conf"  <<EOF
[Service]
Type=oneshot
ExecStartPre=/usr/bin/sleep $TOUT

EOF
fi
mkdir -p "$SYSTEMD_RUN/luks-auto.target.wants"
for argv in $(getargs rd.luks.uuid -d rd_LUKS_UUID); do
	_UUID=${argv#luks-}
	_UUID_ESC=$(systemd-escape -p $_UUID)
	mkdir -p "${SYSTEMD_RUN}/systemd-cryptsetup@luksx2d${_UUID_ESC}.service.d"
	cat > "${SYSTEMD_RUN}/systemd-cryptsetup@luksx2d${_UUID_ESC}.service.d/drop-in.conf"  <<EOF
[Unit]
After=luks-auto.target
ConditionPathExists=!/dev/mapper/luks-${_UUID}

EOF
	cat > "${SYSTEMD_RUN}/luks-auto@${_UUID_ESC}.service"  <<EOF
[Unit]
Description=luks-auto Cryptography Setup for %I
DefaultDependencies=no
Conflicts=umount.target
IgnoreOnIsolate=true
Before=luks-auto.target
BindsTo=dev-disk-byx2duuid-${_UUID_ESC}.device
After=dev-disk-byx2duuid-${_UUID_ESC}.device luks-auto-key.service
Before=umount.target

[Service]
Type=oneshot
RemainAfterExit=yes
TimeoutSec=0
ExecStart=/etc/systemd/system/luks-auto.sh ${_UUID}
ExecStop=$CRYPTSETUP detach 'luks-${_UUID}'
Environment=DRACUT_SYSTEMD=1
StandardInput=null
StandardOutput=syslog
StandardError=syslog+console

EOF
ln -fs ${SYSTEMD_RUN}/luks-auto@${_UUID_ESC}.service $SYSTEMD_RUN/luks-auto.target.wants/luks-auto@${_UUID_ESC}.service
done

/usr/lib/dracut/modules.d/99luks-auto/luks-auto-key.service


[Unit]
Description=LUKS AUTO key searcher
After=cryptsetup-pre.target
Before=luks-auto.target
DefaultDependencies=no

[Service]
Environment=DRACUT_SYSTEMD=1
Type=oneshot
ExecStartPre=/usr/bin/sleep 1
ExecStart=/etc/systemd/system/luks-auto-key.sh
RemainAfterExit=true
StandardInput=null
StandardOutput=syslog
StandardError=syslog+console

/usr/lib/dracut/modules.d/99luks-auto/luks-auto-key.sh


#!/bin/sh
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
export DRACUT_SYSTEMD=1

. /lib/dracut-lib.sh
MNT_B="/tmp/luks-auto"
ARG=$(getargs rd.luks.key)
IFS=$':' _t=(${ARG})
KEY=${_t[0]}
F_FIELD=''
F_VALUE=''
if [ ! -z $KEY ] && [ ! -z ${_t[1]} ];then
	IFS=$'=' _t=(${_t[1]})
	F_FIELD=${_t[0]}
	F_VALUE=${_t[1]}
	F_VALUE="${F_VALUE%"}"
	F_VALUE="${F_VALUE#"}"
fi
mkdir -p $MNT_B

finding_luks_keys(){
	local _DEVNAME=''
	local _UUID=''
	local _TYPE=''
	local _LABEL=''
	local _MNT=''
	local _KEY="$1"
	local _F_FIELD="$2"
	local _F_VALUE="$3"
	local _RET=0	
	blkid -s TYPE -s UUID -s LABEL -u filesystem | grep -v -E -e "TYPE=".*_member"" -e "TYPE="crypto_.*"" -e "TYPE="swap"" | while IFS=$'' read -r _line; do
		IFS=$':' _t=($_line);
		_DEVNAME=${_t[0]}
		_UUID=''
		_TYPE=''
		_LABEL=''
		_MNT=''
		IFS=$' ' _t=(${_t[1]});
		for _a in "${_t[@]}"; do
			IFS=$'=' _v=(${_a});
			temp="${_v[1]%"}"
			temp="${temp#"}"
			case ${_v[0]} in
				'UUID')
					_UUID=$temp
				;;
				'TYPE')
					_TYPE=$temp
				;;
				'LABEL')
					_LABEL=$temp
				;;
			esac
		done
		if [ ! -z "$_F_FIELD" ];then
			case $_F_FIELD in
				'UUID')
					[ ! -z "$_F_VALUE" ] && [ "$_UUID" != "$_F_VALUE" ] && continue
				;;
				'LABEL')
					[ ! -z "$_F_VALUE" ] && [ "$_LABEL" != "$_F_VALUE" ] && continue
				;;
				*)
					[ "$_DEVNAME" != "$_F_FIELD" ] && continue
				;;
			esac
		fi
		_MNT=$(findmnt -n -o TARGET $_DEVNAME)
		if [ -z "$_MNT" ]; then
			_MNT=${MNT_B}/KEY-${_UUID}
			mkdir -p "$_MNT" && mount -o ro "$_DEVNAME" "$_MNT"
			_RET=$?
		else
			_RET=0
		fi
		if [ "${_RET}" -eq 0 ] && [ -f "${_MNT}/${_KEY}" ]; then
			cp "${_MNT}/${_KEY}" "$MNT_B/${_UUID}.key"
			info "Found ${_MNT}/${_KEY} on ${_UUID}"
		fi
		if [[ "${_MNT}" =~ "${MNT_B}" ]]; then
			umount "$_MNT" && rm -rfd --one-file-system "$_MNT"						
		fi
	done
	return 0
}
finding_luks_keys $KEY $F_FIELD $F_VALUE

/usr/lib/dracut/modules.d/99luks-auto/luks-auto.target


[Unit]
Description=LUKS AUTO target
After=systemd-readahead-collect.service systemd-readahead-replay.service
After=cryptsetup-pre.target luks-auto-key.service
Before=cryptsetup.target

/usr/lib/dracut/modules.d/99luks-auto/luks-auto.sh


#!/bin/sh
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
export DRACUT_SYSTEMD=1
. /lib/dracut-lib.sh

MNT_B="/tmp/luks-auto"
CRYPTSETUP='/usr/lib/systemd/systemd-cryptsetup'

for i in $(ls -p $MNT_B | grep -v /);do
	info "Trying $i on $1..."
	$CRYPTSETUP attach "luks-$1" "/dev/disk/by-uuid/$1" $MNT_B/$i 'tries=1'
	if [ "$?" -eq "0" ]; then
		info "Found $i for $1"
		exit 0
	fi
done
warn "No key found for $1.  Fallback to passphrase mode."

/usr/lib/dracut/modules.d/99luks-auto/luks-auto-clean.service

[Unit]
Description=LUKS AUTO key cleaner
After=cryptsetup.target
DefaultDependencies=no

[Service]
Type=oneshot
ExecStart=/usr/bin/rm -rfd --one-file-system /tmp/luks-auto

/etc/dracut.conf.d/luks-auto.conf

add_dracutmodules+=" luks-auto "

rimarchevuli


mkdir -p /usr/lib/dracut/modules.d/99luks-auto/
# размещаем тут почти все файлы
chmod +x /usr/lib/dracut/modules.d/99luks-auto/*.sh
# создаем файл /etc/dracut.conf.d/luks-auto.conf
# И генерируем новый initramfs
dracut -f

cunchiusioni

Per a cunvenzione, aghju mantinutu a cumpatibilità cù l'opzioni di a linea di cumanda di u kernel in quantu à u modu sysvinit, chì face più faciule d'utilizà in installazioni più vechje.

Source: www.habr.com

Add a comment