{ pkgs, ... }: let # ============================================================ # Assistant interactif de changement du PIN YubiKey # ============================================================ yubikeyPinChange = pkgs.writeShellScript "yubikey-pin-change" '' set -u state_dir="$HOME/.local/state/nixos-workstations" marker="$state_dir/yubikey-pin-initialized" # ---------------------------------------------------------- # Couleurs ANSI # ---------------------------------------------------------- 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" # ---------------------------------------------------------- # Fonctions d'affichage # ---------------------------------------------------------- separator() { printf "''${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━''${RESET}\n" } header() { printf "\033[2J\033[H" echo separator echo printf " ''${BOLD}''${CYAN}🔐 INITIALISATION DE VOTRE YUBIKEY''${RESET}\n" echo separator echo } step() { number="$1" text="$2" printf " ''${BOLD}''${CYAN}[%s]''${RESET} ''${WHITE}%s''${RESET}\n" \ "$number" "$text" } info() { printf " ''${GREY}%s''${RESET}\n" "$1" } success() { echo separator echo printf " ''${BOLD}''${GREEN}✔ INITIALISATION TERMINÉE''${RESET}\n" echo separator echo } failure() { echo separator echo printf " ''${BOLD}''${RED}✖ INITIALISATION NON TERMINÉE''${RESET}\n" echo separator echo } # ---------------------------------------------------------- # Déjà initialisé # ---------------------------------------------------------- if [ -e "$marker" ]; then exit 0 fi # ---------------------------------------------------------- # Annulation / interruption # ---------------------------------------------------------- trap ' printf "\n\n" printf "''${RED}Initialisation interrompue.''${RESET}\n" exit 130 ' INT TERM # ---------------------------------------------------------- # Écran d'accueil # ---------------------------------------------------------- header printf " ''${WHITE}Bienvenue.''${RESET}\n" echo printf " Pour sécuriser votre accès au poste, vous devez personnaliser\n" printf " le ''${BOLD}PIN de votre YubiKey''${RESET}.\n" echo printf " ''${YELLOW}⚠ Cette opération est obligatoire.''${RESET}\n" echo step "1/3" "Munissez-vous du PIN temporaire fourni par le service informatique." echo step "2/3" "Choisissez un nouveau PIN personnel." info "Ne réutilisez pas le PIN temporaire." echo step "3/3" "Confirmez votre nouveau PIN." echo separator echo printf " ''${GREY}Le PIN est enregistré directement dans votre YubiKey.''${RESET}\n" printf " ''${GREY}Il n'est ni enregistré sur le poste, ni envoyé au service informatique.''${RESET}\n" echo separator echo printf " ''${BOLD}''${WHITE}Insérez votre YubiKey et suivez les instructions.''${RESET}\n" echo printf " ''${YELLOW}Ne fermez pas cette fenêtre.''${RESET}\n" echo separator echo # Petite pause pour que l'utilisateur lise l'écran ${pkgs.coreutils}/bin/sleep 2 # ---------------------------------------------------------- # Changement du PIN # ---------------------------------------------------------- if ${pkgs.yubikey-manager}/bin/ykman fido access change-pin; then # IMPORTANT : # le marqueur n'est créé qu'après retour positif de ykman. ${pkgs.coreutils}/bin/mkdir -p "$state_dir" ${pkgs.coreutils}/bin/touch "$marker" success printf " ''${GREEN}Votre nouveau PIN est maintenant actif.''${RESET}\n" echo printf " Utilisez désormais ce PIN pour vous connecter\n" printf " avec votre YubiKey.\n" echo printf " ''${GREY}Cette procédure ne sera plus affichée.''${RESET}\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 else failure printf " ''${RED}Le PIN de la YubiKey n'a pas été modifié.''${RESET}\n" echo printf " Votre session va être fermée afin de protéger\n" printf " l'accès au poste.\n" echo printf " ''${YELLOW}La procédure sera automatiquement reproposée''${RESET}\n" printf " ''${YELLOW}à votre prochaine connexion.''${RESET}\n" echo separator echo printf " Fermeture de la session" for i in 1 2 3; do printf "." ${pkgs.coreutils}/bin/sleep 1 done echo exit 1 fi ''; # ============================================================ # Superviseur # ============================================================ yubikeyFirstLoginSupervisor = pkgs.writeShellScript "yubikey-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" marker="$state_dir/yubikey-pin-initialized" # Initialisation déjà effectuée. if [ -e "$marker" ]; then exit 0 fi # Laisse KDE terminer son démarrage. ${pkgs.coreutils}/bin/sleep 3 # -------------------------------------------------------- # Assistant plein écran # -------------------------------------------------------- ${pkgs.kdePackages.konsole}/bin/konsole \ --separate \ --fullscreen \ --hide-menubar \ --hide-tabbar \ -e ${yubikeyPinChange} # -------------------------------------------------------- # L'assistant vient de se terminer. # -------------------------------------------------------- if [ -e "$marker" ]; then # PIN correctement changé. exit 0 fi # Pas de marqueur : # # - utilisateur ayant fermé la fenêtre ; # - Ctrl+C ; # - erreur ykman ; # - changement du PIN abandonné. # # Dans tous ces cas, on ferme la session d'Alice. session_id="''${XDG_SESSION_ID:-}" if [ -n "$session_id" ]; then ${pkgs.systemd}/bin/loginctl terminate-session "$session_id" else ${pkgs.systemd}/bin/loginctl terminate-user "$current_user" fi exit 1 ''; in { # ============================================================ # Lancement automatique à l'ouverture de KDE # ============================================================ environment.etc."xdg/autostart/yubikey-first-login.desktop".text = '' [Desktop Entry] Type=Application Name=Initialisation de la YubiKey Comment=Configuration obligatoire de votre PIN personnel Exec=${yubikeyFirstLoginSupervisor} OnlyShowIn=KDE; NoDisplay=true StartupNotify=false ''; }