L'histoire a commencĂ© il y a longtemps, lors de la sortie de Centos 7 (RHEL 7). Si vous avez utilisĂ© le chiffrement des disques avec Centos 6, il n'y avait aucun problĂšme de dĂ©verrouillage automatique des disques lors de la connexion d'une clĂ© USB avec les clĂ©s nĂ©cessaires. Cependant, avec la sortie de la version 7, tout a soudainement cessĂ© de fonctionner comme vous en aviez l'habitude. Ă ce moment-lĂ , on pouvait trouver une solution en revenant de dracut Ă sysvinit grĂące Ă une simple ligne dans le fichier de configuration : echo âomit_dracutmodules+=" systemd "â > /etc/dracut.conf.d/luks-workaround.conf
Ce qui nous privait immĂ©diatement de toute la beautĂ© de systemd â le dĂ©marrage rapide et parallĂšle des services systĂšme, ce qui rĂ©duisait considĂ©rablement le temps de dĂ©marrage du systĂšme.
Et toujours rien :
Ne sachant pas attendre une solution, je l'ai créée moi-mĂȘme et maintenant je la partage avec le public, pour ceux que cela intĂ©resse, lisez la suite.

Introduction
Systemd, quand j'ai commencĂ© Ă travailler avec Centos 7, n'a suscitĂ© aucune Ă©motion, car mis Ă part un changement mineur dans la syntaxe de gestion des services, je n'ai pas ressenti de diffĂ©rence particuliĂšre au dĂ©but. Par la suite, j'ai aimĂ© systemd, mais la premiĂšre impression a Ă©tĂ© un peu entachĂ©e, car les dĂ©veloppeurs de dracut ne consacraient pas beaucoup de temps au soutien du processus de dĂ©marrage avec systemd en conjonction avec le chiffrement des disques. En gĂ©nĂ©ral, cela fonctionnait, mais taper le mot de passe du disque Ă chaque dĂ©marrage â ce n'est pas le faire le plus intĂ©ressant. de serveurs â ce n'est pas une occupation des plus passionnantes.
AprĂšs avoir essayĂ© une multitude de recommandations et avoir Ă©tudiĂ© le manuel, j'ai compris qu'en mode systemd, il Ă©tait possible de configurer avec USB, mais seulement en associant manuellement chaque disque Ă la clĂ© sur la clĂ© USB, et que la clĂ© USB elle-mĂȘme ne pouvait ĂȘtre liĂ©e que par son UUID, l'Ă©tiquette (LABEL) ne fonctionnant pas. Maintenir cela chez moi n'Ă©tait pas trĂšs pratique, donc finalement je me suis plongĂ© dans l'attente et, aprĂšs avoir attendu prĂšs de 7 ans, j'ai compris â personne ne s'apprĂȘte Ă rĂ©soudre le problĂšme.
ProblĂšmes
Bien sûr, presque tout le monde peut écrire son propre plugin pour dracut, mais en faire un qui fonctionne, c'est déjà moins simple. Il s'est avéré qu'en raison de la nature parallÚle du démarrage de systemd, inclure mon propre code et modifier le processus de démarrage n'est pas aussi facile. La documentation de dracut n'expliquait pas tout. Cependant, suite à de longues expériences, j'ai pu résoudre le problÚme.
Comment cela fonctionne
à la base, il y a trois unités :
- luks-auto-key.service â recherche des supports avec des clĂ©s pour LUKS
- luks-auto.target â joue le rĂŽle de dĂ©pendance pour les unitĂ©s intĂ©grĂ©es de systemd-cryptsetup
- luks-auto-clean.service â nettoie les fichiers temporaires créés par luks-auto-key.service
luks-auto-generator.sh est un script qui sâexĂ©cute avec systemd et gĂ©nĂšre des unitĂ©s en fonction des paramĂštres du noyau. Des gĂ©nĂ©rateurs similaires crĂ©ent des unitĂ©s fstab, etc.
luks-auto-generator.sh
Avec drop-in.conf, le comportement par défaut de systemd-cryptsetup est modifié en ajoutant la dépendance à luks-auto.target.
luks-auto-key.service et luks-auto-key.sh
Cette unité exécute le script luks-auto-key.sh qui, basé sur les clés rd.luks.*, détecte les dispositifs contenant les clés et les copie dans un répertoire temporaire pour une utilisation future. AprÚs la fin du processus, les clés du répertoire temporaire sont supprimées par luks-auto-clean.service.
Sources :
/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=Rechercheur de clés AUTO LUKS
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=Cible AUTO LUKS
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=Nettoyeur de clés AUTO LUKS
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 "Installation
mkdir -p /usr/lib/dracut/modules.d/99luks-auto/
# On place ici presque tous les fichiers
chmod +x /usr/lib/dracut/modules.d/99luks-auto/*.sh
# On crée le fichier /etc/dracut.conf.d/luks-auto.conf
# Et on génÚre un nouvel initramfs
dracut -f
Conclusion
Pour plus de commodité, j'ai conservé la compatibilité avec les paramÚtres de ligne de commande du noyau comme pour le mode sysvinit, ce qui facilite l'utilisation dans les anciennes installations.
Source : habr.com
