linux:ca-ssh
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Prochaine révision | Révision précédente | ||
| linux:ca-ssh [2026/06/03 13:12] – créée root | linux:ca-ssh [2026/06/03 18:23] (Version actuelle) – [Étape 4.2 : Signature par la CA Yubikey] root | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | # Setup CA SSH pour Make IT Simple | + | ====== |
| Guide complet pour mettre en place une autorité de certification SSH dans un contexte MSP, avec support multi-Yubikey et intégration dans l' | Guide complet pour mettre en place une autorité de certification SSH dans un contexte MSP, avec support multi-Yubikey et intégration dans l' | ||
| - | --- | + | **Architecture allégée** : la clé privée de la CA est stockée sur une Yubikey 5 NFC dédiée (slot PIV), pas sur disque. Un backup d' |
| + | |||
| + | ---- | ||
| - | ## Compatibilité Windows | + | ===== Compatibilité Windows |
| **Réponse courte** : oui, mais avec une distinction importante entre les rôles. | **Réponse courte** : oui, mais avec une distinction importante entre les rôles. | ||
| - | | Rôle | Système | + | ^ Rôle ^ Système |
| - | |------|---------|-------| | + | | **Poste de signature** (utilisation Yubikey CA) | Windows / Linux / macOS | OpenSSH |
| - | | **Machine CA** (signature des certifs) | Linux (LXC Proxmox) | + | | **Poste technicien** (utilisation Yubikey |
| - | | **Poste technicien** (utilisation Yubikey) | Windows / Linux / macOS | OpenSSH inclus dans Windows 10/11 (1809+) | | + | |
| | **Serveurs clients** (qui acceptent les certifs) | Linux principalement | Windows Server avec OpenSSH for Windows fonctionne aussi | | | **Serveurs clients** (qui acceptent les certifs) | Linux principalement | Windows Server avec OpenSSH for Windows fonctionne aussi | | ||
| **Côté Windows pour les techniciens** : | **Côté Windows pour les techniciens** : | ||
| - | - OpenSSH client/ | + | * OpenSSH client/ |
| - | - Vérification : `Get-WindowsCapability -Online | ? Name -like ' | + | |
| - | - Installation si absent : `Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0` | + | |
| - | - Pour les versions récentes d' | + | |
| - | - Le support FIDO2/ | + | |
| - | - L' | + | |
| - | **Côté machine | + | **Pour signer avec la Yubikey |
| - | --- | + | ---- |
| - | ## Notes Debian 13 (Trixie) | + | ===== Notes Debian 13 (Trixie) |
| Cette documentation cible Debian 13 (codename **Trixie**), | Cette documentation cible Debian 13 (codename **Trixie**), | ||
| - | ### Versions embarquées | + | ==== Versions embarquées |
| - | | Composant | + | ^ Composant |
| - | |-----------|---------------------|--------------------| | + | |
| | OpenSSH | 9.2p1 | 10.0p1 | | | OpenSSH | 9.2p1 | 10.0p1 | | ||
| | systemd | 252 | 257 | | | systemd | 252 | 257 | | ||
| Ligne 40: | Ligne 40: | ||
| | Python | 3.11 | 3.13 | | | Python | 3.11 | 3.13 | | ||
| - | ### Changements pertinents pour la CA SSH | + | ==== Changements pertinents pour la CA SSH ==== |
| **OpenSSH 10.0** : meilleurs algos par défaut, mais surtout : | **OpenSSH 10.0** : meilleurs algos par défaut, mais surtout : | ||
| - | - Les **clés DSA ne sont plus supportées du tout**, même avec les options de compat (`HostKeyAlgorithms`, `PubkeyAcceptedAlgorithms`). Aucun impact pour nous (on n' | + | * Les **clés DSA ne sont plus supportées du tout**, même avec les options de compat ('' |
| - | - Le support FIDO2 (libfido2) est plus mature qu'en Bookworm. | + | |
| - | - Les algorithmes post-quantum (mlkem768x25519-sha256) sont disponibles par défaut pour le key exchange. | + | |
| - | **`/tmp` est maintenant un tmpfs** en Trixie (RAM). Aucun impact sur nos workflows (les `.pub` font quelques centaines d' | + | ==== Support |
| - | **`/ | + | |
| + | * LTS jusqu'à **juin 2030** | ||
| - | **openssh-server ne lit plus `~/ | + | C'est donc une base saine pour démarrer une infra MSP qui doit vivre 4-5 ans sans upgrade majeur. |
| - | ### Support à long terme | + | ---- |
| - | - Full support jusqu'à **août 2028** | + | ===== Vue d'ensemble de l'architecture ===== |
| - | - LTS jusqu'à **juin 2030** | + | |
| - | C'est donc une base saine pour démarrer une infra MSP qui doit vivre 4-5 ans sans upgrade majeur. | + | < |
| + | ┌──────────────────────────┐ | ||
| + | │ Poste de signature | ||
| + | │ (laptop MIS Vincent) | ||
| + | │ │ | ||
| + | │ ┌────────────────────┐ | ||
| + | │ │ Yubikey CA dédiée | ||
| + | │ │ (slot PIV 9c) │ │ │ via PKCS# | ||
| + | │ │ ECCP384 | ||
| + | │ │ touch CACHED | ||
| + | │ └────────────────────┘ | ||
| + | │ │ | ||
| + | │ ┌────────────────────┐ | ||
| + | │ │ Fichier emergency | ||
| + | │ │ chiffré age │ │ | ||
| + | │ │ dans Bitwarden | ||
| + | │ └────────────────────┘ | ||
| + | └──────────────────────────┘ | ||
| + | │ | ||
| + | │ déploiement via Ansible | ||
| + | ▼ | ||
| + | ┌──────────────────────────────────┐ | ||
| + | │ Serveurs clients | ||
| + | │ / | ||
| + | │ (200+ VMs) │ 1. Yubikey CA pub | ||
| + | │ │ 2. Emergency CA pub | ||
| + | │ / | ||
| + | └──────────────────────────────────┘ | ||
| + | </ | ||
| - | ### Images officielles | + | **Le principe** : |
| + | * La CA quotidienne vit sur Yubikey PIV → clé privée non-extractible, | ||
| + | * La CA emergency est un fichier classique chiffré avec '' | ||
| + | * Les **deux** clés publiques sont déployées sur les serveurs comme CAs valides | ||
| + | * En cas de perte de la Yubikey CA, on déchiffre l' | ||
| - | - Cloud image : https:// | + | ---- |
| - | - Template LXC Proxmox : `debian-13-standard_13.X-Y_amd64.tar.zst` (récupérable via `pveam`) | + | |
| - | --- | + | ===== Phase 1 : Préparation du poste de signature ===== |
| - | ## Vue d' | + | ==== Étape 1.1 : Matériel requis ==== |
| - | ``` | + | |
| - | ┌──────────────────┐ | + | |
| - | │ Yubikey | + | |
| - | │ par tech | + | |
| - | └────────┬─────────┘ | + | |
| - | │ .pub envoyée à Odoo | + | |
| - | ▼ | + | |
| - | ┌──────────────────┐ | + | |
| - | │ Odoo │ ──API──►│ | + | |
| - | │ makeitsimple_ | + | |
| - | │ | + | |
| - | │ │ à la │ | + | |
| - | │ │ demande│ | + | |
| - | └────────┬─────────┘ | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | │ | + | |
| - | │ | + | |
| - | │ déploiement | + | |
| - | ▼ | + | |
| - | ┌──────────────────┐ | + | |
| - | │ Serveurs | + | |
| - | │ clients | + | |
| - | │ (200+ VMs) | + | |
| - | └──────────────────┘ | + | |
| - | ``` | + | |
| - | --- | + | ==== Étape 1.2 : Installation des outils ==== |
| - | ## Phase 1 : Préparation de la LXC CA | + | **Sur Debian / Ubuntu / WSL2** |
| - | ### Étape 1.1 : Création du conteneur | + | <code bash> |
| + | sudo apt update | ||
| + | sudo apt install -y \ | ||
| + | openssh-client \ | ||
| + | yubikey-manager \ | ||
| + | opensc \ | ||
| + | age | ||
| + | </ | ||
| - | Sur le Proxmox MIS (pas un hyperviseur client) : | + | **Sur macOS** |
| - | ```bash | + | < |
| - | # Variables | + | brew install yubikey-manager opensc age openssh |
| - | CTID=200 | + | </ |
| - | HOSTNAME=" | + | |
| - | STORAGE=" | + | |
| - | BRIDGE=" | + | |
| - | TEMPLATE=" | + | |
| - | # Vérifier le nom exact disponible avec : | + | |
| - | # pveam update && pveam available | grep debian-13 | + | |
| - | # Et télécharger si pas encore présent : | + | |
| - | # pveam download local debian-13-standard_13.5-1_amd64.tar.zst | + | |
| - | # Création LXC | + | **Sur Windows** |
| - | pct create $CTID local:vztmpl/ | + | |
| - | --hostname $HOSTNAME \ | + | |
| - | --cores 1 --memory 512 --swap 256 \ | + | |
| - | --rootfs $STORAGE:8 \ | + | |
| - | --net0 name=eth0, | + | |
| - | --nameserver 10.10.10.1 \ | + | |
| - | --onboot 0 \ | + | |
| - | --start 0 \ | + | |
| - | --unprivileged 1 \ | + | |
| - | --features nesting=0, | + | |
| - | --password " | + | |
| - | # Démarrage | + | <code powershell> |
| - | pct start $CTID | + | # Yubikey Manager : https:// |
| - | ``` | + | # Installer aussi yubico-piv-tool qui contient ykcs11.dll |
| + | # OpenSSH inclus avec Windows 10/11 (sinon : Add-WindowsCapability) | ||
| + | # age : winget install FiloSottile.age | ||
| + | </ | ||
| - | ### Étape 1.2 : Durcissement initial | + | ==== Étape 1.3 : Localisation du provider PKCS#11 ==== |
| - | ```bash | + | Cette information est cruciale pour les commandes de signature. Note le chemin selon ton OS : |
| - | # Entrer dans la LXC | + | |
| - | pct enter $CTID | + | |
| - | # Hardening de base | + | ^ OS ^ Chemin PKCS#11 (OpenSC) ^ |
| - | apt update && apt upgrade | + | | Debian/ |
| - | apt install | + | | Debian/ |
| + | | macOS (Intel) | ''/ | ||
| + | | macOS (Apple Silicon) | ''/ | ||
| + | | Windows | '' | ||
| - | # Firewall | + | Vérification rapide qu'il existe |
| - | ufw default deny incoming | + | |
| - | ufw default deny outgoing | + | |
| - | ufw allow from 10.10.10.0/ | + | |
| - | ufw allow out 53/ | + | |
| - | ufw allow out 80, | + | |
| - | ufw enable | + | |
| - | # Utilisateur dédié pour la signature | + | <code bash> |
| - | useradd -m -s /bin/bash ca-signer | + | # Linux/macOS |
| - | mkdir -p / | + | ls -la $PKCS11_PATH |
| - | chmod 700 / | + | </code> |
| - | # Désactivation auth password sur SSH | + | Pour la suite du document, on utilisera la variable |
| - | sed -i 's/ | + | |
| - | sed -i 's/ | + | |
| - | systemctl restart ssh | + | |
| - | ``` | + | |
| - | ### Étape 1.3 : Stockage chiffré (optionnel mais recommandé) | + | <code bash> |
| + | export PKCS11=/ | ||
| + | </ | ||
| - | Pour aller plus loin, la rootfs | + | ==== Étape 1.4 : Initialisation des PINs de la Yubikey CA ==== |
| - | ```bash | + | ⚠️ **Yubikey CA branchée**. Vérifie que c'est la bonne (pas une Yubikey SSH du quotidien) : |
| - | # Sur l'hôte Proxmox | + | |
| - | zfs create -o encryption=aes-256-gcm -o keyformat=passphrase rpool/ | + | |
| - | # La passphrase sera demandée à chaque démarrage de l' | + | |
| - | ``` | + | |
| - | --- | + | <code bash> |
| + | ykman info | ||
| + | # Doit afficher le serial number de la Yubikey CA | ||
| + | </ | ||
| - | ## Phase 2 : Génération des CAs | + | **PIN PIV** (8 caractères minimum, sera demandé à chaque session de signature) |
| - | ### Étape 2.1 : CA pour les utilisateurs (techniciens) | + | <code bash> |
| + | ykman piv access change-pin | ||
| + | # Default PIN: 123456 | ||
| + | # New PIN: [choisir 8+ chars] | ||
| + | </ | ||
| - | ```bash | + | **PUK** (utilisé pour débloquer si trop d' |
| - | # Connecté en tant que ca-signer | + | |
| - | mkdir -p ~/mis-ca && cd ~/mis-ca | + | < |
| + | ykman piv access change-puk | ||
| + | # Default PUK: 12345678 | ||
| + | # New PUK: [générer 8 chars aléatoires] | ||
| + | </ | ||
| + | |||
| + | **Management Key** (utilisée pour les opérations admin PIV, on la protège avec le PIN) : | ||
| + | |||
| + | <code bash> | ||
| + | ykman piv access change-management-key --algorithm AES256 --generate --protect | ||
| + | # --protect = stocke la management key chiffrée par le PIN | ||
| + | </ | ||
| + | |||
| + | 📋 **Notes à conserver | ||
| + | * Serial number de la Yubikey | ||
| + | * PIN PIV | ||
| + | * PUK | ||
| + | * (la management key est protégée par le PIN, pas besoin de la stocker à part) | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Phase 2 : Génération des CAs ===== | ||
| + | |||
| + | ==== Étape 2.1 : CA principale sur Yubikey (users) ==== | ||
| + | |||
| + | <code bash> | ||
| + | # Yubikey CA branchée | ||
| + | mkdir -p ~/mis-ssh-ca && cd ~/mis-ssh-ca | ||
| chmod 700 . | chmod 700 . | ||
| - | ssh-keygen | + | # Génération de la paire ECCP384 dans le slot 9c (Digital Signature) |
| - | -f mis-users-ca \ | + | ykman piv keys generate \ |
| - | -C "MIS Users CA - Make IT Simple" | + | |
| - | -N ' | + | --pin-policy ONCE \ |
| - | ``` | + | --touch-policy CACHED |
| + | | ||
| + | mis-users-ca-yubi-cert.pub | ||
| + | # → demande le PIN | ||
| + | # → demande le touch | ||
| + | </ | ||
| - | ### Étape 2.2 : CA pour les hôtes (serveurs) | + | Décortiquons |
| - | ```bash | + | ^ Option ^ Valeur ^ Sens ^ |
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | |||
| + | **Alternative plus stricte** : '' | ||
| + | |||
| + | ==== Étape 2.2 : Certificat self-signed PIV ==== | ||
| + | |||
| + | PIV exige qu'un certificat X.509 soit présent dans le slot, même s'il ne sert à rien dans notre usage SSH : | ||
| + | |||
| + | < | ||
| + | ykman piv certificates generate \ | ||
| + | --subject " | ||
| + | --valid-days 3650 \ | ||
| + | 9c \ | ||
| + | mis-users-ca-yubi-cert.pub | ||
| + | # → demande le PIN | ||
| + | </ | ||
| + | |||
| + | ==== Étape 2.3 : Export de la clé publique au format SSH ==== | ||
| + | |||
| + | C'est cette clé publique qui sera déployée sur tous les serveurs comme **CA principale acceptée** : | ||
| + | |||
| + | <code bash> | ||
| + | ssh-keygen -D $PKCS11 -e > mis-users-ca-yubi.pub | ||
| + | |||
| + | # Inspection | ||
| + | cat mis-users-ca-yubi.pub | ||
| + | # Doit afficher : ecdsa-sha2-nistp384 AAAA... | ||
| + | |||
| + | # Renommer avec un commentaire explicite (facultatif) | ||
| + | sed -i 's|$| MIS Users CA - Yubikey|' | ||
| + | </ | ||
| + | |||
| + | ==== Étape 2.4 : Génération de la CA emergency (container éphémère) ==== | ||
| + | |||
| + | La CA emergency est une clé privée Ed25519 classique, mais qui ne doit **jamais exister en clair sur ton laptop** après génération. La meilleure approche : un container Docker éphémère sans réseau, qui ne laisse aucune trace après destruction. | ||
| + | |||
| + | **Pourquoi pas juste sur ton laptop ?** Parce qu' | ||
| + | |||
| + | **Génération via Docker** : | ||
| + | |||
| + | <code bash> | ||
| + | # Lancement d'un container Debian 13 minimal, SANS RÉSEAU | ||
| + | docker run --rm -it \ | ||
| + | --network none \ | ||
| + | --hostname offline-ca-gen \ | ||
| + | -v ~/ | ||
| + | debian: | ||
| + | </ | ||
| + | |||
| + | **Dans le container** (aucun accès Internet possible) : | ||
| + | |||
| + | <code bash> | ||
| + | # Installation des outils (depuis le cache APT du container, pas Internet) | ||
| + | # Si l' | ||
| + | apt-get install -y openssh-client age coreutils 2>/ | ||
| + | |||
| + | cd /tmp | ||
| + | |||
| + | # Génération Ed25519 classique | ||
| ssh-keygen -t ed25519 -a 200 \ | ssh-keygen -t ed25519 -a 200 \ | ||
| - | -f mis-hosts-ca \ | + | -f mis-users-ca-emergency |
| - | -C " | + | -C " |
| - | -N 'AUTRE_PASSPHRASE_TRES_ROBUSTE' | + | -N '' |
| - | ``` | + | |
| - | ### Étape 2.3 : Backup chiffré des clés privées | + | # Chiffrement avec age - passphrase en interactif (PAS en argument !) |
| + | age --passphrase \ | ||
| + | -o mis-users-ca-emergency.age \ | ||
| + | mis-users-ca-emergency | ||
| + | # → entrer une passphrase TRÈS robuste (Diceware 6-8 mots recommandé) | ||
| - | ⚠️ **Étape critique**. Sans backup, perdre | + | # Effacement sécurisé de la version en clair |
| + | shred -u mis-users-ca-emergency | ||
| - | ```bash | + | # Copie des fichiers finaux vers l'hôte via le volume monté |
| - | # Création d'une archive chiffrée | + | cp mis-users-ca-emergency.age /output/ |
| - | cd ~/mis-ca | + | cp mis-users-ca-emergency.pub /output/ |
| - | tar czf - mis-users-ca | + | |
| - | age -p > mis-ca-backup-$(date +%Y%m%d).tar.gz.age | + | |
| - | # Demande une passphrase distincte des passphrases des CAs | + | |
| - | # À conserver dans : | + | # Sortie du container → destruction automatique |
| - | # 1. Bitwarden | + | exit |
| - | # 2. Clé USB chiffrée dans coffre physique | + | </ |
| - | # 3. (optionnel) Coffre bancaire pour archive papier-QR de la passphrase | + | |
| - | ``` | + | |
| - | --- | + | **Note** : si '' |
| + | |||
| + | <code bash> | ||
| + | # À faire une seule fois, sur ton hôte | ||
| + | cat > / | ||
| + | FROM debian: | ||
| + | RUN apt-get update && \ | ||
| + | apt-get install -y --no-install-recommends \ | ||
| + | openssh-client age coreutils && \ | ||
| + | rm -rf / | ||
| + | EOF | ||
| + | |||
| + | docker build -t mis-ca-gen: | ||
| + | |||
| + | # Puis utiliser cette image (en remplaçant debian: | ||
| + | docker run --rm -it --network none -v ~/ | ||
| + | </ | ||
| + | |||
| + | **Variante Podman rootless** (si tu préfères ne pas dépendre d'un daemon Docker root) : | ||
| + | |||
| + | <code bash> | ||
| + | podman run --rm -it --network none -v ~/ | ||
| + | </ | ||
| + | |||
| + | **Résultat sur ton hôte** : | ||
| + | |||
| + | <code bash> | ||
| + | ls -la ~/ | ||
| + | # mis-users-ca-emergency.age | ||
| + | # mis-users-ca-emergency.pub | ||
| + | # mis-users-ca-yubi.pub | ||
| + | # mis-users-ca-yubi-cert.pub | ||
| + | </ | ||
| + | |||
| + | ==== Étape 2.5 : CA pour les hôtes (optionnelle pour démarrer) ==== | ||
| + | |||
| + | Même approche pour la CA d' | ||
| + | * Soit sur la **même Yubikey** dans le slot 9a (Authentication) ou 9d (Key Management) | ||
| + | * Soit avec un fichier classique chiffré, plus simple pour démarrer | ||
| + | |||
| + | Comme tu as décidé de ne pas faire les certifs machines tout de suite, on saute cette étape pour le moment. À reprendre quand tu te lanceras dans les certifs d' | ||
| + | |||
| + | ==== Étape 2.6 : Stratégie de stockage des secrets (double chiffrement) ==== | ||
| + | |||
| + | **Principe** : la clé emergency est protégée par **deux couches** indépendantes : | ||
| + | |||
| + | < | ||
| + | Clé privée Ed25519 (claire) | ||
| + | ↓ couche 1 : chiffrement age (passphrase forte) | ||
| + | Fichier .age (illisible sans passphrase age) | ||
| + | ↓ couche 2 : attachment dans Bitwarden (chiffré par master password) | ||
| + | Coffre Bitwarden (illisible sans master password) | ||
| + | </ | ||
| + | |||
| + | Pour que cette défense en profondeur fonctionne, **les deux secrets doivent être stockés à des endroits différents** : sinon une seule compromission donne accès à tout. | ||
| + | |||
| + | === Ce qui va dans Bitwarden === | ||
| + | |||
| + | Entrée **"MIS SSH CA - Master Backup" | ||
| + | |||
| + | **Notes (champ texte de l' | ||
| + | |||
| + | < | ||
| + | ═══════════════════════════════════════════════ | ||
| + | PROCÉDURE DE RÉCUPÉRATION D' | ||
| + | |||
| + | 1. Récupérer la passphrase age : | ||
| + | - Coffre bureau MIS, enveloppe scellée "CA Emergency" | ||
| + | - OU coffre backup (maison Vincent / coffre bancaire) | ||
| + | |||
| + | 2. Télécharger mis-users-ca-emergency.age depuis cette entrée | ||
| + | |||
| + | 3. Sur container éphémère : | ||
| + | | ||
| + | cd /work | ||
| + | age --decrypt mis-users-ca-emergency.age > recovery-key | ||
| + | chmod 600 recovery-key | ||
| + | # utiliser pour signer (voir Phase 9 du runbook) | ||
| + | shred -u recovery-key | ||
| + | | ||
| + | |||
| + | ═══════════════════════════════════════════════ | ||
| + | INFOS YUBIKEY CA | ||
| + | |||
| + | Serial number | ||
| + | PIN PIV : [PIN à compléter] | ||
| + | PUK : [PUK à compléter] | ||
| + | Algorithme | ||
| + | Slot : 9c | ||
| + | Touch policy | ||
| + | PIN policy | ||
| + | |||
| + | ═══════════════════════════════════════════════ | ||
| + | FINGERPRINTS (vérification d' | ||
| + | |||
| + | Yubikey CA pub : [ssh-keygen -l -f mis-users-ca-yubi.pub] | ||
| + | Emergency CA pub : [ssh-keygen -l -f mis-users-ca-emergency.pub] | ||
| + | |||
| + | ═══════════════════════════════════════════════ | ||
| + | </ | ||
| + | |||
| + | **Attachments (fichiers attachés à l' | ||
| + | |||
| + | ^ Fichier ^ Sensibilité ^ Pourquoi dans Bitwarden ^ | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | |||
| + | **Ce qui ne doit JAMAIS aller dans Bitwarden** : | ||
| + | * ❌ La passphrase age (sinon couche 1 + couche 2 = même point de défaillance) | ||
| + | * ❌ La clé privée emergency en clair | ||
| + | * ❌ Un export PKCS#12 de la Yubikey (impossible techniquement, | ||
| + | |||
| + | === Ce qui va sur papier (hors numérique) === | ||
| + | |||
| + | La **passphrase age** uniquement. À écrire à la main sur papier : | ||
| + | |||
| + | * **Localisation principale** : coffre physique au bureau MIS, dans une enveloppe scellée "CA Emergency - Vincent uniquement" | ||
| + | * **Localisation backup** : coffre physique à la maison de Vincent (ou coffre bancaire), même enveloppe | ||
| + | |||
| + | **Format recommandé** : passphrase Diceware 6-8 mots, plus facile à recopier sans erreur qu'une chaîne aléatoire. | ||
| + | |||
| + | Exemple : '' | ||
| + | |||
| + | **Approche avancée (optionnelle)** : Shamir Secret Sharing avec '' | ||
| + | |||
| + | === Backup hors-Bitwarden additionnel === | ||
| + | |||
| + | En complément (ceinture-bretelles) : | ||
| + | * Clé USB chiffrée LUKS dans coffre physique avec une copie de tout '' | ||
| + | * À refaire à chaque rotation/ | ||
| + | * La passphrase LUKS est encore un secret différent (toujours pas dans Bitwarden) | ||
| + | |||
| + | ==== Étape 2.7 : Test de récupération (CRITIQUE) ==== | ||
| + | |||
| + | ⚠️ **Avant de tout ranger dans le coffre et de considérer le setup terminé**, tu dois faire un test de récupération complet. C'est l' | ||
| + | |||
| + | <code bash> | ||
| + | # 1. Dans un dossier temporaire de test | ||
| + | mkdir / | ||
| + | |||
| + | # 2. Copier le .age depuis Bitwarden (téléchargement de l' | ||
| + | # OU depuis ~/ | ||
| + | cp ~/ | ||
| + | |||
| + | # 3. Aller récupérer le papier dans le coffre, lire la passphrase | ||
| + | # (Geste réel, pas une simulation : tu dois vérifier que la passphrase | ||
| + | # est bien lisible et que tu peux la recopier sans erreur) | ||
| + | |||
| + | # 4. Déchiffrer en utilisant la passphrase du papier | ||
| + | age --decrypt mis-users-ca-emergency.age > recovery-key | ||
| + | # → entrer la passphrase telle qu' | ||
| + | |||
| + | # 5. Vérifier que la clé déchiffrée est bien la bonne | ||
| + | ssh-keygen -y -f recovery-key > recovered.pub | ||
| + | diff recovered.pub ~/ | ||
| + | # Sortie attendue : VIDE (les deux fichiers sont identiques) | ||
| + | # Si différents → la passphrase a été mal recopiée OU le .age est corrompu | ||
| + | |||
| + | # 6. Nettoyage immédiat | ||
| + | shred -u recovery-key recovered.pub | ||
| + | cd .. && rm -rf / | ||
| + | </ | ||
| + | |||
| + | **Si le test réussit, tu as validé** : | ||
| + | * ✅ La passphrase est correctement écrite sur papier (lisible, sans erreur) | ||
| + | * ✅ Le fichier '' | ||
| + | * ✅ Tu sais exécuter la procédure (le geste compte autant que le savoir) | ||
| + | * ✅ Les fingerprints correspondent | ||
| + | |||
| + | **Si le test échoue**, NE PAS continuer. Identifier le problème (passphrase mal recopiée ? mauvais fichier '' | ||
| + | |||
| + | **À refaire annuellement** dans le cadre du drill de récupération (voir checklist en fin de doc). | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Phase 3 : Bootstrap d'un serveur client ===== | ||
| + | |||
| + | ==== Étape 3.1 : Préparation du fichier de CAs publiques ==== | ||
| + | |||
| + | Sur ton poste de signature, prépare un fichier qui contient les **deux** clés publiques (Yubikey + emergency) que tu vas déployer sur tous les serveurs : | ||
| + | |||
| + | <code bash> | ||
| + | cd ~/ | ||
| + | cat mis-users-ca-yubi.pub mis-users-ca-emergency.pub > mis-users-ca-deploy.pub | ||
| + | |||
| + | cat mis-users-ca-deploy.pub | ||
| + | # Doit contenir 2 lignes : | ||
| + | # ecdsa-sha2-nistp384 AAAA... MIS Users CA - Yubikey | ||
| + | # ssh-ed25519 AAAA... MIS Users CA - EMERGENCY USE ONLY | ||
| + | </ | ||
| + | |||
| + | C'est ce fichier '' | ||
| - | ## Phase 3 : Bootstrap d'un serveur client | + | ==== Étape |
| - | ### Étape 3.1 : Déploiement de la CA users sur le serveur | + | Sur un serveur |
| - | Sur un serveur client (Debian provisionné via cloud-init) : | + | <code bash> |
| + | # Copie du fichier de CAs | ||
| + | scp ~/mis-ssh-ca/ | ||
| - | ```bash | + | # Côté serveur, déploiement |
| - | # Copie de la clé publique de la CA users | + | ssh mis-admin@srv01.acme.lan |
| - | scp ca-signer@10.10.10.50:~/mis-ca/mis-users-ca.pub | + | sudo install |
| - | chmod 644 / | + | |
| # Création d'un KRL vide initial | # Création d'un KRL vide initial | ||
| - | ssh-keygen -k -f / | + | sudo ssh-keygen -k -f / |
| - | chmod 644 / | + | sudo chmod 644 / |
| # Configuration sshd | # Configuration sshd | ||
| - | cat >> | + | sudo tee -a / |
| # ===== MIS SSH CA ===== | # ===== MIS SSH CA ===== | ||
| Ligne 248: | Ligne 526: | ||
| # Test et reload | # Test et reload | ||
| - | sshd -t && systemctl reload ssh | + | sudo sshd -t && |
| - | ``` | + | </ |
| À industrialiser via Ansible (voir Phase 7). | À industrialiser via Ansible (voir Phase 7). | ||
| - | ### Étape 3.2 : Certificat d' | + | ---- |
| - | Sur la CA : | + | ===== Phase 4 : Enrôlement d'une Yubikey technicien ===== |
| - | ```bash | + | ==== Étape 4.1 : Génération sur le poste du technicien ==== |
| - | # Récupération de la clé publique du serveur | + | |
| - | scp mis-admin@srv01.acme.lan:/ | + | |
| - | # Signature comme hôte | + | **Sur Windows** |
| - | ssh-keygen -s ~/ | + | |
| - | -I " | + | |
| - | -h \ | + | |
| - | -n " | + | |
| - | -V " | + | |
| - | / | + | |
| - | # Envoi sur le serveur | + | < |
| - | scp / | + | |
| - | ssh mis-admin@srv01.acme.lan "sudo mv / | + | |
| - | + | ||
| - | # Activation côté serveur | + | |
| - | ssh mis-admin@srv01.acme.lan "sudo sed -i '/ | + | |
| - | echo ' | + | |
| - | sudo systemctl reload ssh" | + | |
| - | ``` | + | |
| - | + | ||
| - | ### Étape 3.3 : Configuration côté postes techniciens | + | |
| - | + | ||
| - | Sur **chaque** poste tech (Windows ou Linux), dans `~/ | + | |
| - | + | ||
| - | ``` | + | |
| - | @cert-authority *.acme.lan, | + | |
| - | ``` | + | |
| - | + | ||
| - | (la clé publique correspond au contenu de `mis-hosts-ca.pub`) | + | |
| - | + | ||
| - | À partir de ce moment, plus aucun warning de host key à la première connexion sur un serveur MIS. | + | |
| - | + | ||
| - | --- | + | |
| - | + | ||
| - | ## Phase 4 : Enrôlement d'une Yubikey technicien | + | |
| - | + | ||
| - | ### Étape 4.1 : Génération sur le poste du technicien | + | |
| - | + | ||
| - | **Sur Windows** : | + | |
| - | + | ||
| - | ```powershell | + | |
| - | # PowerShell, Yubikey branchée | + | |
| # Définition d'un PIN FIDO2 si pas déjà fait (via Yubikey Manager GUI) | # Définition d'un PIN FIDO2 si pas déjà fait (via Yubikey Manager GUI) | ||
| Ligne 306: | Ligne 545: | ||
| -f $env: | -f $env: | ||
| -C " | -C " | ||
| - | ``` | + | </ |
| **Sur Linux/ | **Sur Linux/ | ||
| - | ```bash | + | < |
| ssh-keygen -t ed25519-sk -O resident -O application=ssh: | ssh-keygen -t ed25519-sk -O resident -O application=ssh: | ||
| -f ~/ | -f ~/ | ||
| -C " | -C " | ||
| - | ``` | + | </ |
| - | Résultat : `id_ed25519_sk_yubi1` (stub) et `id_ed25519_sk_yubi1.pub` (clé publique). | + | Résultat : '' |
| - | ### Étape 4.2 : Signature par la CA | + | ==== Étape 4.2 : Signature par la CA Yubikey ==== |
| - | Le technicien | + | Le tech envoie sa '' |
| - | ```bash | + | < |
| - | # Sur la LXC, en tant que ca-signer | + | cd ~/mis-ssh-ca |
| - | cd ~/mis-ca | + | export PKCS11=/ |
| # Variables | # Variables | ||
| - | PUBKEY_PATH=/ | + | PUBKEY=/ |
| CERT_ID=" | CERT_ID=" | ||
| PRINCIPALS=" | PRINCIPALS=" | ||
| VALIDITY=" | VALIDITY=" | ||
| - | SERIAL=1001 | + | SERIAL=1001 |
| - | ssh-keygen -s mis-users-ca \ | + | ssh-keygen -s mis-users-ca-yubi.pub \ |
| + | -D $PKCS11 | ||
| -I " | -I " | ||
| -n " | -n " | ||
| Ligne 342: | Ligne 582: | ||
| -O no-agent-forwarding \ | -O no-agent-forwarding \ | ||
| -O permit-pty \ | -O permit-pty \ | ||
| - | "$PUBKEY_PATH" | + | "$PUBKEY" |
| - | # Le fichier vincent-yubi-primary-cert.pub | + | # Appuyer sur la yubikey dès que le pin est introduit |
| - | ``` | + | # → demande le PIN PIV (1x par session grâce à --pin-policy ONCE) |
| + | # → demande le touch sur la Yubikey CA | ||
| + | # → fichier vincent-yubi-primary-cert.pub généré à côté de la .pub | ||
| + | </ | ||
| - | Renvoyer le `-cert.pub` au technicien. | + | **Note importante** : avec '' |
| - | ### Étape 4.3 : Mise en place côté | + | Renvoyer le '' |
| - | Le tech place le `-cert.pub` à côté de sa clé : | + | ==== Étape 4.3 : Mise en place côté technicien ==== |
| - | ``` | + | Le tech place le '' |
| + | |||
| + | < | ||
| ~/.ssh/ | ~/.ssh/ | ||
| ├── id_ed25519_sk_yubi1 | ├── id_ed25519_sk_yubi1 | ||
| ├── id_ed25519_sk_yubi1.pub | ├── id_ed25519_sk_yubi1.pub | ||
| └── id_ed25519_sk_yubi1-cert.pub | └── id_ed25519_sk_yubi1-cert.pub | ||
| - | ``` | + | </ |
| Vérification du contenu du certificat : | Vérification du contenu du certificat : | ||
| - | ```bash | + | < |
| ssh-keygen -L -f ~/ | ssh-keygen -L -f ~/ | ||
| - | ``` | + | </ |
| - | Doit afficher : Principals, Valid from/to, Critical Options, Extensions. | + | Doit afficher : Signing CA ('' |
| - | ### Étape 4.4 : Test de connexion | + | ==== Étape 4.4 : Test de connexion |
| - | ```bash | + | < |
| ssh -i ~/ | ssh -i ~/ | ||
| - | # → PIN FIDO2 demandé | + | # → PIN FIDO2 demandé |
| - | # → touch Yubikey | + | # → touch Yubikey |
| # → connecté | # → connecté | ||
| - | ``` | + | </ |
| - | **Indicateur clé** | + | ==== Étape 4.5 : Enrôlement de la Yubikey de backup ==== |
| - | ### Étape 4.5 : Enrôlement de la Yubikey | + | **Répéter |
| + | * Serial différent ('' | ||
| + | * Identifiant unique ('' | ||
| - | **Répéter | + | ==== Étape 4.6 : Configuration |
| - | À la fin, le technicien a 6 fichiers dans `~/.ssh/` : | + | < |
| - | + | Host *.acme.lan acme-* | |
| - | ``` | + | |
| - | id_ed25519_sk_yubi1 | + | |
| - | id_ed25519_sk_yubi1.pub | + | |
| - | id_ed25519_sk_yubi1-cert.pub | + | |
| - | id_ed25519_sk_yubi2 | + | |
| - | id_ed25519_sk_yubi2.pub | + | |
| - | id_ed25519_sk_yubi2-cert.pub | + | |
| - | ``` | + | |
| - | + | ||
| - | ### Étape 4.6 : Configuration `~/ | + | |
| - | + | ||
| - | ``` | + | |
| - | Host *.acme.lan acme-* | + | |
| User mis-admin | User mis-admin | ||
| IdentityFile ~/ | IdentityFile ~/ | ||
| Ligne 404: | Ligne 638: | ||
| CertificateFile ~/ | CertificateFile ~/ | ||
| CertificateFile ~/ | CertificateFile ~/ | ||
| + | </ | ||
| - | Host *.mis.lan | + | ---- |
| - | User mis-admin | + | |
| - | IdentityFile ~/ | + | |
| - | IdentityFile ~/ | + | |
| - | IdentitiesOnly yes | + | |
| - | CertificateFile ~/ | + | |
| - | CertificateFile ~/ | + | |
| - | ``` | + | |
| - | + | ||
| - | SSH essaiera Yubi1 d' | + | |
| - | + | ||
| - | --- | + | |
| - | ## Phase 5 : Révocation d'une clé | + | ===== Phase 5 : Révocation d'une clé ===== |
| - | ### Étape 5.1 : Mise à jour de la KRL | + | ==== Étape 5.1 : Mise à jour de la KRL ==== |
| - | Sur la CA, si on perd la Yubikey | + | Yubikey |
| - | ```bash | + | < |
| - | cd ~/mis-ca | + | cd ~/mis-ssh-ca |
| - | # Création du spec de révocation | + | # Spec de révocation |
| cat > / | cat > / | ||
| # Révocation par serial | # Révocation par serial | ||
| Ligne 439: | Ligne 663: | ||
| EOF | EOF | ||
| - | # Génération/ | + | # Génération/ |
| - | ssh-keygen -k -f mis-revoked-keys -s mis-users-ca -u / | + | ssh-keygen -k -f mis-revoked-keys |
| + | | ||
| + | -D $PKCS11 \ | ||
| + | | ||
| # -u = update (ajoute au KRL existant) | # -u = update (ajoute au KRL existant) | ||
| - | # Sans -u, le KRL est remplacé | + | # → demande PIN + touch |
| + | </ | ||
| - | # Vérification du contenu | + | ==== Étape 5.2 : Déploiement de la KRL via Ansible ==== |
| - | ssh-keygen -Q -f mis-revoked-keys -t krl | + | |
| - | ``` | + | |
| - | ### Étape 5.2 : Déploiement de la KRL | + | <code bash> |
| + | ansible-playbook -i inventory.yml mis-update-krl.yml | ||
| + | </ | ||
| - | Via Ansible | + | En quelques minutes, la Yubikey backup n'est plus utilisable |
| - | ```bash | + | ---- |
| - | ansible-playbook | + | |
| - | ``` | + | |
| - | En quelques minutes, la Yubikey backup n'est plus utilisable sur aucun serveur MIS. **Aucune modification de `sshd_config` ni d' | + | ===== Phase 6 : Renouvellement des certificats ===== |
| - | --- | + | ==== Option A : Manuel ==== |
| - | ## Phase 6 : Renouvellement des certificats | + | Refaire l' |
| - | Les certificats ayant une durée de vie de 1 an, prévoir un workflow de renouvellement : | + | ==== Option B : Automatisé via Odoo ==== |
| - | + | ||
| - | ### Option A : Manuel | + | |
| - | + | ||
| - | Refaire les étapes 4.2 (signature) avec un nouvel identifiant `vincent-yubi-primary-2027` et envoyer le nouveau `-cert.pub` au tech. Le tech remplace son ancien `-cert.pub`. | + | |
| - | + | ||
| - | ### Option B : Automatisé via Odoo | + | |
| Cron Odoo qui scanne les certificats expirant dans 30 jours et : | Cron Odoo qui scanne les certificats expirant dans 30 jours et : | ||
| - | 1. Notifie le tech par mail | + | - Notifie le tech par mail |
| - | 2. Propose un wizard de renouvellement | + | |
| - | 3. Si le tech accepte, | + | |
| - | 4. Envoie le nouveau | + | |
| - | --- | + | ---- |
| - | ## Phase 7 : Industrialisation Ansible | + | ===== Phase 7 : Industrialisation Ansible |
| - | ### Playbook de déploiement initial CA + KRL | + | ==== Playbook de déploiement initial CA + KRL ==== |
| - | `playbooks/ | + | '' |
| - | ```yaml | + | < |
| --- | --- | ||
| - name: Deploy MIS SSH CA on all client servers | - name: Deploy MIS SSH CA on all client servers | ||
| Ligne 490: | Ligne 710: | ||
| become: true | become: true | ||
| vars: | vars: | ||
| - | ca_pub_path: | + | ca_pub_path: |
| krl_path: files/ | krl_path: files/ | ||
| | | ||
| tasks: | tasks: | ||
| - | - name: Deploy MIS users CA public | + | - name: Deploy MIS users CA public |
| copy: | copy: | ||
| src: "{{ ca_pub_path }}" | src: "{{ ca_pub_path }}" | ||
| Ligne 544: | Ligne 764: | ||
| name: ssh | name: ssh | ||
| state: reloaded | state: reloaded | ||
| - | ``` | + | </ |
| - | ### Playbook de mise à jour KRL uniquement | + | ==== Playbook de mise à jour KRL uniquement |
| - | `playbooks/ | + | '' |
| - | ```yaml | + | < |
| --- | --- | ||
| - name: Update MIS SSH KRL on all client servers | - name: Update MIS SSH KRL on all client servers | ||
| Ligne 569: | Ligne 789: | ||
| name: ssh | name: ssh | ||
| state: reloaded | state: reloaded | ||
| - | ``` | + | </ |
| - | --- | + | ---- |
| - | ## Phase 8 : Compte parachute (break-glass) | + | ===== Phase 8 : Compte parachute (break-glass) |
| ⚠️ **Ne JAMAIS sauter cette étape.** | ⚠️ **Ne JAMAIS sauter cette étape.** | ||
| - | Indépendamment | + | C'est un parachute **indépendant** |
| - | ```bash | + | < |
| # Sur un poste sûr, génération d'une clé classique pour le parachute | # Sur un poste sûr, génération d'une clé classique pour le parachute | ||
| ssh-keygen -t ed25519 -a 200 -f mis-breakglass -C "MIS BREAK-GLASS - DO NOT USE" | ssh-keygen -t ed25519 -a 200 -f mis-breakglass -C "MIS BREAK-GLASS - DO NOT USE" | ||
| Ligne 585: | Ligne 805: | ||
| # Stocker mis-breakglass (privé) : | # Stocker mis-breakglass (privé) : | ||
| - | # - Chiffré dans Bitwarden (attachment) | + | # - Chiffré dans Bitwarden (attachment) |
| # - Sur clé USB chiffrée dans coffre physique | # - Sur clé USB chiffrée dans coffre physique | ||
| # - Supprimer du disque local après stockage sécurisé | # - Supprimer du disque local après stockage sécurisé | ||
| # Garder mis-breakglass.pub pour déploiement | # Garder mis-breakglass.pub pour déploiement | ||
| - | ``` | + | </ |
| Intégrer la clé publique dans le template cloud-init / virt-customize de **tous** les serveurs : | Intégrer la clé publique dans le template cloud-init / virt-customize de **tous** les serveurs : | ||
| - | ```bash | + | < |
| - | # Dans virt-customize de la golden image | + | |
| virt-customize -a debian-13-genericcloud-amd64.qcow2 \ | virt-customize -a debian-13-genericcloud-amd64.qcow2 \ | ||
| --run-command ' | --run-command ' | ||
| Ligne 601: | Ligne 820: | ||
| --run-command 'echo " | --run-command 'echo " | ||
| ... | ... | ||
| - | ``` | + | </ |
| - | Le jour où la CA est inaccessible (perte de toutes les Yubikeys, corruption de la LXC, etc.), tu sors la clé du coffre Bitwarden, tu te connectes avec, tu reconstruis la situation. | + | ---- |
| - | --- | + | ===== Phase 9 : Procédure de récupération d' |
| - | ## Phase 9 : Migration future vers Yubikey | + | ==== Cas 1 : Yubikey CA perdue / cassée, emergency disponible ==== |
| - | Quand le workflow sera rodé (6-12 mois), migration de la clé privée de la CA depuis disque vers Yubikey PIV : | + | **Workflow** |
| - | ```bash | + | - Acheter une nouvelle Yubikey 5 NFC dédiée à la CA |
| - | # Sur un poste sûr, Yubikey | + | - Déchiffrer temporairement l' |
| - | apt install yubikey-manager opensc | + | ```bash |
| + | cd ~/ | ||
| + | age --decrypt mis-users-ca-emergency.age > / | ||
| + | chmod 600 / | ||
| + | ``` | ||
| + | - **Utiliser l' | ||
| + | | ||
| + | # Préparer la nouvelle Yubikey (Étapes 1.4 + 2.1 à 2.3) | ||
| + | # Tu obtiens mis-users-ca-yubi-NEW.pub | ||
| + | ``` | ||
| + | - Mettre à jour '' | ||
| + | ```bash | ||
| + | cat mis-users-ca-yubi-NEW.pub mis-users-ca-emergency.pub > mis-users-ca-deploy.pub | ||
| + | ``` | ||
| + | - Déployer via Ansible sur tout le parc | ||
| + | - Révoquer l' | ||
| + | | ||
| + | cat > / | ||
| + | # Révocation de l' | ||
| + | | ||
| + | EOF | ||
| + | |||
| + | | ||
| + | -s mis-users-ca-yubi-NEW.pub \ | ||
| + | -D $PKCS11 \ | ||
| + | -u / | ||
| + | ``` | ||
| + | - **Effacement sécurisé** du fichier emergency en clair : | ||
| + | | ||
| + | shred -u / | ||
| + | ``` | ||
| + | - Mise à jour de l' | ||
| - | # Génération d'une nouvelle paire ECCP384 | + | **Important** : tous les certificats utilisateurs signés par l'ancienne Yubikey CA sont **toujours valides** (puisque l' |
| - | ykman piv keys generate --algorithm ECCP384 --pin-policy ONCE --touch-policy CACHED \ | + | |
| - | 9c / | + | |
| - | # Certificat self-signed pour PIV | + | ==== Cas 2 : Tout est perdu sauf break-glass ==== |
| - | ykman piv certificates generate --subject "CN=MIS Users CA" 9c /tmp/mis-ca-piv.pub | + | |
| - | # Export au format SSH | + | Scénario apocalypse : Yubikey CA perdue + Bitwarden inaccessible + papier coffre détruit. |
| - | ssh-keygen -D / | + | |
| - | ``` | + | |
| - | Pour signer ensuite | + | - Connexion sur chaque serveur via SSH avec '' |
| + | | ||
| + | ssh -i ~/ | ||
| + | ``` | ||
| + | - Régénération complète d'une nouvelle CA (depuis zéro, Phase 2) | ||
| + | - Déploiement manuel du nouveau '' | ||
| + | - Re-signature de toutes les Yubikeys techniciens | ||
| + | - Rotation du break-glass aussi (puisqu' | ||
| - | ```bash | + | **À tester** : faire un drill annuel de récupération sur un environnement de staging pour valider que la procédure marche **avant** d'en avoir vraiment besoin. |
| - | ssh-keygen -s mis-users-ca-yubi.pub \ | + | |
| - | -D / | + | |
| - | -I " | + | |
| - | -n " | + | |
| - | -V " | + | |
| - | vincent-yubi-primary.pub | + | |
| - | # → PIN PIV demandé | + | |
| - | # → touch Yubikey | + | |
| - | # → certificat signé | + | |
| - | ``` | + | |
| - | La clé privée de la CA n' | + | ---- |
| - | + | ||
| - | --- | + | |
| - | ## Annexes | + | ===== Annexes |
| - | ### A. Commandes utiles de diagnostic | + | ==== A. Commandes utiles de diagnostic |
| - | ```bash | + | < |
| # Inspecter un certificat utilisateur | # Inspecter un certificat utilisateur | ||
| ssh-keygen -L -f id_ed25519_sk_yubi1-cert.pub | ssh-keygen -L -f id_ed25519_sk_yubi1-cert.pub | ||
| + | |||
| + | # Voir l' | ||
| + | ykman piv info | ||
| + | |||
| + | # Voir le slot 9c (où vit la CA) | ||
| + | ykman piv keys metadata 9c | ||
| # Voir la KRL active sur un serveur | # Voir la KRL active sur un serveur | ||
| Ligne 659: | Ligne 905: | ||
| # Output: " | # Output: " | ||
| - | # Côté serveur, voir quelles | + | # Côté serveur, voir les connexions par certificat |
| journalctl -u ssh | grep " | journalctl -u ssh | grep " | ||
| - | # Lister les clés résidentes sur une Yubikey | + | # Lister les clés publiques visibles via PKCS#11 (avec Yubikey |
| - | ssh-keygen -K | + | ssh-keygen -D $PKCS11 -e |
| - | # Récupère les stubs sur le poste courant depuis la Yubikey | + | |
| - | ``` | + | |
| - | ### B. Format complet d'une signature ssh-keygen | + | # Tester |
| + | echo " | ||
| + | </ | ||
| - | ```bash | + | ==== B. Format complet d'une signature ssh-keygen avec Yubikey ==== |
| - | ssh-keygen -s CA_PRIVATE_KEY | + | |
| + | < | ||
| + | ssh-keygen -s CA_PUBLIC_KEY \ | ||
| + | -D PKCS11_PROVIDER | ||
| -I CERT_IDENTIFIER \ | -I CERT_IDENTIFIER \ | ||
| -n PRINCIPAL1, | -n PRINCIPAL1, | ||
| Ligne 678: | Ligne 927: | ||
| -O OPTION2 \ | -O OPTION2 \ | ||
| USER_PUBLIC_KEY.pub | USER_PUBLIC_KEY.pub | ||
| - | ``` | + | </ |
| - | | Option | + | ^ Option |
| - | |--------|-------------| | + | | '' |
| - | | `-s` | Chemin vers la clé privée | + | | '' |
| - | | `-I` | Identifiant lisible du certificat (visible dans logs sshd) | | + | | '' |
| - | | `-n` | Principals (noms d' | + | | '' |
| - | | `-V` | Validité (`+52w`, `+30d`, `+8h`, `20260601: | + | | '' |
| - | | `-z` | Serial unique (entier) | | + | | '' |
| - | | `-h` | Génère un certificat d' | + | | '' |
| - | | `-O clear` | Reset les permissions par défaut | | + | | '' |
| - | | `-O no-port-forwarding` | Désactive le port forwarding | | + | | '' |
| - | | `-O no-agent-forwarding` | Désactive l' | + | | '' |
| - | | `-O no-X11-forwarding` | Désactive X11 | | + | | '' |
| - | | `-O permit-pty` | Autorise l' | + | | '' |
| - | | `-O force-command=" | + | | '' |
| - | | `-O source-address=" | + | |
| - | ### C. Liens utiles | + | ==== C. Liens utiles |
| - | - OpenSSH manual | + | * OpenSSH manual |
| - | - Documentation officielle Yubico FIDO2 SSH : https:// | + | |
| - | - Cloud-init reference | + | * Documentation Yubico PIV : https://developers.yubico.com/PIV/ |
| - | - Format des certificats SSH (technique) : `PROTOCOL.certkeys` dans le code OpenSSH | + | * Documentation '' |
| + | * Format des certificats SSH (technique) : '' | ||
| - | --- | + | ---- |
| - | ## Checklist de mise en place | + | ===== Checklist de mise en place ===== |
| - | ### Phase 0 - Préparation | + | ==== Phase 0 - Matériel et logiciels ==== |
| - | - [ ] Yubikeys commandées (minimum | + | * [ ] Yubikey 5 NFC dédiée à la CA commandée |
| - | - [ ] PINs FIDO2 définis sur chaque Yubikey (via Yubikey Manager) | + | * [ ] Yubikeys |
| - | - [ ] Bitwarden ready pour stockage des secrets | + | |
| + | * [ ] Coffre physique identifié | ||
| + | * [ ] OpenSSH + yubikey-manager + opensc + age installés sur le poste de signature | ||
| - | ### Phase 1-2 - CA | + | ==== Phase 1-2 - CA ==== |
| - | - [ ] LXC `mis-ssh-ca` créée et durcie | + | |
| - | - [ ] CA users générée + passphrase robuste | + | * [ ] CA principale générée sur Yubikey (slot 9c, ECCP384) |
| - | - [ ] CA hosts générée + passphrase robuste | + | * [ ] Clé publique Yubikey CA exportée ('' |
| - | - [ ] Backup | + | * [ ] Image Docker '' |
| - | - [ ] LXC éteinte par défaut, allumage à la demande | + | * [ ] Emergency |
| + | | ||
| + | * [ ] Passphrase age écrite sur papier dans coffre bureau MIS | ||
| + | * [ ] Passphrase age (copie) dans coffre backup (maison ou bancaire) | ||
| + | * [ ] Backup | ||
| + | | ||
| - | ### Phase 3 - Bootstrap parc | + | ==== Phase 3 - Bootstrap parc ==== |
| - | - [ ] Compte break-glass | + | |
| - | - [ ] Playbook Ansible | + | |
| - | - [ ] Déploiement progressif sur le parc complet | + | * [ ] Fichier '' |
| - | - [ ] Certificats d' | + | * [ ] Déploiement progressif sur le parc complet |
| - | ### Phase 4 - Techniciens | + | ==== Phase 4 - Techniciens |
| - | - [ ] Premières Yubikeys enrôlées (toi en priorité) | + | |
| - | - [ ] Tests de connexion validés | + | |
| - | - [ ] Configuration | + | |
| - | ### Phase 5+ - Industrialisation | + | ==== Phase 5+ - Industrialisation |
| - | - [ ] Module Odoo `makeitsimple_ssh_ca` (modèles + wizards) | + | |
| - | - [ ] Intégration Semaphore pour déploiement KRL | + | |
| - | - [ ] Cron de notification d' | + | |
| - | - [ ] Migration CA vers Yubikey PIV (à 6-12 mois) | + | |
| - | --- | + | ---- |
| - | *Document maintenu par Make IT Simple - dernière révision : 2026* | + | //Document maintenu par Make IT Simple - dernière révision : 2026// |
linux/ca-ssh.1780492342.txt.gz · Dernière modification : de root
