> **État LAB v1.7 / Étape 2** : systemd-homed + LUKS2 pour Alice. L'enrôlement FIDO2 dans le home viendra à l'étape 3.
# 🛡️ NixOS Workstations ### Déploiement industrialisé de postes de travail NixOS sécurisés ![NixOS](https://img.shields.io/badge/NixOS-26.05-5277C3?style=for-the-badge&logo=nixos&logoColor=white) ![KDE Plasma](https://img.shields.io/badge/KDE_Plasma-6-1D99F3?style=for-the-badge&logo=kde&logoColor=white) ![Security](https://img.shields.io/badge/Sécurité-FIDO2%20%2F%20YubiKey-111827?style=for-the-badge) ![Deployment](https://img.shields.io/badge/Déploiement-Déclaratif-7EBAE4?style=for-the-badge&logo=nixos&logoColor=white) ![Status](https://img.shields.io/badge/Statut-Candidat_Production-2563EB?style=for-the-badge) ![License](https://img.shields.io/badge/Licence-PolyForm_Noncommercial-F59E0B?style=for-the-badge) **Une base déclarative et reproductible pour déployer, sécuriser et maintenir des environnements de bureau NixOS homogènes.**
--- ## 🎯 Objectif **NixOS Workstations** fournit un socle commun permettant de construire un parc de postes de travail NixOS avec : - 🧬 une configuration déclarative versionnée dans Git ; - 📦 un ensemble logiciel homogène ; - 🖥️ KDE Plasma 6 ; - 👤 des comptes locaux maîtrisés ; - 🔐 une authentification locale de secours ; - 🔑 FIDO2 / YubiKey ; - ✨ une finalisation graphique du poste lors de la première utilisation ; - 💻 une séparation stricte entre configuration commune et matériel propre à chaque machine. ```text ┌───────────────────────────┐ │ Git │ │ nixos-workstations │ └─────────────┬─────────────┘ │ ┌────────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ 📦 Logiciels 👤 Utilisateurs 🛡️ Sécurité │ │ │ └────────────────┼────────────────┘ │ ▼ 🖥️ NixOS + KDE Plasma │ 🔐 Mot de passe 🔑 FIDO2 / YubiKey │ ▼ ✅ Poste opérationnel ``` --- ## ✨ Principes | | Principe | Objectif | |---|---|---| | 🧬 | **Déclaratif** | Décrire l'état attendu du poste dans Git | | ♻️ | **Reproductible** | Reconstruire un poste de manière cohérente | | 🧱 | **Modulaire** | Séparer logiciels, utilisateurs, sécurité et UX | | 🔐 | **Natif NixOS** | Utiliser les mécanismes système plutôt que les contourner | | 🔑 | **FIDO2** | Utiliser une clé de sécurité comme moyen d'authentification principal | | 🧰 | **Industrialisable** | Éviter les fichiers de configuration complets spécifiques à chaque poste | | 🧪 | **Validation progressive** | `build` → `dry-activate` → `test` → `switch` | --- ## 🏗️ Architecture ```text nixos-workstations/ ├── configuration.nix ├── LICENSE ├── COMMERCIAL-LICENSE.md ├── PRODUCTION-CHECKLIST.md │ ├── workstation-setup/ │ ├── CMakeLists.txt │ ├── org.raspot.nixosworkstations.setup.desktop │ └── src/ │ ├── CMakeLists.txt │ ├── main.cpp │ ├── Main.qml │ ├── ProvisioningBackend.h │ └── ProvisioningBackend.cpp │ └── modules/ ├── software.nix ├── users.nix ├── security.nix └── workstation-setup.nix ``` ### 💻 Matériel propre à chaque poste Le fichier généré lors de l'installation reste **local à la machine** : ```text /etc/nixos/hardware-configuration.nix ``` Il n'est pas partagé dans le dépôt commun. ```nix imports = [ /etc/nixos/hardware-configuration.nix ./modules/software.nix ./modules/users.nix ./modules/security.nix ./modules/workstation-setup.nix ]; ``` Les UUID de partitions et autres informations propres au matériel ne peuvent ainsi pas écraser la configuration d'un autre poste. --- ## 🧩 Modules ### 📦 `software.nix` Déploie l'environnement logiciel commun : Chromium, Firefox ESR, OnlyOffice, Teams, Outlook Web, Git et les outils FIDO2 nécessaires. ### 👤 `users.nix` Décrit les comptes locaux et leurs rôles. Les mots de passe restent mutables afin que l'utilisateur puisse personnaliser son secret local avec `passwd`. Dans ce **lab**, le mot de passe temporaire d'`alice` est volontairement déclaré dans `users.nix` avec `initialHashedPassword`. ```text Mot de passe temporaire du lab : LaboTest@1980 ``` Avec `users.mutableUsers = true`, ce hash sert à la création initiale du compte. Une fois le mot de passe changé par l'utilisateur, les activations suivantes conservent le nouveau mot de passe local. > Pour un déploiement réel, le dépôt sera privé et la stratégie de secret initial pourra être adaptée au processus d'exploitation. ### 🛡️ `security.nix` Étape 1 LAB : conserve uniquement les règles d’accès à la YubiKey. Aucun mapping U2F et aucune authentification PAM/FIDO2 ne sont activés ; l’enrôlement sera pris en charge ultérieurement par systemd-homed. ### ✨ `workstation-setup.nix` Déploie l'assistant plein écran de finalisation du poste et son lancement automatique pour l'utilisateur concerné. Le nom de l'utilisateur n'est pas codé dans l'application : il est déclaré dans la configuration NixOS : ```nix nixosWorkstations.workstationSetup = { enable = true; user = "alice"; }; ``` --- ## ✨ Finalisation du poste Lors de la première ouverture de session de l'utilisateur :
### 👋 Bienvenue → 🔐 Mot de passe → 🔑 YubiKey → ✅ Poste prêt
### 🔐 Mot de passe local - 👁️ affichage/masquage des champs ; - 📊 indicateur de robustesse purement informatif ; - ✅ mot de passe actuel obligatoire ; - ✅ confirmation du nouveau mot de passe ; - 🟢 aucun blocage UI lié à une robustesse jugée faible ; - 🔒 changement réel effectué par `/run/wrappers/bin/passwd`. ### 🔑 PIN YubiKey - 👁️ affichage/masquage du PIN ; - ✅ PIN temporaire obligatoire ; - ✅ choix et confirmation du nouveau PIN ; - 🔐 changement réel effectué par `ykman fido access change-pin` ; - ⚠️ aucune boucle automatique en cas de mauvais PIN. ### 🚪 Assistant obligatoire Tant que les deux opérations n'ont pas **réellement réussi** : - le bouton final n'est pas disponible ; - une fermeture classique de la fenêtre est refusée ; - une minimisation est immédiatement ramenée en plein écran ; - l'assistant sera reproposé à la prochaine ouverture de session si la configuration reste incomplète. Les étapes ne sont considérées terminées qu'après création des marqueurs : ```text ~/.local/state/nixos-workstations/password-initialized ~/.local/state/nixos-workstations/yubikey-pin-created ``` --- ## 🛡️ Traitement des secrets ```text ┌───────────────────────────────┐ │ Qt Quick / QML │ │ saisie utilisateur │ └───────────────┬───────────────┘ │ pipe privé ▼ ┌───────────────────────────────┐ │ backend Qt contrôlé │ └───────────────┬───────────────┘ │ ┌────────┴────────┐ ▼ ▼ /run/wrappers/bin/ ykman FIDO2 passwd │ │ ▼ ▼ /etc/shadow YubiKey ``` Principes retenus : - 🚫 aucun mot de passe ou PIN dans les arguments de processus ; - 🚫 aucun **secret définitif utilisateur** écrit dans Git ; - 🧪 le mot de passe temporaire du lab est volontairement versionné dans `users.nix` ; - 🚫 aucune modification directe de `/etc/shadow` ; - 🚫 aucun module PAM artisanal ; - 🚫 aucun reset automatique de YubiKey ; - ✅ wrapper `passwd` fourni par NixOS ; - ✅ outil Yubico officiel pour FIDO2 ; - ✅ logs des helpers désactivés ; - ✅ core dumps désactivés pendant le provisioning ; - ✅ une seule tentative FIDO2 par validation utilisateur. --- ## 🔐 Mot de passe temporaire du lab Le compte `alice` est créé avec un mot de passe temporaire connu pour faciliter les essais reproductibles : ```text LaboTest@1980 ``` Son hash est déclaré directement dans : ```text modules/users.nix ``` L'assistant demande ensuite à l'utilisateur de remplacer ce mot de passe temporaire par son mot de passe personnel. Avec `users.mutableUsers = true`, le nouveau mot de passe est conservé lors des activations suivantes. > Cette décision est volontaire pour le **lab**. Elle évite une étape locale supplémentaire avant chaque nouvelle installation de test. --- ## 🧪 Déploiement ### 1. Construction ```bash sudo nixos-rebuild build \ -I nixos-config=/home/localadm/nixos-workstations/configuration.nix ``` ### 2. Simulation d'activation ```bash sudo nixos-rebuild dry-activate \ -I nixos-config=/home/localadm/nixos-workstations/configuration.nix ``` ### 3. Test temporaire ```bash sudo nixos-rebuild test \ -I nixos-config=/home/localadm/nixos-workstations/configuration.nix ``` ### 4. Activation persistante Après validation complète de la checklist : ```bash sudo nixos-rebuild switch \ -I nixos-config=/home/localadm/nixos-workstations/configuration.nix ``` 👉 Voir [`PRODUCTION-CHECKLIST.md`](PRODUCTION-CHECKLIST.md) avant un `switch`. --- ## 🔭 Industrialisation future Le socle est conçu pour évoluer vers : ```text Inventaire / GLPI / CSV │ ▼ Utilisateur + poste + profil matériel │ ▼ Configuration NixOS commune │ ▼ Installation automatisée │ ▼ Finalisation utilisateur FIDO2 ``` Les prochaines briques possibles sont notamment Disko, un inventaire machines/utilisateurs et une installation unattended. --- ## ⚖️ Licence Le projet est distribué sous **PolyForm Noncommercial 1.0.0**. ✅ utilisation et modification non commerciales selon les conditions de la licence ; 🚫 exploitation commerciale sans autorisation ; 💼 une exploitation commerciale peut faire l'objet d'un accord séparé avec le titulaire des droits. Voir [`LICENSE`](LICENSE) et [`COMMERCIAL-LICENSE.md`](COMMERCIAL-LICENSE.md). > Cette licence est *source-available non commerciale* ; elle n'est pas une licence Open Source au sens OSI. --- ## Correctifs v1.2 du setup La version 1.2 durcit la brique `workstation-setup` : - l'utilisateur cible n'est plus compilé dans le binaire ; le lanceur le transmet avec `--target-user` ; - les chemins des helpers sont générés dans `Config.h`, sans macro CMake fragile ; - le binaire ne quitte plus silencieusement en cas de mauvais utilisateur ; - `--diagnose` affiche l'utilisateur courant, l'utilisateur cible et l'état des marqueurs ; - un journal sans secret est écrit dans `~/.local/state/nixos-workstations/setup.log` ; - les buffers explicites contenant des secrets sont effacés dès que possible ; - les timeouts des helpers sont distingués des autres erreurs ; - `programs.yubikey-manager.enable = true` fournit ykman avec les règles udev NixOS nécessaires ; - une seule invocation de `ykman` est effectuée par tentative de changement de PIN. Diagnostic manuel : ```bash nixos-workstations-setup --target-user alice --diagnose ``` Lancement manuel de l'interface : ```bash nixos-workstations-setup --target-user alice ``` ### Correctif v1.2 — contrôle de l’utilisateur La v1.1 pouvait refuser `alice` tout en affichant `alice` comme utilisateur courant et cible à cause d’un ordre d’initialisation incorrect des membres C++. La v1.2 supprime l’état d’autorisation mémorisé et vérifie directement l’UID effectif du processus par rapport à l’UID du compte cible. La compilation traite également les avertissements `reorder` comme des erreurs. ### Correctif v1.3 — changement de mot de passe avec PAM/U2F La configuration conserve U2F pour les services PAM d’authentification, mais le désactive explicitement pour le service `passwd` avec `security.pam.services.passwd.u2f.enable = false;`. Cela évite que le changement de mot de passe lancé par l’assistant soit intercepté par `pam_u2f`. Le message de timeout est également spécifique à l’étape en cours : mot de passe ou YubiKey. ### Correctif v1.4 — dialogue PAM `passwd` Le helper de mot de passe accepte désormais l'invite PAM générique `Password:` pour l'authentification initiale. Les étapes sont suivies explicitement et les erreurs techniques sont journalisées sans secret. ### Correctif v1.5 — changement de PIN FIDO2 direct La v1.5 n'utilise plus `expect` pour piloter les invites texte de `ykman` lors du changement de PIN. Le helper utilise directement `python-fido2` et `ClientPin.change_pin()` sur l'interface CTAP2 de la clé. Les secrets sont transmis au helper par stdin, jamais dans les arguments du processus. Une seule tentative CTAP2 est effectuée par validation. ## Étape 1 v1.6 — YubiKey vierge Cette version valide uniquement l'initialisation d'une YubiKey FIDO2 vierge : - aucun PIN FIDO2 initial ; - aucun `u2f-mappings` dans Git ou `/etc` ; - aucun `pam_u2f` actif ; - le setup demande uniquement le nouveau PIN et sa confirmation ; - `ClientPin.set_pin()` crée le premier PIN ; - si un PIN existe déjà, l'opération est refusée sans tentative de PIN ; - le mot de passe local continue de fonctionner comme dans la v1.5. L'authentification FIDO2 du compte et le chiffrement LUKS2 ne font volontairement pas partie de cette étape.