Actualiser modules/yubikey-first-login.nix

This commit is contained in:
2026-08-18 15:07:31 +02:00
parent 96415babe7
commit 2646fe39e0
+293 -132
View File
@@ -1,6 +1,13 @@
{ pkgs, ... }: { pkgs, ... }:
let 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" '' firstLoginSetup = pkgs.writeShellScript "first-login-setup" ''
set -u set -u
@@ -12,21 +19,26 @@ let
runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}" runtime_dir="''${XDG_RUNTIME_DIR:-/tmp}"
active_file="$runtime_dir/nixos-workstations-first-login.active" active_file="$runtime_dir/nixos-workstations-first-login.active"
# ----------------------------------------------------------
# Permet au superviseur de savoir que l'assistant tourne.
# ----------------------------------------------------------
printf '%s\n' "$$" > "$active_file" printf '%s\n' "$$" > "$active_file"
cleanup() { cleanup() {
rm -f "$active_file" ${pkgs.coreutils}/bin/rm -f "$active_file"
} }
trap cleanup EXIT HUP INT TERM trap cleanup EXIT HUP INT TERM
# ========================================================== # ----------------------------------------------------------
# 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"
@@ -34,27 +46,27 @@ let
GREY="\033[38;5;245m" GREY="\033[38;5;245m"
WHITE="\033[38;5;255m" WHITE="\033[38;5;255m"
line() { separator() {
printf "''${GREY}''${RESET}\n" printf "''${BLUE}''${RESET}\n"
} }
clear clear_screen() {
printf "\033[2J\033[H"
}
echo header() {
echo clear_screen
printf " ''${BOLD}''${CYAN}CONFIGURATION DE VOTRE COMPTE''${RESET}\n"
echo
line
echo
printf " Bienvenue ''${BOLD}Alice''${RESET}.\n" echo
echo separator
printf " Cette procédure termine la préparation de votre poste.\n" echo
printf " Elle ne sera effectuée qu'une seule fois.\n"
echo printf " ''${BOLD}''${CYAN}🔐 CONFIGURATION DE VOTRE COMPTE''${RESET}\n"
line
echo echo
separator
echo
}
# ========================================================== # ==========================================================
# ÉTAPE 1 : MOT DE PASSE LOCAL # ÉTAPE 1 : MOT DE PASSE LOCAL
@@ -62,42 +74,91 @@ let
if [ ! -e "$password_marker" ]; then if [ ! -e "$password_marker" ]; then
printf " ''${BOLD}''${CYAN}ÉTAPE 1 / 2''${RESET}\n" header
echo
printf " ''${BOLD}Choisissez votre mot de passe de secours''${RESET}\n" printf " ''${BOLD}''${CYAN}ÉTAPE 1 SUR 2''${RESET}\n"
echo echo
printf " Ce mot de passe permet notamment d'accéder au poste\n" printf " ''${BOLD}''${WHITE}Personnalisation du mot de passe de secours''${RESET}\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 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/mkdir -p "$state_dir"
${pkgs.coreutils}/bin/touch "$password_marker" ${pkgs.coreutils}/bin/touch "$password_marker"
echo echo
printf " ''${GREEN} Mot de passe modifié avec succès.''${RESET}\n" separator
echo 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 else
echo 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 echo
printf " La procédure sera automatiquement reproposée.\n"
${pkgs.coreutils}/bin/sleep 3 ${pkgs.coreutils}/bin/sleep 3
@@ -110,60 +171,102 @@ let
# ÉTAPE 2 : PIN YUBIKEY # É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 [ ! -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 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/mkdir -p "$state_dir"
${pkgs.coreutils}/bin/touch "$yubikey_marker" ${pkgs.coreutils}/bin/touch "$yubikey_marker"
echo 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 else
echo 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 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 ${pkgs.coreutils}/bin/sleep 3
@@ -173,44 +276,41 @@ let
fi fi
# ========================================================== # ==========================================================
# TERMINÉ # CONFIGURATION TERMINÉE
# ========================================================== # ==========================================================
clear header
printf " ''${BOLD}''${GREEN} VOTRE POSTE EST PRÊT''${RESET}\n"
echo echo
echo separator
line
echo echo
printf " ''${BOLD}''${GREEN} CONFIGURATION TERMINÉE''${RESET}\n" printf " La configuration initiale de votre compte est terminée.\n"
echo echo
line printf " ''${GREEN}''${RESET} Mot de passe personnel configuré\n"
echo printf " ''${GREEN}''${RESET} PIN personnel YubiKey configuré\n"
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
separator
echo echo
printf " Pour vos prochaines connexions :\n" printf " ''${BOLD}Pour vos prochaines connexions :''${RESET}\n"
echo echo
printf " ''${BOLD}YubiKey + votre PIN personnel''${RESET}\n" printf " ''${BOLD}YubiKey + PIN personnel''${RESET}\n"
echo echo
printf " Votre mot de passe local reste disponible comme solution\n" 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 echo
line separator
echo echo
printf " Fermeture automatique" printf " Fermeture automatique"
for i in 1 2 3 4 5; do for i in 1 2 3 4 5; do
printf "." printf "."
@@ -218,16 +318,26 @@ let
done done
echo echo
exit 0 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 = firstLoginSupervisor =
pkgs.writeShellScript "first-login-supervisor" '' pkgs.writeShellScript "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
@@ -245,23 +355,29 @@ let
KDIALOG="${pkgs.kdePackages.kdialog}/bin/kdialog" KDIALOG="${pkgs.kdePackages.kdialog}/bin/kdialog"
KONSOLE="${pkgs.kdePackages.konsole}/bin/konsole" KONSOLE="${pkgs.kdePackages.konsole}/bin/konsole"
# Une seule instance du superviseur. # --------------------------------------------------------
# Empêche deux superviseurs de fonctionner simultanément.
# --------------------------------------------------------
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. # --------------------------------------------------------
# Tout est déjà configuré.
# --------------------------------------------------------
if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then
exit 0 exit 0
fi fi
# Laisse Plasma terminer son démarrage. # Laisse Plasma finir son démarrage.
${pkgs.coreutils}/bin/sleep 3 ${pkgs.coreutils}/bin/sleep 4
# ======================================================== # ========================================================
# Présentation # Boucle de provisioning
# ======================================================== # ========================================================
while \ while \
@@ -269,6 +385,10 @@ let
[ ! -e "$yubikey_marker" ] [ ! -e "$yubikey_marker" ]
do do
# ------------------------------------------------------
# Présentation KDE
# ------------------------------------------------------
"$KDIALOG" \ "$KDIALOG" \
--title "Finalisation de votre poste" \ --title "Finalisation de votre poste" \
--warningcontinuecancel \ --warningcontinuecancel \
@@ -276,35 +396,67 @@ let
Votre poste est presque prêt. 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" \ "$KDIALOG" \
--title "Configuration requise" \ --title "Configuration requise" \
--sorry \ --sorry \
"La configuration initiale de votre compte n'est pas terminée. "La configuration initiale de votre compte n'est pas terminée.
Cette étape est obligatoire.
L'assistant va être reproposé." L'assistant va être reproposé."
${pkgs.coreutils}/bin/sleep 1 ${pkgs.coreutils}/bin/sleep 1
continue continue
fi 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" \ "$KONSOLE" \
@@ -315,22 +467,21 @@ L'assistant va être reproposé."
-e ${firstLoginSetup} \ -e ${firstLoginSetup} \
>/dev/null 2>&1 & >/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 while true; do
if [ \ # Les deux opérations sont terminées.
-e "$password_marker" \ if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then
] && [ \
-e "$yubikey_marker" \
]; then
break break
fi fi
# Le script n'est plus déclaré actif.
if [ ! -s "$active_file" ]; then if [ ! -s "$active_file" ]; then
break break
fi fi
@@ -343,23 +494,23 @@ L'assistant va être reproposé."
break break
fi fi
# Le script a disparu.
if ! ${pkgs.coreutils}/bin/kill -0 "$assistant_pid" 2>/dev/null; then if ! ${pkgs.coreutils}/bin/kill -0 "$assistant_pid" 2>/dev/null; then
rm -f "$active_file"
${pkgs.coreutils}/bin/rm -f "$active_file"
break break
fi fi
${pkgs.coreutils}/bin/sleep 1 ${pkgs.coreutils}/bin/sleep 1
done done
# ------------------------------------------------------ # ======================================================
# Tout est terminé. # Tout est terminé
# ------------------------------------------------------ # ======================================================
if [ \ if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then
-e "$password_marker" \
] && [ \
-e "$yubikey_marker" \
]; then
"$KDIALOG" \ "$KDIALOG" \
--title "Poste configuré" \ --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. 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." Votre mot de passe local reste disponible comme solution de secours."
exit 0 exit 0
fi fi
# ======================================================
# Configuration partielle / fenêtre fermée / erreur
# ======================================================
"$KDIALOG" \ "$KDIALOG" \
--title "Configuration incomplète" \ --title "Configuration incomplète" \
--sorry \ --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. Les étapes déjà réalisées sont conservées.
@@ -393,6 +550,10 @@ L'assistant va reprendre uniquement les étapes restantes."
in in
{ {
# ============================================================
# Lancement automatique lors de l'ouverture de session 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