Files
nixos-workstations/modules/yubikey-first-login.nix
T

287 lines
7.5 KiB
Nix

{ 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
'';
}