567 lines
15 KiB
Nix
567 lines
15 KiB
Nix
{ 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
|
|
|
|
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"
|
|
|
|
# ----------------------------------------------------------
|
|
# Permet au superviseur de savoir que l'assistant tourne.
|
|
# ----------------------------------------------------------
|
|
|
|
printf '%s\n' "$$" > "$active_file"
|
|
|
|
cleanup() {
|
|
${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"
|
|
RED="\033[38;5;196m"
|
|
GREY="\033[38;5;245m"
|
|
WHITE="\033[38;5;255m"
|
|
|
|
separator() {
|
|
printf "''${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━''${RESET}\n"
|
|
}
|
|
|
|
clear_screen() {
|
|
printf "\033[2J\033[H"
|
|
}
|
|
|
|
header() {
|
|
clear_screen
|
|
|
|
echo
|
|
separator
|
|
echo
|
|
|
|
printf " ''${BOLD}''${CYAN}🔐 CONFIGURATION DE VOTRE COMPTE''${RESET}\n"
|
|
|
|
echo
|
|
separator
|
|
echo
|
|
}
|
|
|
|
# ==========================================================
|
|
# ÉTAPE 1 : MOT DE PASSE LOCAL
|
|
# ==========================================================
|
|
|
|
if [ ! -e "$password_marker" ]; then
|
|
|
|
header
|
|
|
|
printf " ''${BOLD}''${CYAN}ÉTAPE 1 SUR 2''${RESET}\n"
|
|
echo
|
|
|
|
printf " ''${BOLD}''${WHITE}Personnalisation du mot de passe de secours''${RESET}\n"
|
|
echo
|
|
|
|
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
|
|
separator
|
|
echo
|
|
|
|
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
|
|
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
|
|
|
|
${pkgs.coreutils}/bin/sleep 3
|
|
|
|
exit 1
|
|
fi
|
|
|
|
fi
|
|
|
|
# ==========================================================
|
|
# ÉTAPE 2 : PIN YUBIKEY
|
|
# ==========================================================
|
|
|
|
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
|
|
separator
|
|
echo
|
|
|
|
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
|
|
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
|
|
|
|
${pkgs.coreutils}/bin/sleep 3
|
|
|
|
exit 1
|
|
fi
|
|
|
|
fi
|
|
|
|
# ==========================================================
|
|
# CONFIGURATION TERMINÉE
|
|
# ==========================================================
|
|
|
|
header
|
|
|
|
printf " ''${BOLD}''${GREEN}✓ VOTRE POSTE EST PRÊT''${RESET}\n"
|
|
|
|
echo
|
|
separator
|
|
echo
|
|
|
|
printf " La configuration initiale de votre compte est terminée.\n"
|
|
|
|
echo
|
|
printf " ''${GREEN}✓''${RESET} Mot de passe personnel configuré\n"
|
|
printf " ''${GREEN}✓''${RESET} PIN personnel YubiKey configuré\n"
|
|
|
|
echo
|
|
separator
|
|
echo
|
|
|
|
printf " ''${BOLD}Pour vos prochaines connexions :''${RESET}\n"
|
|
|
|
echo
|
|
printf " ''${BOLD}YubiKey + PIN personnel''${RESET}\n"
|
|
|
|
echo
|
|
printf " Votre mot de passe local reste disponible comme solution\n"
|
|
printf " de secours si votre YubiKey est indisponible.\n"
|
|
|
|
echo
|
|
separator
|
|
echo
|
|
|
|
printf " Fermeture automatique"
|
|
|
|
for i in 1 2 3 4 5; do
|
|
printf "."
|
|
${pkgs.coreutils}/bin/sleep 1
|
|
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.
|
|
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"
|
|
|
|
# --------------------------------------------------------
|
|
# Empêche deux superviseurs de fonctionner simultanément.
|
|
# --------------------------------------------------------
|
|
|
|
exec 9>"$supervisor_lock"
|
|
|
|
if ! ${pkgs.util-linux}/bin/flock -n 9; then
|
|
exit 0
|
|
fi
|
|
|
|
# --------------------------------------------------------
|
|
# Tout est déjà configuré.
|
|
# --------------------------------------------------------
|
|
|
|
if [ -e "$password_marker" ] && [ -e "$yubikey_marker" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Laisse Plasma finir son démarrage.
|
|
${pkgs.coreutils}/bin/sleep 4
|
|
|
|
# ========================================================
|
|
# Boucle de provisioning
|
|
# ========================================================
|
|
|
|
while \
|
|
[ ! -e "$password_marker" ] || \
|
|
[ ! -e "$yubikey_marker" ]
|
|
do
|
|
|
|
# ------------------------------------------------------
|
|
# Présentation KDE
|
|
# ------------------------------------------------------
|
|
|
|
"$KDIALOG" \
|
|
--title "Finalisation de votre poste" \
|
|
--warningcontinuecancel \
|
|
"Bienvenue Alice.
|
|
|
|
Votre poste est presque prêt.
|
|
|
|
Pour terminer sa configuration, vous devez personnaliser vos deux moyens d'authentification :
|
|
|
|
🔑 Votre mot de passe local de secours
|
|
|
|
🔐 Le PIN de votre YubiKey
|
|
|
|
Les nouveaux secrets que vous choisirez sont personnels.
|
|
|
|
Ils ne sont ni enregistrés dans Git, ni communiqués au service informatique.
|
|
|
|
Cette opération ne doit être effectuée qu'une seule fois."
|
|
|
|
dialog_result=$?
|
|
|
|
# ------------------------------------------------------
|
|
# 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
|
|
|
|
# ------------------------------------------------------
|
|
# 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" \
|
|
--separate \
|
|
--fullscreen \
|
|
--hide-menubar \
|
|
--hide-tabbar \
|
|
-e ${firstLoginSetup} \
|
|
>/dev/null 2>&1 &
|
|
|
|
# Laisse au script le temps d'écrire active_file.
|
|
${pkgs.coreutils}/bin/sleep 2
|
|
|
|
# ======================================================
|
|
# Attend la fin réelle de l'assistant
|
|
# ======================================================
|
|
|
|
while true; do
|
|
|
|
# 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
|
|
|
|
assistant_pid="$(
|
|
${pkgs.coreutils}/bin/cat "$active_file" 2>/dev/null || true
|
|
)"
|
|
|
|
if [ -z "$assistant_pid" ]; then
|
|
break
|
|
fi
|
|
|
|
# Le script a disparu.
|
|
if ! ${pkgs.coreutils}/bin/kill -0 "$assistant_pid" 2>/dev/null; then
|
|
|
|
${pkgs.coreutils}/bin/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 :
|
|
|
|
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 initiale n'est pas 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
|
|
{
|
|
# ============================================================
|
|
# Lancement automatique lors de l'ouverture de session KDE
|
|
# ============================================================
|
|
|
|
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
|
|
'';
|
|
} |