Actualiser modules/yubikey-first-login.nix

This commit is contained in:
2026-08-18 14:33:45 +02:00
parent be3d312dca
commit adf44ca2fe
+262 -194
View File
@@ -1,24 +1,16 @@
{ pkgs, ... }: { pkgs, ... }:
let let
# ============================================================ firstLoginSetup = pkgs.writeShellScript "first-login-setup" ''
# Assistant interactif de changement du PIN YubiKey
# ============================================================
yubikeyPinChange = pkgs.writeShellScript "yubikey-pin-change" ''
set -u set -u
state_dir="$HOME/.local/state/nixos-workstations" state_dir="$HOME/.local/state/nixos-workstations"
marker="$state_dir/yubikey-pin-initialized"
password_marker="$state_dir/password-initialized"
yubikey_marker="$state_dir/yubikey-pin-initialized"
runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}" runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}"
active_file="$runtime_dir/nixos-workstations-yubikey-first-login.active" active_file="$runtime_dir/nixos-workstations-first-login.active"
# ----------------------------------------------------------
# Déclare l'assistant comme actif.
# On stocke son PID pour permettre au superviseur
# de savoir s'il tourne réellement.
# ----------------------------------------------------------
printf '%s\n' "$$" > "$active_file" printf '%s\n' "$$" > "$active_file"
@@ -28,22 +20,13 @@ let
trap cleanup EXIT HUP INT TERM trap cleanup EXIT HUP INT TERM
# ---------------------------------------------------------- # ==========================================================
# Si l'initialisation a déjà été effectuée, rien à faire.
# ----------------------------------------------------------
if [ -e "$marker" ]; then
exit 0
fi
# ----------------------------------------------------------
# Couleurs # Couleurs
# ---------------------------------------------------------- # ==========================================================
RESET="\033[0m" RESET="\033[0m"
BOLD="\033[1m" BOLD="\033[1m"
BLUE="\033[38;5;39m"
CYAN="\033[38;5;45m" CYAN="\033[38;5;45m"
GREEN="\033[38;5;82m" GREEN="\033[38;5;82m"
YELLOW="\033[38;5;220m" YELLOW="\033[38;5;220m"
@@ -51,110 +34,180 @@ let
GREY="\033[38;5;245m" GREY="\033[38;5;245m"
WHITE="\033[38;5;255m" WHITE="\033[38;5;255m"
separator() { line() {
printf "''${BLUE}''${RESET}\n" printf "''${GREY}''${RESET}\n"
} }
# ---------------------------------------------------------- clear
# Nettoyage de l'écran
# ----------------------------------------------------------
printf "\033[2J\033[H"
echo echo
separator
echo echo
printf " ''${BOLD}''${CYAN}🔐 INITIALISATION DE VOTRE YUBIKEY''${RESET}\n" printf " ''${BOLD}''${CYAN}CONFIGURATION DE VOTRE COMPTE''${RESET}\n"
echo echo
separator line
echo echo
printf " ''${WHITE}Bienvenue.''${RESET}\n" printf " Bienvenue ''${BOLD}Alice''${RESET}.\n"
echo echo
printf " Cette procédure termine la préparation de votre poste.\n"
printf " Pour sécuriser votre accès au poste, vous devez maintenant\n" printf " Elle ne sera effectuée qu'une seule fois.\n"
printf " personnaliser le ''${BOLD}PIN de votre YubiKey''${RESET}.\n"
echo
printf " ''${YELLOW} Cette opération est obligatoire.''${RESET}\n"
echo
# ----------------------------------------------------------
# Étapes
# ----------------------------------------------------------
printf " ''${BOLD}''${CYAN}[1/3]''${RESET} ''${WHITE}Saisissez votre PIN temporaire.''${RESET}\n"
printf " ''${GREY}Il vous a été communiqué avec votre poste.''${RESET}\n"
echo
printf " ''${BOLD}''${CYAN}[2/3]''${RESET} ''${WHITE}Choisissez votre nouveau PIN personnel.''${RESET}\n"
printf " ''${GREY}Ne réutilisez pas le PIN temporaire.''${RESET}\n"
echo
printf " ''${BOLD}''${CYAN}[3/3]''${RESET} ''${WHITE}Confirmez votre nouveau PIN.''${RESET}\n"
echo
separator
echo
printf " ''${GREY}Votre nouveau PIN est enregistré directement dans la YubiKey.''${RESET}\n"
printf " ''${GREY}Il n'est pas enregistré dans la configuration du poste.''${RESET}\n"
echo echo
separator line
echo echo
printf " ''${BOLD}''${YELLOW}IMPORTANT''${RESET}\n" # ==========================================================
echo # ÉTAPE 1 : MOT DE PASSE LOCAL
printf " Ne fermez pas cette fenêtre pendant l'opération.\n" # ==========================================================
printf " Vérifiez l'état de ''${BOLD}Verr Num''${RESET} si vous utilisez le pavé numérique.\n"
printf " En cas de doute, utilisez les chiffres situés au-dessus du clavier.\n"
if [ ! -e "$password_marker" ]; then
printf " ''${BOLD}''${CYAN}ÉTAPE 1 / 2''${RESET}\n"
echo echo
separator printf " ''${BOLD}Choisissez votre mot de passe de secours''${RESET}\n"
echo echo
printf " ''${BOLD}''${WHITE}Suivez maintenant les instructions ci-dessous.''${RESET}\n" printf " Ce mot de passe permet notamment d'accéder au poste\n"
printf " si votre YubiKey est indisponible.\n"
echo
printf " ''${YELLOW}Vous allez saisir :''${RESET}\n"
echo
printf " votre mot de passe temporaire actuel\n"
printf " votre nouveau mot de passe personnel\n"
printf " une confirmation du nouveau mot de passe\n"
echo
line
echo echo
# ---------------------------------------------------------- if ${pkgs.shadow}/bin/passwd; then
# Changement du PIN
# ---------------------------------------------------------- ${pkgs.coreutils}/bin/mkdir -p "$state_dir"
${pkgs.coreutils}/bin/touch "$password_marker"
echo
printf " ''${GREEN} Mot de passe modifié avec succès.''${RESET}\n"
echo
${pkgs.coreutils}/bin/sleep 2
else
echo
printf " ''${RED} Le changement du mot de passe a échoué.''${RESET}\n"
echo
printf " La procédure sera automatiquement reproposée.\n"
${pkgs.coreutils}/bin/sleep 3
exit 1
fi
fi
# ==========================================================
# ÉTAPE 2 : PIN YUBIKEY
# ==========================================================
clear
echo
echo
printf " ''${BOLD}''${CYAN}CONFIGURATION DE VOTRE COMPTE''${RESET}\n"
echo
line
echo
printf " ''${BOLD}''${CYAN}ÉTAPE 2 / 2''${RESET}\n"
echo
printf " ''${BOLD}Personnalisez le PIN de votre YubiKey''${RESET}\n"
echo
printf " Votre clé utilise actuellement le PIN temporaire fourni\n"
printf " lors de la préparation du poste.\n"
echo
printf " ''${YELLOW}Vous allez saisir :''${RESET}\n"
echo
printf " votre PIN temporaire actuel\n"
printf " votre nouveau PIN personnel\n"
printf " une confirmation du nouveau PIN\n"
echo
printf " ''${GREY}Le nouveau PIN reste enregistré uniquement dans la YubiKey.''${RESET}\n"
echo
printf " ''${YELLOW} Vérifiez Verr Num si vous utilisez le pavé numérique.''${RESET}\n"
printf " En cas de doute, utilisez les chiffres situés au-dessus du clavier.\n"
echo
line
echo
if [ ! -e "$yubikey_marker" ]; then
if ${pkgs.yubikey-manager}/bin/ykman fido access change-pin; then if ${pkgs.yubikey-manager}/bin/ykman fido access change-pin; then
# --------------------------------------------------------
# Succès
#
# IMPORTANT :
# le marqueur est créé immédiatement après le succès
# confirmé par ykman.
# --------------------------------------------------------
${pkgs.coreutils}/bin/mkdir -p "$state_dir" ${pkgs.coreutils}/bin/mkdir -p "$state_dir"
${pkgs.coreutils}/bin/touch "$marker" ${pkgs.coreutils}/bin/touch "$yubikey_marker"
echo echo
separator printf " ''${GREEN} PIN YubiKey modifié avec succès.''${RESET}\n"
echo
printf " ''${BOLD}''${GREEN} INITIALISATION TERMINÉE''${RESET}\n" ${pkgs.coreutils}/bin/sleep 2
else
echo echo
separator printf " ''${RED} Le changement du PIN n'a pas été terminé.''${RESET}\n"
echo echo
printf " Votre mot de passe déjà modifié sera conservé.\n"
printf " Seule cette étape sera reproposée.\n"
printf " ''${GREEN}Votre nouveau PIN est maintenant actif.''${RESET}\n" ${pkgs.coreutils}/bin/sleep 3
echo
printf " Utilisez désormais ce nouveau PIN pour vous\n" exit 1
printf " connecter avec votre YubiKey.\n" fi
fi
# ==========================================================
# TERMINÉ
# ==========================================================
clear
echo echo
printf " ''${GREY}Cette procédure ne sera plus affichée.''${RESET}\n" echo
line
echo
printf " ''${BOLD}''${GREEN} CONFIGURATION TERMINÉE''${RESET}\n"
echo echo
separator line
echo
printf " Votre compte est maintenant prêt.\n"
echo
printf " ''${GREEN}''${RESET} Mot de passe personnel configuré\n"
printf " ''${GREEN}''${RESET} PIN personnel YubiKey configuré\n"
echo
echo
printf " Pour vos prochaines connexions :\n"
echo
printf " ''${BOLD}YubiKey + votre PIN personnel''${RESET}\n"
echo
printf " Votre mot de passe local reste disponible comme solution\n"
printf " de secours.\n"
echo
line
echo echo
printf " Fermeture automatique" printf " Fermeture automatique"
@@ -166,171 +219,186 @@ let
echo echo
exit 0 exit 0
else
# --------------------------------------------------------
# Échec / annulation
#
# Aucun marqueur n'est créé.
# Le superviseur relancera automatiquement l'assistant.
# --------------------------------------------------------
echo
separator
echo
printf " ''${BOLD}''${RED} INITIALISATION NON TERMINÉE''${RESET}\n"
echo
separator
echo
printf " ''${RED}Le PIN n'a pas été modifié.''${RESET}\n"
echo
printf " La fenêtre va être fermée puis l'assistant\n"
printf " sera automatiquement relancé.\n"
echo
printf " ''${YELLOW}Vous devez terminer cette procédure''${RESET}\n"
printf " ''${YELLOW}pour finaliser l'initialisation de votre YubiKey.''${RESET}\n"
echo
separator
echo
${pkgs.coreutils}/bin/sleep 4
exit 1
fi
''; '';
# ============================================================ firstLoginSupervisor =
# Superviseur de première connexion pkgs.writeShellScript "first-login-supervisor" ''
# ============================================================
yubikeyFirstLoginSupervisor =
pkgs.writeShellScript "yubikey-first-login-supervisor" ''
set -u set -u
current_user="$(${pkgs.coreutils}/bin/id -un)" current_user="$(${pkgs.coreutils}/bin/id -un)"
# -------------------------------------------------------- # Pour le moment uniquement Alice.
# Pour le moment, uniquement Alice.
# --------------------------------------------------------
if [ "$current_user" != "alice" ]; then if [ "$current_user" != "alice" ]; then
exit 0 exit 0
fi fi
state_dir="$HOME/.local/state/nixos-workstations" state_dir="$HOME/.local/state/nixos-workstations"
marker="$state_dir/yubikey-pin-initialized"
password_marker="$state_dir/password-initialized"
yubikey_marker="$state_dir/yubikey-pin-initialized"
runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}" runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}"
active_file="$runtime_dir/nixos-workstations-yubikey-first-login.active" active_file="$runtime_dir/nixos-workstations-first-login.active"
supervisor_lock="$runtime_dir/nixos-workstations-yubikey-first-login.lock" supervisor_lock="$runtime_dir/nixos-workstations-first-login.lock"
KDIALOG="${pkgs.kdePackages.kdialog}/bin/kdialog"
KONSOLE="${pkgs.kdePackages.konsole}/bin/konsole"
# --------------------------------------------------------
# Une seule instance du superviseur. # Une seule instance du superviseur.
# --------------------------------------------------------
exec 9>"$supervisor_lock" exec 9>"$supervisor_lock"
if ! ${pkgs.util-linux}/bin/flock -n 9; then if ! ${pkgs.util-linux}/bin/flock -n 9; then
exit 0 exit 0
fi fi
# -------------------------------------------------------- # Les deux opérations sont déjà terminées.
# Initialisation déjà terminée. if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then
# --------------------------------------------------------
if [ -e "$marker" ]; then
exit 0 exit 0
fi fi
# Laisse Plasma terminer son démarrage. # Laisse Plasma terminer son démarrage.
${pkgs.coreutils}/bin/sleep 4 ${pkgs.coreutils}/bin/sleep 3
# -------------------------------------------------------- # ========================================================
# Boucle de supervision # Présentation
# -------------------------------------------------------- # ========================================================
while [ ! -e "$marker" ]; do while \
[ ! -e "$password_marker" ] || \
[ ! -e "$yubikey_marker" ]
do
assistant_running=0 "$KDIALOG" \
--title "Finalisation de votre poste" \
--warningcontinuecancel \
"Bienvenue Alice.
# ------------------------------------------------------ Votre poste est presque prêt.
# Vérifie si l'assistant précédemment lancé tourne
# réellement toujours.
# ------------------------------------------------------
if [ -s "$active_file" ]; then Pour terminer sa configuration, vous devez personnaliser deux éléments de sécurité :
assistant_pid="$(${pkgs.coreutils}/bin/cat "$active_file" 2>/dev/null || true)" 🔑 Votre mot de passe local de secours
if [ -n "$assistant_pid" ] \ 🔐 Le PIN de votre YubiKey
&& ${pkgs.coreutils}/bin/kill -0 "$assistant_pid" 2>/dev/null; then
assistant_running=1 Ces informations deviennent personnelles.
else Elles ne sont pas enregistrées dans Git et ne sont pas transmises au service informatique.
# Fichier devenu obsolète. La procédure prend seulement quelques instants."
rm -f "$active_file"
fi result=$?
if [ "$result" -ne 0 ]; then
"$KDIALOG" \
--title "Configuration requise" \
--sorry \
"La configuration initiale de votre compte n'est pas terminée.
L'assistant va être reproposé."
${pkgs.coreutils}/bin/sleep 1
continue
fi fi
# ------------------------------------------------------ # ------------------------------------------------------
# Aucun assistant actif : # Lance l'assistant interactif
# on en ouvre un.
# ------------------------------------------------------ # ------------------------------------------------------
if [ "$assistant_running" -eq 0 ]; then "$KONSOLE" \
${pkgs.kdePackages.konsole}/bin/konsole \
--separate \ --separate \
--fullscreen \ --fullscreen \
--hide-menubar \ --hide-menubar \
--hide-tabbar \ --hide-tabbar \
-e ${yubikeyPinChange} \ -e ${firstLoginSetup} \
>/dev/null 2>&1 & >/dev/null 2>&1 &
# Laisse le temps à Konsole et au script de démarrer. ${pkgs.coreutils}/bin/sleep 1
${pkgs.coreutils}/bin/sleep 2
else # ------------------------------------------------------
# Attend la fin réelle du script.
# ------------------------------------------------------
${pkgs.coreutils}/bin/sleep 2 while true; do
if [ \
-e "$password_marker" \
] && [ \
-e "$yubikey_marker" \
]; then
break
fi fi
if [ ! -s "$active_file" ]; then
break
fi
assistant_pid="$(
${pkgs.coreutils}/bin/cat "$active_file" 2>/dev/null || true
)"
if [ -z "$assistant_pid" ]; then
break
fi
if ! ${pkgs.coreutils}/bin/kill -0 "$assistant_pid" 2>/dev/null; then
rm -f "$active_file"
break
fi
${pkgs.coreutils}/bin/sleep 1
done done
# -------------------------------------------------------- # ------------------------------------------------------
# Le marqueur existe : # Tout est terminé.
# l'initialisation est terminée. # ------------------------------------------------------
#
# On ne touche PAS à la session KDE. if [ \
# -------------------------------------------------------- -e "$password_marker" \
] && [ \
-e "$yubikey_marker" \
]; then
"$KDIALOG" \
--title "Poste configuré" \
--msgbox \
" Votre poste est prêt.
Votre mot de passe personnel et le PIN de votre YubiKey ont été configurés.
Pour vos prochaines connexions, utilisez votre YubiKey et votre nouveau PIN.
Votre mot de passe local reste disponible comme solution de secours."
exit 0
fi
"$KDIALOG" \
--title "Configuration incomplète" \
--sorry \
"La configuration n'a pas été entièrement terminée.
Les étapes déjà réalisées sont conservées.
L'assistant va reprendre uniquement les étapes restantes."
${pkgs.coreutils}/bin/sleep 1
done
exit 0 exit 0
''; '';
in in
{ {
# ============================================================
# Lancement automatique à l'ouverture de KDE
# ============================================================
environment.etc."xdg/autostart/yubikey-first-login.desktop".text = '' environment.etc."xdg/autostart/yubikey-first-login.desktop".text = ''
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Name=Initialisation de la YubiKey Name=Finalisation du poste
Comment=Configuration obligatoire de votre PIN personnel Comment=Configuration initiale du compte utilisateur
Exec=${yubikeyFirstLoginSupervisor} Exec=${firstLoginSupervisor}
OnlyShowIn=KDE; OnlyShowIn=KDE;
NoDisplay=true NoDisplay=true
StartupNotify=false StartupNotify=false