{ pkgs, ... }: let firstLoginSetup = pkgs.writeShellScript "first-login-setup" '' set -u state_dir="$HOME/.local/state/nixos-workstations" password_marker="$state_dir/password-initialized" yubikey_marker="$state_dir/yubikey-pin-initialized" runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}" active_file="$runtime_dir/nixos-workstations-first-login.active" printf '%s\n' "$$" > "$active_file" cleanup() { rm -f "$active_file" } trap cleanup EXIT HUP INT TERM # ========================================================== # Couleurs # ========================================================== RESET="\033[0m" BOLD="\033[1m" CYAN="\033[38;5;45m" GREEN="\033[38;5;82m" YELLOW="\033[38;5;220m" RED="\033[38;5;196m" GREY="\033[38;5;245m" WHITE="\033[38;5;255m" line() { printf "''${GREY}────────────────────────────────────────────────────────────''${RESET}\n" } clear echo echo printf " ''${BOLD}''${CYAN}CONFIGURATION DE VOTRE COMPTE''${RESET}\n" echo line echo 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 line echo # ========================================================== # ÉTAPE 1 : MOT DE PASSE LOCAL # ========================================================== 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" 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 echo if ${pkgs.shadow}/bin/passwd; then ${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 ${pkgs.coreutils}/bin/mkdir -p "$state_dir" ${pkgs.coreutils}/bin/touch "$yubikey_marker" echo printf " ''${GREEN}✓ PIN YubiKey modifié avec succès.''${RESET}\n" ${pkgs.coreutils}/bin/sleep 2 else echo printf " ''${RED}✗ Le changement du PIN n'a pas été terminé.''${RESET}\n" 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 exit 1 fi fi # ========================================================== # TERMINÉ # ========================================================== clear echo echo line echo printf " ''${BOLD}''${GREEN}✓ CONFIGURATION TERMINÉE''${RESET}\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" 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 printf " Fermeture automatique" for i in 1 2 3 4 5; do printf "." ${pkgs.coreutils}/bin/sleep 1 done echo exit 0 ''; firstLoginSupervisor = pkgs.writeShellScript "first-login-supervisor" '' set -u current_user="$(${pkgs.coreutils}/bin/id -un)" # Pour le moment uniquement Alice. if [ "$current_user" != "alice" ]; then exit 0 fi state_dir="$HOME/.local/state/nixos-workstations" password_marker="$state_dir/password-initialized" yubikey_marker="$state_dir/yubikey-pin-initialized" runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}" active_file="$runtime_dir/nixos-workstations-first-login.active" 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. 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. if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then exit 0 fi # Laisse Plasma terminer son démarrage. ${pkgs.coreutils}/bin/sleep 3 # ======================================================== # Présentation # ======================================================== while \ [ ! -e "$password_marker" ] || \ [ ! -e "$yubikey_marker" ] do "$KDIALOG" \ --title "Finalisation de votre poste" \ --warningcontinuecancel \ "Bienvenue Alice. Votre poste est presque prêt. Pour terminer sa configuration, vous devez personnaliser deux éléments de sécurité : 🔑 Votre mot de passe local de secours 🔐 Le PIN de votre YubiKey Ces informations deviennent personnelles. Elles ne sont pas enregistrées dans Git et ne sont pas transmises au service informatique. La procédure prend seulement quelques instants." 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 # ------------------------------------------------------ # Lance l'assistant interactif # ------------------------------------------------------ "$KONSOLE" \ --separate \ --fullscreen \ --hide-menubar \ --hide-tabbar \ -e ${firstLoginSetup} \ >/dev/null 2>&1 & ${pkgs.coreutils}/bin/sleep 1 # ------------------------------------------------------ # Attend la fin réelle du script. # ------------------------------------------------------ while true; do if [ \ -e "$password_marker" \ ] && [ \ -e "$yubikey_marker" \ ]; then break 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 # ------------------------------------------------------ # Tout est terminé. # ------------------------------------------------------ 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 ''; in { environment.etc."xdg/autostart/yubikey-first-login.desktop".text = '' [Desktop Entry] Type=Application Name=Finalisation du poste Comment=Configuration initiale du compte utilisateur Exec=${firstLoginSupervisor} OnlyShowIn=KDE; NoDisplay=true StartupNotify=false ''; }