From 2646fe39e0b17e3411aa24867dc786b6c199499e Mon Sep 17 00:00:00 2001 From: Olivier <1+olivier@noreply.raspot.in> Date: Tue, 18 Aug 2026 15:07:31 +0200 Subject: [PATCH] Actualiser modules/yubikey-first-login.nix --- modules/yubikey-first-login.nix | 425 ++++++++++++++++++++++---------- 1 file changed, 293 insertions(+), 132 deletions(-) diff --git a/modules/yubikey-first-login.nix b/modules/yubikey-first-login.nix index 52c7efd..a5061fd 100644 --- a/modules/yubikey-first-login.nix +++ b/modules/yubikey-first-login.nix @@ -1,6 +1,13 @@ { pkgs, ... }: let + # ============================================================ + # Assistant interactif de première connexion + # + # Étape 1 : changement du mot de passe local + # Étape 2 : changement du PIN YubiKey + # ============================================================ + firstLoginSetup = pkgs.writeShellScript "first-login-setup" '' set -u @@ -12,21 +19,26 @@ let runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}" active_file="$runtime_dir/nixos-workstations-first-login.active" + # ---------------------------------------------------------- + # Permet au superviseur de savoir que l'assistant tourne. + # ---------------------------------------------------------- + printf '%s\n' "$$" > "$active_file" cleanup() { - rm -f "$active_file" + ${pkgs.coreutils}/bin/rm -f "$active_file" } trap cleanup EXIT HUP INT TERM - # ========================================================== + # ---------------------------------------------------------- # Couleurs - # ========================================================== + # ---------------------------------------------------------- RESET="\033[0m" BOLD="\033[1m" + BLUE="\033[38;5;39m" CYAN="\033[38;5;45m" GREEN="\033[38;5;82m" YELLOW="\033[38;5;220m" @@ -34,27 +46,27 @@ let GREY="\033[38;5;245m" WHITE="\033[38;5;255m" - line() { - printf "''${GREY}────────────────────────────────────────────────────────────''${RESET}\n" + separator() { + printf "''${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━''${RESET}\n" } - clear + clear_screen() { + printf "\033[2J\033[H" + } - echo - echo - printf " ''${BOLD}''${CYAN}CONFIGURATION DE VOTRE COMPTE''${RESET}\n" - echo - line - echo + header() { + clear_screen - printf " Bienvenue ''${BOLD}Alice''${RESET}.\n" - echo - printf " Cette procédure termine la préparation de votre poste.\n" - printf " Elle ne sera effectuée qu'une seule fois.\n" + echo + separator + echo - echo - line - echo + printf " ''${BOLD}''${CYAN}🔐 CONFIGURATION DE VOTRE COMPTE''${RESET}\n" + + echo + separator + echo + } # ========================================================== # ÉTAPE 1 : MOT DE PASSE LOCAL @@ -62,42 +74,91 @@ let if [ ! -e "$password_marker" ]; then - printf " ''${BOLD}''${CYAN}ÉTAPE 1 / 2''${RESET}\n" - echo - printf " ''${BOLD}Choisissez votre mot de passe de secours''${RESET}\n" + header + + printf " ''${BOLD}''${CYAN}ÉTAPE 1 SUR 2''${RESET}\n" echo - 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 + printf " ''${BOLD}''${WHITE}Personnalisation du mot de passe de secours''${RESET}\n" echo - if ${pkgs.shadow}/bin/passwd; then + printf " Votre compte possède actuellement un mot de passe temporaire.\n" + printf " Vous devez maintenant le remplacer par votre mot de passe\n" + printf " personnel.\n" + echo + separator + echo + + printf " ''${CYAN}①''${RESET} Saisissez votre mot de passe temporaire actuel.\n" + echo + + printf " ''${CYAN}②''${RESET} Choisissez votre nouveau mot de passe personnel.\n" + echo + + printf " ''${CYAN}③''${RESET} Confirmez votre nouveau mot de passe.\n" + + echo + separator + echo + + printf " ''${GREY}Ce mot de passe reste local au poste.''${RESET}\n" + printf " ''${GREY}Il pourra être utilisé comme solution de secours si votre''${RESET}\n" + printf " ''${GREY}YubiKey est indisponible.''${RESET}\n" + + echo + separator + echo + + printf " ''${BOLD}''${YELLOW}Veuillez maintenant suivre les instructions ci-dessous.''${RESET}\n" + echo + + # -------------------------------------------------------- + # IMPORTANT NixOS + # + # On utilise volontairement le wrapper SUID NixOS. + # + # NE PAS remplacer par : + # ${pkgs.shadow}/bin/passwd + # -------------------------------------------------------- + + if /run/wrappers/bin/passwd; then + + # Le marqueur est créé immédiatement après le succès + # confirmé par passwd. ${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" + separator echo - ${pkgs.coreutils}/bin/sleep 2 + printf " ''${BOLD}''${GREEN}✓ MOT DE PASSE MODIFIÉ AVEC SUCCÈS''${RESET}\n" + + echo + printf " Votre nouveau mot de passe personnel est maintenant actif.\n" + + echo + separator + echo + + ${pkgs.coreutils}/bin/sleep 3 else echo - printf " ''${RED}✗ Le changement du mot de passe a échoué.''${RESET}\n" + separator + echo + + printf " ''${BOLD}''${RED}✗ LE MOT DE PASSE N'A PAS ÉTÉ MODIFIÉ''${RESET}\n" + + echo + printf " L'opération a été annulée ou a échoué.\n" + printf " Cette étape sera automatiquement reproposée.\n" + + echo + separator echo - printf " La procédure sera automatiquement reproposée.\n" ${pkgs.coreutils}/bin/sleep 3 @@ -110,60 +171,102 @@ let # É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 + header + + printf " ''${BOLD}''${CYAN}ÉTAPE 2 SUR 2''${RESET}\n" + echo + + printf " ''${BOLD}''${WHITE}Personnalisation du PIN de votre YubiKey''${RESET}\n" + echo + + printf " Votre YubiKey possède actuellement le PIN temporaire\n" + printf " fourni lors de la préparation du poste.\n" + + echo + separator + echo + + printf " ''${CYAN}①''${RESET} Saisissez votre PIN temporaire actuel.\n" + echo + + printf " ''${CYAN}②''${RESET} Choisissez votre nouveau PIN personnel.\n" + echo + + printf " ''${CYAN}③''${RESET} Confirmez votre nouveau PIN.\n" + + echo + separator + echo + + printf " ''${GREY}Votre PIN est enregistré directement dans la YubiKey.''${RESET}\n" + printf " ''${GREY}Il n'est ni enregistré sur ce poste, ni dans Git.''${RESET}\n" + printf " ''${GREY}Le service informatique ne connaît pas votre nouveau PIN.''${RESET}\n" + + echo + separator + echo + + printf " ''${BOLD}''${YELLOW}⚠ ATTENTION AU PAVÉ NUMÉRIQUE''${RESET}\n" + echo + + printf " Vérifiez que ''${BOLD}Verr Num''${RESET} est activé avant de saisir votre PIN.\n" + printf " En cas de doute, utilisez les chiffres situés au-dessus\n" + printf " des lettres du clavier.\n" + + echo + separator + echo + + printf " ''${BOLD}''${YELLOW}Veuillez maintenant suivre les instructions ci-dessous.''${RESET}\n" + echo + if ${pkgs.yubikey-manager}/bin/ykman fido access change-pin; then + # Le marqueur est créé immédiatement après que ykman + # confirme réellement le changement du PIN. ${pkgs.coreutils}/bin/mkdir -p "$state_dir" ${pkgs.coreutils}/bin/touch "$yubikey_marker" echo - printf " ''${GREEN}✓ PIN YubiKey modifié avec succès.''${RESET}\n" + separator + echo - ${pkgs.coreutils}/bin/sleep 2 + printf " ''${BOLD}''${GREEN}✓ PIN YUBIKEY MODIFIÉ AVEC SUCCÈS''${RESET}\n" + + echo + printf " Votre nouveau PIN personnel est maintenant actif.\n" + + echo + separator + echo + + ${pkgs.coreutils}/bin/sleep 3 else echo - printf " ''${RED}✗ Le changement du PIN n'a pas été terminé.''${RESET}\n" + separator + echo + + printf " ''${BOLD}''${RED}✗ LE PIN N'A PAS ÉTÉ MODIFIÉ''${RESET}\n" + + echo + printf " L'opération a été annulée ou a échoué.\n" + echo + + if [ -e "$password_marker" ]; then + printf " ''${GREEN}✓ Votre nouveau mot de passe est déjà enregistré.''${RESET}\n" + printf " Il ne vous sera pas demandé de le modifier à nouveau.\n" + echo + fi + + printf " Seule la configuration du PIN sera reproposée.\n" + + echo + separator echo - printf " Votre mot de passe déjà modifié sera conservé.\n" - printf " Seule cette étape sera reproposée.\n" ${pkgs.coreutils}/bin/sleep 3 @@ -173,44 +276,41 @@ let fi # ========================================================== - # TERMINÉ + # CONFIGURATION TERMINÉE # ========================================================== - clear + header + + printf " ''${BOLD}''${GREEN}✓ VOTRE POSTE EST PRÊT''${RESET}\n" echo - echo - line + separator echo - printf " ''${BOLD}''${GREEN}✓ CONFIGURATION TERMINÉE''${RESET}\n" + printf " La configuration initiale de votre compte est terminée.\n" echo - 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" + printf " ''${GREEN}✓''${RESET} Mot de passe personnel configuré\n" + printf " ''${GREEN}✓''${RESET} PIN personnel YubiKey configuré\n" echo + separator echo - printf " Pour vos prochaines connexions :\n" + printf " ''${BOLD}Pour vos prochaines connexions :''${RESET}\n" + echo - printf " ''${BOLD}YubiKey + votre PIN personnel''${RESET}\n" + printf " ''${BOLD}YubiKey + PIN personnel''${RESET}\n" echo printf " Votre mot de passe local reste disponible comme solution\n" - printf " de secours.\n" + printf " de secours si votre YubiKey est indisponible.\n" echo - line + separator echo - printf " Fermeture automatique" + printf " Fermeture automatique" for i in 1 2 3 4 5; do printf "." @@ -218,16 +318,26 @@ let done echo + exit 0 ''; + # ============================================================ + # Superviseur + # + # Son rôle : + # - lancer l'assistant ; + # - le relancer s'il est fermé avant la fin ; + # - NE JAMAIS tuer KDE ou la session. + # ============================================================ + firstLoginSupervisor = pkgs.writeShellScript "first-login-supervisor" '' set -u current_user="$(${pkgs.coreutils}/bin/id -un)" - # Pour le moment uniquement Alice. + # Pour le moment, uniquement Alice. if [ "$current_user" != "alice" ]; then exit 0 fi @@ -245,23 +355,29 @@ let KDIALOG="${pkgs.kdePackages.kdialog}/bin/kdialog" KONSOLE="${pkgs.kdePackages.konsole}/bin/konsole" - # Une seule instance du superviseur. + # -------------------------------------------------------- + # Empêche deux superviseurs de fonctionner simultanément. + # -------------------------------------------------------- + exec 9>"$supervisor_lock" if ! ${pkgs.util-linux}/bin/flock -n 9; then exit 0 fi - # Les deux opérations sont déjà terminées. + # -------------------------------------------------------- + # Tout est déjà configuré. + # -------------------------------------------------------- + if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then exit 0 fi - # Laisse Plasma terminer son démarrage. - ${pkgs.coreutils}/bin/sleep 3 + # Laisse Plasma finir son démarrage. + ${pkgs.coreutils}/bin/sleep 4 # ======================================================== - # Présentation + # Boucle de provisioning # ======================================================== while \ @@ -269,6 +385,10 @@ let [ ! -e "$yubikey_marker" ] do + # ------------------------------------------------------ + # Présentation KDE + # ------------------------------------------------------ + "$KDIALOG" \ --title "Finalisation de votre poste" \ --warningcontinuecancel \ @@ -276,35 +396,67 @@ let Votre poste est presque prêt. -Pour terminer sa configuration, vous devez personnaliser deux éléments de sécurité : +Pour terminer sa configuration, vous devez personnaliser vos deux moyens d'authentification : - 🔑 Votre mot de passe local de secours + 🔑 Votre mot de passe local de secours - 🔐 Le PIN de votre YubiKey + 🔐 Le PIN de votre YubiKey -Ces informations deviennent personnelles. +Les nouveaux secrets que vous choisirez sont personnels. -Elles ne sont pas enregistrées dans Git et ne sont pas transmises au service informatique. +Ils ne sont ni enregistrés dans Git, ni communiqués au service informatique. -La procédure prend seulement quelques instants." +Cette opération ne doit être effectuée qu'une seule fois." - result=$? + dialog_result=$? - if [ "$result" -ne 0 ]; then + # ------------------------------------------------------ + # Alice ferme la fenêtre d'accueil. + # + # On ne touche PAS à KDE. + # L'assistant sera simplement reproposé. + # ------------------------------------------------------ + + if [ "$dialog_result" -ne 0 ]; then "$KDIALOG" \ --title "Configuration requise" \ --sorry \ "La configuration initiale de votre compte n'est pas terminée. +Cette étape est obligatoire. + L'assistant va être reproposé." ${pkgs.coreutils}/bin/sleep 1 + continue fi # ------------------------------------------------------ - # Lance l'assistant interactif + # Supprime un éventuel fichier actif devenu obsolète. + # ------------------------------------------------------ + + if [ -s "$active_file" ]; then + + assistant_pid="$( + ${pkgs.coreutils}/bin/cat "$active_file" 2>/dev/null || true + )" + + if [ -n "$assistant_pid" ]; then + + if ! ${pkgs.coreutils}/bin/kill -0 "$assistant_pid" 2>/dev/null; then + ${pkgs.coreutils}/bin/rm -f "$active_file" + fi + + else + ${pkgs.coreutils}/bin/rm -f "$active_file" + fi + + fi + + # ------------------------------------------------------ + # Lance l'assistant. # ------------------------------------------------------ "$KONSOLE" \ @@ -315,22 +467,21 @@ L'assistant va être reproposé." -e ${firstLoginSetup} \ >/dev/null 2>&1 & - ${pkgs.coreutils}/bin/sleep 1 + # Laisse au script le temps d'écrire active_file. + ${pkgs.coreutils}/bin/sleep 2 - # ------------------------------------------------------ - # Attend la fin réelle du script. - # ------------------------------------------------------ + # ====================================================== + # Attend la fin réelle de l'assistant + # ====================================================== while true; do - if [ \ - -e "$password_marker" \ - ] && [ \ - -e "$yubikey_marker" \ - ]; then + # Les deux opérations sont terminées. + if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then break fi + # Le script n'est plus déclaré actif. if [ ! -s "$active_file" ]; then break fi @@ -343,23 +494,23 @@ L'assistant va être reproposé." break fi + # Le script a disparu. if ! ${pkgs.coreutils}/bin/kill -0 "$assistant_pid" 2>/dev/null; then - rm -f "$active_file" + + ${pkgs.coreutils}/bin/rm -f "$active_file" + break fi ${pkgs.coreutils}/bin/sleep 1 + done - # ------------------------------------------------------ - # Tout est terminé. - # ------------------------------------------------------ + # ====================================================== + # Tout est terminé + # ====================================================== - if [ \ - -e "$password_marker" \ - ] && [ \ - -e "$yubikey_marker" \ - ]; then + if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then "$KDIALOG" \ --title "Poste configuré" \ @@ -368,17 +519,23 @@ L'assistant va être reproposé." 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. +Pour vos prochaines connexions, utilisez : + + YubiKey + votre PIN personnel Votre mot de passe local reste disponible comme solution de secours." exit 0 fi + # ====================================================== + # Configuration partielle / fenêtre fermée / erreur + # ====================================================== + "$KDIALOG" \ --title "Configuration incomplète" \ --sorry \ - "La configuration n'a pas été entièrement terminée. + "La configuration initiale n'est pas entièrement terminée. Les étapes déjà réalisées sont conservées. @@ -393,6 +550,10 @@ L'assistant va reprendre uniquement les étapes restantes." in { + # ============================================================ + # Lancement automatique lors de l'ouverture de session KDE + # ============================================================ + environment.etc."xdg/autostart/yubikey-first-login.desktop".text = '' [Desktop Entry] Type=Application