Outils pour utilisateurs

Outils du site


linux:ca-ssh

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
linux:ca-ssh [2026/06/03 13:35] rootlinux:ca-ssh [2026/06/03 18:23] (Version actuelle) – [Étape 4.2 : Signature par la CA Yubikey] root
Ligne 253: Ligne 253:
 </code> </code>
  
-==== É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) ====
  
-⚠️ **Idéalement, faire cette étape sur une machine offline ou un live USB Tails**. Au minimumdéconnecte le wifi pendant l'opération.+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érationLa meilleure approche : un container Docker éphémère sans réseauqui ne laisse aucune trace après destruction. 
 + 
 +**Pourquoi pas juste sur ton laptop ?** Parce qu'entre la génération en clair et le chiffrement age, la clé existe en clair sur ton disque. Avec un container sans réseau, aucun process tiers (même un éventuel malware) ne peut exfiltrer pendant cette fenêtre. 
 + 
 +**Génération via Docker** :
  
 <code bash> <code bash>
-cd ~/mis-ssh-ca+# Lancement d'un container Debian 13 minimal, SANS RÉSEAU 
 +docker run --rm -it \ 
 +  --network none \ 
 +  --hostname offline-ca-gen \ 
 +  -v ~/mis-ssh-ca:/output \ 
 +  debian:trixie-slim bash 
 +</code> 
 + 
 +**Dans le container** (aucun accès Internet possible) : 
 + 
 +<code bash> 
 +# Installation des outils (depuis le cache APT du container, pas Internet) 
 +# Si l'image n'a pas les paquets, faire docker build préalable (voir note ci-dessous) 
 +apt-get install -y openssh-client age coreutils 2>/dev/null || echo "Image sans cache, voir note" 
 + 
 +cd /tmp
  
-# Génération d'une paire Ed25519 classique sans passphrase +# 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 une passphrase TRÈS robuste (>20 chars, mémorisable type Diceware)+# → entrer une passphrase TRÈS robuste (Diceware 6-8 mots recommandé)
  
-# Effacement sécurisé du fichier en clair+# Effacement sécurisé de la version en clair
 shred -u mis-users-ca-emergency shred -u mis-users-ca-emergency
  
-La clé publiqueellereste en clair (pas un secret+Copie des fichiers finaux vers l'hôte via le volume monté 
-ls -la +cp mis-users-ca-emergency.age /output/ 
-# mis-users-ca-emergency.age       ← clé privée chiffrée +cp mis-users-ca-emergency.pub /output/ 
-# mis-users-ca-emergency.pub       ← clé publique + 
-# mis-users-ca-yubi.pub            ← clé publique de la CA Yubikey+# Sortie du container → destruction automatique (--rm) 
 +exit 
 +</code> 
 + 
 +**Note** : si ''debian:trixie-slim'' n'a pas les paquets en cacheprépare une image avec les outils inclus une fois pour toutes : 
 + 
 +<code bash> 
 +# À faire une seule foissur ton hôte 
 +cat > /tmp/Dockerfile <<'EOF' 
 +FROM debian:trixie-slim 
 +RUN apt-get update && \ 
 +    apt-get install -y --no-install-recommends \ 
 +        openssh-client age coreutils && \ 
 +    rm -rf /var/lib/apt/lists/
 +EOF 
 + 
 +docker build -t mis-ca-gen:latest -f /tmp/Dockerfile /tmp/ 
 + 
 +# Puis utiliser cette image (en remplaçant debian:trixie-slim) : 
 +docker run --rm -it --network none -v ~/mis-ssh-ca:/output mis-ca-gen:latest bash 
 +</code> 
 + 
 +**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 ~/mis-ssh-ca:/output:Z mis-ca-gen:latest bash 
 +</code> 
 + 
 +**Résultat sur ton hôte** : 
 + 
 +<code bash> 
 +ls -la ~/mis-ssh-ca/ 
 +# mis-users-ca-emergency.age       ← clé privée DOUBLEMENT chiffrable (age + Bitwarden) 
 +# mis-users-ca-emergency.pub       ← clé publique (pas un secret) 
 +# mis-users-ca-yubi.pub            ← clé publique de la Yubikey CA
 # mis-users-ca-yubi-cert.pub       ← cert X.509 PIV (inutile pour SSH) # mis-users-ca-yubi-cert.pub       ← cert X.509 PIV (inutile pour SSH)
 </code> </code>
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'hôtes. 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'hôtes.
  
-==== Étape 2.6 : Sauvegarde dans Bitwarden ====+==== Étape 2.6 : Stratégie de stockage des secrets (double chiffrement) ====
  
-Créer une entrée Bitwarden **"MIS SSH CA - Master Backup"** avec :+**Principe** : la clé emergency est protégée par **deux couches** indépendantes :
  
-**Notes (champ texte)** : 
 <code> <code>
-=== Yubikey CA (slot 9c PIV) === +Clé privée Ed25519 (claire) 
-Serial: [serial Yubikey+        ↓ 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 +</code> 
-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'entrée)** : 
 + 
 +<code> 
 +═══════════════════════════════════════════════ 
 +PROCÉDURE DE RÉCUPÉRATION D'URGENCE 
 + 
 +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 : 
 +     docker run --rm -it --network none -v $PWD:/work mis-ca-gen bash 
 +     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 
 +     exit 
 + 
 +═══════════════════════════════════════════════ 
 +INFOS YUBIKEY CA 
 + 
 +Serial number    : [serial à compléter
 +PIN PIV          : [PIN à compléter
 +PUK              : [PUK à compléter
 +Algorithme       : ECCP384 
 +Slot             : 9c 
 +Touch policy     : CACHED 
 +PIN policy       : ONCE 
 + 
 +═══════════════════════════════════════════════ 
 +FINGERPRINTS (vérification d'intégrité)
  
-=== Emergency CA (fichier age) === +Yubikey CA pub   : [ssh-keygen -l -f mis-users-ca-yubi.pub
-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+
 </code> </code>
  
-**Attachments** : +**Attachments (fichiers attachés à l'entrée)** :
-  * ''mis-users-ca-emergency.age'' (la clé privée emergency chiffrée) +
-  * ''mis-users-ca-emergency.pub'' (clé publique emergency) +
-  ''mis-users-ca-yubi.pub'' (clé publique Yubikey)+
  
-**Stratégie de la passphrase** : +^ Fichier ^ Sensibilité ^ Pourquoi dans Bitwarden ^ 
-  * **NE PAS** la stocker dans Bitwarden (sinon compromission Bitwarden = compromission CA) +''mis-users-ca-emergency.age'' | DOUBLEMENT chiffré | Clé privée emergencyinutilisable sans la passphrase age | 
-  * L'écrire sur papier, dans le coffre physique du bureau MIS +| ''mis-users-ca-emergency.pub'' | Publique (pas un secret) | Pratique pour la déployer et la vérifier | 
-  * Idéalement : passphrase Diceware 6-8 motsmémorisable +| ''mis-users-ca-yubi.pub'' | Publique (pas un secret| Pratique pour le déploiement | 
-  * Optionnel : la séparer en 2 morceaux (Shamir Secret Sharingentre coffres distincts+| ''mis-users-ca-deploy.pub'' | Publique | Concaténation des pubs prête à déployer |
  
-**Backup additionnel hors-Bitwarden** : +**Ce qui ne doit JAMAIS aller dans Bitwarden** : 
-  * Clé USB chiffrée (LUKSdans coffre physique avec une copie de tout le dossier ''~/mis-ssh-ca/''+  * ❌ 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, mais à ne pas chercher à faire) 
 + 
 +=== 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 : ''correct horse battery staple winter coffee'' (à remplacer évidemment). 
 + 
 +**Approche avancée (optionnelle)** : Shamir Secret Sharing avec ''ssss-split'' pour découper la passphrase en N parts dont K nécessaires. Exemple : 3 parts, 2 nécessaires, distribuées entre Vincent + associé + avocat de confiance. Sécurité maximale, mais à mettre en place quand tout le reste est rodé. 
 + 
 +=== Backup hors-Bitwarden additionnel === 
 + 
 +En complément (ceinture-bretelles) 
 +  * Clé USB chiffrée LUKS dans coffre physique avec une copie de tout ''~/mis-ssh-ca/''
   * À refaire à chaque rotation/renouvellement de CA   * À refaire à chaque rotation/renouvellement de CA
 +  * 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'étape qui te garantit que le jour J, la procédure fonctionnera vraiment.
 +
 +<code bash>
 +# 1. Dans un dossier temporaire de test
 +mkdir /tmp/test-recovery && cd /tmp/test-recovery
 +
 +# 2. Copier le .age depuis Bitwarden (téléchargement de l'attachment)
 +# OU depuis ~/mis-ssh-ca/ si encore dispo
 +cp ~/mis-ssh-ca/mis-users-ca-emergency.age .
 +
 +# 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'écrite sur papier
 +
 +# 5. Vérifier que la clé déchiffrée est bien la bonne
 +ssh-keygen -y -f recovery-key > recovered.pub
 +diff recovered.pub ~/mis-ssh-ca/mis-users-ca-emergency.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 /tmp/test-recovery
 +</code>
 +
 +**Si le test réussit, tu as validé** :
 +  * ✅ La passphrase est correctement écrite sur papier (lisible, sans erreur)
 +  * ✅ Le fichier ''.age'' dans Bitwarden n'est pas corrompu
 +  * ✅ 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 ''.age'' ?) et regénérer si nécessaire.
 +
 +**À refaire annuellement** dans le cadre du drill de récupération (voir checklist en fin de doc).
  
 ---- ----
Ligne 438: Ligne 584:
   "$PUBKEY"   "$PUBKEY"
  
 +# 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 (''mis-users-ca-yubi.pub'')   * [ ] Clé publique Yubikey CA exportée (''mis-users-ca-yubi.pub'')
-  * [ ] Emergency CA générée offline + chiffrée avec age +  * [ ] Image Docker ''mis-ca-gen'' préparée 
-  * [ ] Backup Bitwarden : attachments + notes + passphrase sur papier en coffre+  * [ ] Emergency CA générée dans container éphémère + chiffrée avec age 
 +  * [ ] Bitwarden : entrée "MIS SSH CA - Master Backup" avec attachments 
 +  * [ ] Passphrase age écrite sur papier dans coffre bureau MIS 
 +  * [ ] Passphrase age (copie) dans coffre backup (maison ou bancaire)
   * [ ] 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