Actualiser modules/yubikey-first-login.nix

This commit is contained in:
2026-08-18 14:33:45 +02:00
parent be3d312dca
commit adf44ca2fe
+279 -211
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,286 +34,371 @@ 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"
echo if [ ! -e "$password_marker" ]; then
separator
echo
printf " ''${BOLD}''${WHITE}Suivez maintenant les instructions ci-dessous.''${RESET}\n"
echo
# ----------------------------------------------------------
# Changement du PIN
# ----------------------------------------------------------
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/touch "$marker"
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}''${GREEN} INITIALISATION TERMINÉE''${RESET}\n" printf " Ce mot de passe permet notamment d'accéder au poste\n"
printf " si votre YubiKey est indisponible.\n"
echo echo
separator printf " ''${YELLOW}Vous allez saisir :''${RESET}\n"
echo echo
printf " votre mot de passe temporaire actuel\n"
printf " ''${GREEN}Votre nouveau PIN est maintenant actif.''${RESET}\n" printf " votre nouveau mot de passe personnel\n"
echo printf " une confirmation du nouveau mot de passe\n"
printf " Utilisez désormais ce nouveau PIN pour vous\n"
printf " connecter avec votre YubiKey.\n"
echo echo
printf " ''${GREY}Cette procédure ne sera plus affichée.''${RESET}\n" line
echo
separator
echo echo
printf " Fermeture automatique" if ${pkgs.shadow}/bin/passwd; then
for i in 1 2 3 4 5; do ${pkgs.coreutils}/bin/mkdir -p "$state_dir"
printf "." ${pkgs.coreutils}/bin/touch "$password_marker"
${pkgs.coreutils}/bin/sleep 1
done
echo echo
exit 0 printf " ''${GREEN} Mot de passe modifié avec succès.''${RESET}\n"
echo
else ${pkgs.coreutils}/bin/sleep 2
# -------------------------------------------------------- else
# Échec / annulation
#
# Aucun marqueur n'est créé.
# Le superviseur relancera automatiquement l'assistant.
# --------------------------------------------------------
echo echo
separator printf " ''${RED} Le changement du mot de passe a échoué.''${RESET}\n"
echo echo
printf " La procédure sera automatiquement reproposée.\n"
printf " ''${BOLD}''${RED} INITIALISATION NON TERMINÉE''${RESET}\n" ${pkgs.coreutils}/bin/sleep 3
echo exit 1
separator fi
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 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 =
# 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.
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
# ------------------------------------------------------ # ------------------------------------------------------
# Vérifie si l'assistant précédemment lancé tourne # Lance l'assistant interactif
# réellement toujours.
# ------------------------------------------------------ # ------------------------------------------------------
if [ -s "$active_file" ]; then "$KONSOLE" \
--separate \
--fullscreen \
--hide-menubar \
--hide-tabbar \
-e ${firstLoginSetup} \
>/dev/null 2>&1 &
assistant_pid="$(${pkgs.coreutils}/bin/cat "$active_file" 2>/dev/null || true)" ${pkgs.coreutils}/bin/sleep 1
if [ -n "$assistant_pid" ] \ # ------------------------------------------------------
&& ${pkgs.coreutils}/bin/kill -0 "$assistant_pid" 2>/dev/null; then # Attend la fin réelle du script.
# ------------------------------------------------------
assistant_running=1 while true; do
else
# Fichier devenu obsolète.
rm -f "$active_file"
if [ \
-e "$password_marker" \
] && [ \
-e "$yubikey_marker" \
]; then
break
fi 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
# ------------------------------------------------------ # ------------------------------------------------------
# Aucun assistant actif : # Tout est terminé.
# on en ouvre un.
# ------------------------------------------------------ # ------------------------------------------------------
if [ "$assistant_running" -eq 0 ]; then if [ \
-e "$password_marker" \
] && [ \
-e "$yubikey_marker" \
]; then
${pkgs.kdePackages.konsole}/bin/konsole \ "$KDIALOG" \
--separate \ --title "Poste configuré" \
--fullscreen \ --msgbox \
--hide-menubar \ " Votre poste est prêt.
--hide-tabbar \
-e ${yubikeyPinChange} \
>/dev/null 2>&1 &
# Laisse le temps à Konsole et au script de démarrer. Votre mot de passe personnel et le PIN de votre YubiKey ont été configurés.
${pkgs.coreutils}/bin/sleep 2
else Pour vos prochaines connexions, utilisez votre YubiKey et votre nouveau PIN.
${pkgs.coreutils}/bin/sleep 2 Votre mot de passe local reste disponible comme solution de secours."
exit 0
fi 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 done
# --------------------------------------------------------
# Le marqueur existe :
# l'initialisation est terminée.
#
# On ne touche PAS à la session KDE.
# --------------------------------------------------------
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