linux:ca-ssh
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| linux:ca-ssh [2026/06/03 13:35] – root | linux:ca-ssh [2026/06/03 18:23] (Version actuelle) – [Étape 4.2 : Signature par la CA Yubikey] root | ||
|---|---|---|---|
| Ligne 253: | Ligne 253: | ||
| </ | </ | ||
| - | ==== Étape 2.4 : Génération de la CA emergency (fichier classique) ==== | + | ==== É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> | <code bash> | ||
| - | cd ~/ | + | # 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 | + | # Génération Ed25519 classique |
| - | # (le chiffrement vient d'age juste après) | + | |
| ssh-keygen -t ed25519 -a 200 \ | ssh-keygen -t ed25519 -a 200 \ | ||
| -f mis-users-ca-emergency \ | -f mis-users-ca-emergency \ | ||
| Ligne 267: | Ligne 285: | ||
| -N '' | -N '' | ||
| - | # Chiffrement avec age | + | # Chiffrement avec age - passphrase en interactif (PAS en argument !) |
| age --passphrase \ | age --passphrase \ | ||
| -o mis-users-ca-emergency.age \ | -o mis-users-ca-emergency.age \ | ||
| mis-users-ca-emergency | mis-users-ca-emergency | ||
| - | # → demande | + | # → entrer |
| - | # Effacement sécurisé | + | # Effacement sécurisé |
| shred -u mis-users-ca-emergency | shred -u mis-users-ca-emergency | ||
| - | # La clé publique, elle, reste en clair (pas un secret) | + | # Copie des fichiers finaux vers l' |
| - | ls -la | + | cp mis-users-ca-emergency.age /output/ |
| - | # mis-users-ca-emergency.age | + | cp mis-users-ca-emergency.pub /output/ |
| - | # mis-users-ca-emergency.pub | + | |
| - | # mis-users-ca-yubi.pub | + | # Sortie du container → destruction automatique (--rm) |
| + | exit | ||
| + | </ | ||
| + | |||
| + | **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** | ||
| + | |||
| + | <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 | # mis-users-ca-yubi-cert.pub | ||
| </ | </ | ||
| Ligne 292: | Ligne 344: | ||
| 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' | 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 : Sauvegarde dans Bitwarden | + | ==== Étape 2.6 : Stratégie de stockage des secrets (double chiffrement) |
| - | Créer une entrée Bitwarden | + | **Principe** : la clé emergency est protégée par **deux couches** indépendantes |
| - | **Notes (champ texte)** : | ||
| < | < | ||
| - | === Yubikey CA (slot 9c PIV) === | + | Clé privée Ed25519 (claire) |
| - | Serial: [serial | + | ↓ couche 1 : chiffrement age (passphrase forte) |
| - | PIN PIV: [PIN choisi] | + | Fichier .age (illisible sans passphrase age) |
| - | PUK: [PUK choisi] | + | ↓ couche 2 : attachment dans Bitwarden (chiffré par master password) |
| - | Algorithme: ECCP384 | + | Coffre Bitwarden (illisible sans master password) |
| - | Touch policy: CACHED | + | </ |
| - | Pin policy: ONCE | + | |
| + | 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 | ||
| + | PIN PIV : [PIN à compléter] | ||
| + | PUK : [PUK à compléter] | ||
| + | Algorithme | ||
| + | Slot : 9c | ||
| + | Touch policy | ||
| + | PIN policy | ||
| + | |||
| + | ═══════════════════════════════════════════════ | ||
| + | FINGERPRINTS (vérification d' | ||
| - | === Emergency | + | Yubikey |
| - | Passphrase age: [passphrase mémorisée séparément] | + | Emergency CA pub : [ssh-keygen -l -f mis-users-ca-emergency.pub] |
| - | Fingerprint: [ssh-keygen -l -f mis-users-ca-emergency.pub] | + | |
| - | === Notes === | + | ═══════════════════════════════════════════════ |
| - | - Fichier age en attachment | + | |
| - | - Passphrase NE DOIT PAS être stockée dans cette entrée | + | |
| - | - Stocker passphrase sur papier dans coffre physique | + | |
| </ | </ | ||
| - | **Attachments** : | + | **Attachments (fichiers attachés à l'entrée)** : |
| - | * '' | + | |
| - | * '' | + | |
| - | | + | |
| - | **Stratégie de la passphrase** : | + | ^ Fichier ^ Sensibilité ^ Pourquoi |
| - | * **NE PAS** la stocker | + | | ''mis-users-ca-emergency.age'' |
| - | * L'écrire sur papier, dans le coffre physique du bureau MIS | + | | '' |
| - | * Idéalement : passphrase Diceware 6-8 mots, mémorisable | + | | '' |
| - | * Optionnel : la séparer en 2 morceaux | + | | '' |
| - | **Backup additionnel | + | **Ce qui ne doit JAMAIS aller dans Bitwarden** : |
| - | * Clé USB chiffrée | + | * ❌ 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 | ||
| + | | ||
| + | |||
| + | **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/ | * À 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). | ||
| ---- | ---- | ||
| Ligne 438: | Ligne 584: | ||
| " | " | ||
| + | # 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 PIN PIV (1x par session grâce à --pin-policy ONCE) | ||
| # → demande le touch sur la Yubikey CA | # → demande le touch sur la Yubikey CA | ||
| Ligne 820: | Ligne 967: | ||
| * [ ] CA principale générée sur Yubikey (slot 9c, ECCP384) | * [ ] CA principale générée sur Yubikey (slot 9c, ECCP384) | ||
| * [ ] Clé publique Yubikey CA exportée ('' | * [ ] Clé publique Yubikey CA exportée ('' | ||
| - | * [ ] Emergency CA générée | + | |
| - | * [ ] Backup | + | |
| + | * [ ] Bitwarden : entrée "MIS SSH CA - Master Backup" | ||
| + | * [ ] Passphrase age écrite | ||
| + | * [ ] Passphrase age (copie) dans coffre | ||
| * [ ] Backup additionnel sur clé USB LUKS dans coffre | * [ ] Backup additionnel sur clé USB LUKS dans coffre | ||
| + | * [ ] **Test de récupération validé** (Étape 2.7) avant rangement définitif | ||
| ==== Phase 3 - Bootstrap parc ==== | ==== Phase 3 - Bootstrap parc ==== | ||
linux/ca-ssh.1780493745.txt.gz · Dernière modification : de root
