Debian 13 : rotation des clés SSH — révoquer proprement les accès et éviter la prolifération des clés (cas n°13)

Cet article vous a aidé ?

La rotation des clés semble simple — jusqu’à ce qu’elle ne le soit plus. Vous changez une clé, quelqu’un ne peut plus déployer, l’accès d’urgence d’une autre équipe se casse, et une clé « temporaire » d’un prestataire oubliée continue de fonctionner — en silence — sur une machine dont personne ne se rappelle la propriété.

C’est la partie des opérations où vous faites soit un changement contrôlé, soit un incident au ralenti avec mille petites coupures. Debian 13 ne change pas les fondamentaux de SSH, mais c’est un bon moment pour arrêter de traiter les clés comme de la monnaie traînante entre les coussins du canapé.

Ce que signifie réellement la « rotation de clés » en production

En laboratoire, faire tourner des clés SSH est une jolie opération en deux étapes : ajouter la nouvelle clé, supprimer l’ancienne. En production, c’est un contrat multipartite que vous renégociez sous contrainte.

Vous ne changez pas seulement un fichier. Vous changez :

  • Identité : quelles clés privées sont considérées comme preuve valide de qui vous êtes.
  • Autorisation : quelles clés publiques se mappent à quels comptes, et avec quelles restrictions.
  • Atteignabilité : quels bastions, runners CI et comptes d’automatisation peuvent encore atteindre ce dont ils ont besoin.
  • Preuve : si vous pouvez ensuite prouver qui avait accès au moment d’un incident.

Une rotation de clés bien menée a trois propriétés :

  1. Réversible en quelques minutes (pendant le déploiement), mais irrémédiable après la fenêtre de grâce (les anciennes clés sont vraiment mortes).
  2. Auditable : vous pouvez répondre à « qui peut se connecter où » sans greper le monde à la main.
  3. Portée limitée : la compromission d’une clé d’une personne ne se transforme pas en « tourner tout partout » sauf si nécessaire.

Une mauvaise rotation signifie généralement que vous tournez la mauvaise chose (clés client vs clés d’hôte), que vous supprimez d’abord et posez des questions ensuite, ou que vous empilez les clés indéfiniment parce que la suppression fait peur.

Clés d’hôte vs clés d’utilisateur : faites tourner la bonne chose

Les clés utilisateur sont celles dans ~/.ssh/authorized_keys qui permettent aux personnes (ou bots) d’entrer. Les clés d’hôte sont ce que vos clients utilisent pour vérifier qu’ils parlent au bon serveur.

La rotation des clés d’hôte suit une procédure différente avec un rayon d’impact distinct. Si votre problème est « un ex-employé a toujours accès » ou « une clé prestataire a fuité », vous vous intéressez aux clés utilisateur et à leurs chemins d’autorisation — pas aux clés d’hôte.

Une citation à garder en tête

Idée paraphraséeRichard Cook : « Le succès dans les systèmes complexes vient souvent des personnes qui s’adaptent constamment, pas du plan qui fonctionne tel quel. »

La rotation des clés, c’est exactement ça : il vous faut un plan, mais vous gagnez en vous adaptant vite quand la réalité diverge.

Faits & historique : pourquoi les clés SSH se multiplient ainsi

La prolifération des clés n’est pas un échec moral. C’est le résultat naturel des incitations : livrer prime sur la maintenance, et SSH est sans friction si on le laisse faire. Quelques faits et éléments de contexte aident à cadrer ce à quoi vous faites face.

  1. SSH a remplacé rsh/telnet principalement sur la base de la confiance et du chiffrement. Le gain initial était « plus de texte en clair », pas « gouvernance d’identité parfaite ». La culture est restée.
  2. OpenSSH a longtemps favorisé la commodité : authorized_keys par utilisateur est simple, donc tout le monde l’a utilisé et des flottes se sont montées autour.
  3. Les types de clés ont évolué : DSA était courant puis déprécié ; RSA est resté omniprésent ; Ed25519 est devenu le choix moderne — petit et rapide.
  4. Le forwarding d’agent SSH visait à réduire la distribution de clés, mais en pratique c’est souvent devenu « une machine distante peut utiliser mon agent », ce qui est… risqué.
  5. known_hosts est un compromis UX : trust-on-first-use était pratique, mais a aussi entraîné les gens à ignorer les avertissements lors de changements de clés d’hôte.
  6. authorized_keys peut contenir des options (restrictions de commande, restrictions d’IP source). La plupart des organisations ne les utilisent pas, puis réinventent ces contrôles ailleurs de façon maladroite.
  7. Les identifiants courts sont historiquement difficiles dans SSH sans outils supplémentaires ; les clés longues sont devenues la norme parce qu’elles « fonctionnent tout simplement ».
  8. CI/CD a aggravé la prolifération : les robots ont besoin d’accès, et les équipes déposent souvent des clés de déploiement « temporairement » sur des machines. « Temporaire » est l’unité de temps la plus longue en exploitation.
  9. Des annuaires centraux existent (LDAP/SSSD, etc.), mais l’autorisation SSH est souvent laissée locale parce que c’est facile et que les interruptions font peur.

La prolifération arrive parce que c’est commode, diffus, et invisible — jusqu’au jour où c’est soudainement très visible.

Mode opératoire de diagnostic rapide (quoi vérifier en premier)

Voici le flux de triage quand quelqu’un dit « nous avons tourné des clés et maintenant SSH est cassé » ou « nous avons révoqué des clés mais l’accès marche encore ». Vous voulez du signal vite, pas un essai.

Première question : est-ce l’authentification, l’autorisation ou le routage ?

  1. Test rapide côté client : le client propose-t-il la clé attendue, et que répond le serveur ?
  2. Journaux du serveur : que pense sshd qu’il s’est passé ?
  3. Source de la configuration serveur : utilisez-vous vraiment des fichiers authorized_keys locaux, ou un AuthorizedKeysCommand, ou les deux ?

Deuxième étape : trouver la « source de vérité »

  • Si l’autorisation est locale, la vérité est distribuée : vous devez localiser chaque authorized_keys et tout include/alternative.
  • Si vous utilisez une commande/SSSD/LDAP, la vérité est centralisée : vérifiez qu’elle est joignable, correcte et que le cache fonctionne comme prévu.
  • Si vous utilisez des certificats SSH, la vérité est la CA et sa politique de signature ; la révocation peut être basée sur le TTL ou un identifiant de clé.

Troisième étape : confirmez que vous avez bien révoqué ce que vous pensez avoir révoqué

  • Une ancienne clé retirée d’un endroit n’aide pas si la même clé existe dans dix autres comptes ou sur un bastion.
  • Les commentaires sur les clés mentent. Les empreintes ne mentent pas. Identifiez toujours par empreinte.
  • N’oubliez pas l’automatisation : root, utilisateurs de déploiement, utilisateurs miroir Git, comptes de sauvegarde, comptes break-glass.

Quand vous êtes coincé : utilisez des logs clients verbeux et les journaux d’authentification côté serveur. Tout le reste, ce sont des impressions.

Construire un inventaire réel : comptes, clés et chemins

Avant de révoquer, faites l’inventaire. Pas parce que la paperasse est amusante, mais parce que révoquer sans inventaire, c’est supprimer la seule clé fonctionnelle d’un nœud de stockage à 2 h du matin.

Où se cachent les clés sur des systèmes Debian

  • /home/*/.ssh/authorized_keys — l’évidence.
  • /root/.ssh/authorized_keys — la douloureuse.
  • Comptes de service avec homes personnalisés : /var/lib/*, /srv/*.
  • Emplacements alternatifs via AuthorizedKeysFile (peuvent être multiples).
  • Récupération centralisée via AuthorizedKeysCommand (les clés peuvent ne jamais toucher le disque par utilisateur).
  • Points de dépôt de la gestion de configuration (fragments gérés, fichiers générés).

Choisir votre modèle de révocation

Choisissez un modèle par environnement, pas par équipe.

  • Fichiers locaux, gérés : les clés résident dans authorized_keys, mais sont maîtrisées par un système de CM (Ansible/Puppet/etc.). Simple, mais toujours distribué.
  • Clés centralisées : AuthorizedKeysCommand récupère les clés depuis un magasin central (annuaire, API, DB backée par git). Excellente traçabilité, plus de points en mouvement.
  • Certificats SSH : les utilisateurs s’authentifient avec des certificats éphémères signés par votre CA ; les serveurs font confiance à la CA. Prolifération minimale, meilleur scénario de révocation si vous gérez bien les TTL.

Si vous êtes déjà assez grand pour parler de « flotte », les certificats gagnent. Si vous êtes petit mais discipliné, les fichiers locaux gérés suffisent. Si vous êtes moyen et chaotique, les clés centralisées sont une amélioration de santé mentale — si vous l’ingéniez comme une production, pas comme un projet de week-end.

Révoquer les accès proprement : techniques sans créer d’indisponibilités

La révocation doit être ennuyeuse. L’ennui est l’objectif. L’astuce est d’étaler les modifications pour pouvoir avancer, pas paniquer en reculant.

Technique 1 : Ajouter puis supprimer avec une fenêtre de grâce

Pour les utilisateurs humains : ajouter la nouvelle clé, valider la connexion, puis supprimer l’ancienne clé après un délai. Pour l’automatisation : vous aurez besoin du support de clés doubles pendant le déploiement et d’un basculement explicite.

La fenêtre de grâce doit être courte. Des jours, pas des mois. Les fenêtres longues sont la façon dont on finit par supporter deux mondes indéfiniment.

Technique 2 : Préférez la révocation par empreinte plutôt que par « nom »

Les gens copient des clés, renomment les commentaires, ou collent la mauvaise clé publique. Identifiez toujours les clés par empreinte. Traitez le commentaire comme des métadonnées fournies par l’utilisateur — parce que c’en est.

Technique 3 : Utilisez les options de clé pour limiter le rayon d’impact

Si vous devez conserver des clés longue durée (et beaucoup d’organisations le font), au moins restreignez-les. Exemples de restrictions :

  • from="10.0.0.0/8" pour limiter les IP source
  • command="..." pour forcer une commande (avec précaution)
  • no-agent-forwarding, no-port-forwarding, no-pty

Ce ne sont pas des contrôles parfaits, mais ils transforment « une clé fuit = shell complet depuis n’importe où » en « une clé fuit = accès limité depuis des lieux spécifiques ». C’est une différence significative en réponse à un incident.

Technique 4 : Coupez l’accès au niveau du compte quand nécessaire

Si un utilisateur est licencié ou qu’une clé est confirmée compromise, attendre la suppression des clés est trop lent. Verrouillez le compte et supprimez les clés.

Le verrouillage de compte n’est pas un substitut à l’hygiène des clés, mais c’est un coupe-circuit rapide.

Technique 5 : Concevez volontairement une procédure de break-glass

Il vous faut un accès d’urgence. Mais « tout le monde a une clé root au cas où » n’est pas un accès d’urgence ; c’est de la prolifération de clés généreuse.

Le break-glass doit signifier : un petit ensemble de clés/certs contrôlés, stockés en sécurité, avec journalisation, et testés lors d’exercices. Si vous ne le testez jamais, il échouera quand vous en aurez besoin.

Blague #1 : La prolifération des clés SSH, c’est comme un tiroir à bazar : un jour vous en aurez besoin, et il vous décevra toujours.

Éviter la prolifération des clés : contrôle centralisé, options et certificats SSH

La révocation, c’est le nettoyage. Éviter la prolifération, c’est la prévention. La prévention coûte moins cher, va plus vite et est moins humiliant.

Centralisez la décision, pas nécessairement les clés

Beaucoup d’équipes lisent « centraliser » comme « mettre toutes les clés dans un fichier ». Ce n’est pas l’objectif. L’objectif est de centraliser l’autorité : qui peut accorder l’accès, comment c’est approuvé, et comment c’est audité.

Bonnes pratiques :

  • La gestion de configuration génère authorized_keys depuis un inventaire central et l’applique.
  • AuthorizedKeysCommand récupère les clés depuis un service d’annuaire et ne renvoie que les clés actuelles et approuvées.
  • Les certificats SSH suppriment le besoin de distribuer les clés publiques utilisateur sur chaque hôte.

Certificats SSH : l’option adulte pour les flottes

Les certificats utilisateur SSH (OpenSSH) permettent aux serveurs de faire confiance à une CA, pas à des clés individuelles. Les utilisateurs conservent leurs clés privées ; la CA signe un certificat court qui dit « cette clé est valide pour l’utilisateur X pendant N heures, avec ces principaux. »

Ce que cela change opérationnellement :

  • La rotation devient surtout une politique de CA : émettre des certificats courts, et la « révocation » devient « attendre le TTL » plus désactiver la signature.
  • L’intégration est plus rapide : les serveurs font déjà confiance à la CA ; les nouveaux utilisateurs ne nécessitent pas de toucher chaque hôte.
  • Le désengagement est plus propre : arrêter de signer pour l’utilisateur et attendre le TTL. Pas de chasse aux clés sur toute la flotte.

Des modes de défaillance existent : disponibilité de la CA, bugs dans le workflow de signature, problèmes de synchronisation horaire. Mais ce sont des problèmes que vous pouvez architecturer. La prolifération est un bazar socio-technique qui ne disparaît jamais complètement.

Rendez les bastions ennuyeux et stricts

Un bastion est l’endroit où votre politique d’accès devient applicable. Si vous permettez des SSH directs depuis des ordinateurs portables vers tout, vous avez choisi le chaos.

Par défaut, les bastions devraient :

  • Interdire l’agent forwarding sauf justification et contraintes.
  • Journaliser fortement (enregistrer les sessions si le profil de risque l’exige).
  • Contrôles réseau : les serveurs acceptent SSH seulement depuis les bastions/les plages VPN.
  • Accès court là où c’est possible.

Tâches pratiques avec commandes, sorties et décisions (12+)

Voici des tâches terrain que vous pouvez exécuter sur Debian 13. Chaque tâche inclut : une commande, ce que la sortie signifie, et la décision à prendre ensuite. Servez-vous en lors d’une rotation, d’une réponse à incident ou d’un audit.

Task 1: Confirm what sshd is really using for authorized keys

cr0x@server:~$ sudo sshd -T | egrep -i 'authorizedkeys(file|command)|pubkeyauthentication|passwordauthentication'
pubkeyauthentication yes
passwordauthentication no
authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2
authorizedkeyscommand none

Sens : Cet hôte utilise des fichiers par utilisateur ; pas de commande de clé centralisée. L’authentification par mot de passe est désactivée (bien).

Décision : La révocation doit toucher les fichiers sur disque (ou migrer vers un modèle géré/central). Inventoriez les chemins authorized_keys pour chaque compte.

Task 2: Verify sshd is running the config you think it is

cr0x@server:~$ systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-12-29 11:02:14 UTC; 3h 18min ago
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 1023 (sshd)
      Tasks: 1 (limit: 18956)
     Memory: 5.7M
        CPU: 1.421s
     CGroup: /system.slice/ssh.service
             └─1023 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

Sens : sshd est actif. La ligne de commande montre que le démon est le binaire attendu.

Décision : Si les changements ne prennent pas effet, vous avez probablement modifié le mauvais fichier, un problème d’ordre d’inclusion, ou oublié de recharger.

Task 3: Validate config includes and catch foot-guns before reload

cr0x@server:~$ sudo sshd -t
cr0x@server:~$ echo $?
0

Sens : Le code de sortie 0 signifie que la syntaxe de la config est valide.

Décision : Procédez avec systemctl reload ssh. Si non zéro, ne rechargez pas — corrigez la config d’abord ou vous risquez de vous verrouiller hors du système au redémarrage.

Task 4: Show who can log in (local accounts) and spot surprises

cr0x@server:~$ getent passwd | awk -F: '($3>=1000 && $1!="nobody"){print $1":"$6":"$7}' | head
alice:/home/alice:/bin/bash
bob:/home/bob:/bin/bash
deploy:/srv/deploy:/bin/bash
backup:/var/lib/backup:/usr/sbin/nologin
ci-runner:/var/lib/ci-runner:/bin/bash

Sens : Vous avez des utilisateurs interactifs et des comptes de service. Certains comptes ont des homes non standard.

Décision : Inventoriez les clés pas seulement dans /home mais aussi dans les répertoires home personnalisés. Vérifiez aussi si des comptes nologin ont des clés et s’ils doivent en avoir.

Task 5: Find every authorized_keys file on the host (fast, noisy, effective)

cr0x@server:~$ sudo find / -xdev -type f -name authorized_keys -o -name authorized_keys2 2>/dev/null | head
/root/.ssh/authorized_keys
/home/alice/.ssh/authorized_keys
/home/bob/.ssh/authorized_keys
/srv/deploy/.ssh/authorized_keys

Sens : Ce sont les portes d’accès sur ce système (au vu de la Task 1). Si vous voyez des emplacements inattendus, c’est souvent là que « temporaire » est devenu permanent.

Décision : Pour la rotation, vous devez mettre à jour chacun d’eux. Pour la prévention, appliquez une source de vérité unique et gérée.

Task 6: Extract fingerprints from authorized_keys and dedupe across accounts

cr0x@server:~$ sudo awk '{print $1" "$2}' /home/alice/.ssh/authorized_keys | ssh-keygen -lf -
256 SHA256:6Oq2j0J3j7cD4Yp8v0Fh7u2i9lXkYxJr3tZx0mQy7xM alice@laptop (ED25519)

Sens : Vous avez maintenant une empreinte stable pour la clé. C’est l’identité contre laquelle vous devez tourner/révoquer.

Décision : Constituez une liste d’empreintes à retirer. Si la même empreinte apparaît dans plusieurs comptes, la révocation doit être coordonnée ou vous manquerez un chemin d’accès.

Task 7: Confirm a suspect key is still accepted (server-side test with sshd logs)

cr0x@server:~$ sudo journalctl -u ssh -n 30 --no-pager
Dec 30 09:10:42 server sshd[22144]: Accepted publickey for alice from 10.30.4.18 port 51222 ssh2: ED25519 SHA256:6Oq2j0J3j7cD4Yp8v0Fh7u2i9lXkYxJr3tZx0mQy7xM
Dec 30 09:11:03 server sshd[22190]: Failed publickey for bob from 10.30.4.18 port 51301 ssh2: ED25519 SHA256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Dec 30 09:11:03 server sshd[22190]: Connection closed by authenticating user bob 10.30.4.18 port 51301 [preauth]

Sens : Les journaux du serveur montrent quelle empreinte a été acceptée ou rejetée.

Décision : Si l’empreinte « révoquée » est toujours acceptée, elle existe quelque part dans le chemin d’auth : un autre compte, un autre fichier, des clés centralisées, ou un wrapper de commande forcée.

Task 8: Check whether an account is locked (fast offboarding circuit breaker)

cr0x@server:~$ sudo passwd -S alice
alice P 2025-12-01 0 99999 7 -1

Sens : Le statut P indique que le compte a un hash de mot de passe utilisable. Cela n’indique pas directement l’accès par clé SSH, mais dit si l’authentification par mot de passe pourrait marcher si elle était activée.

Décision : Pour un offboarding immédiat : verrouillez le compte (L) et supprimez les clés. Confirmez aussi que PasswordAuthentication est désactivé (Task 1).

Task 9: Lock an account and verify it’s locked

cr0x@server:~$ sudo usermod -L alice
cr0x@server:~$ sudo passwd -S alice
alice L 2025-12-01 0 99999 7 -1

Sens : L signifie que le mot de passe est verrouillé. L’authentification par clé peut encore fonctionner à moins que vous ne la contrôliez aussi via des options sshd ou la suppression des clés.

Décision : Ne vous arrêtez pas là. Supprimez le matériel de clé ou désactivez l’accès SSH au niveau du compte avec DenyUsers/Match User si vous avez besoin d’un arrêt immédiat du SSH.

Task 10: Enforce “no SSH for this user” using a Match block (surgical, reversible)

cr0x@server:~$ sudo sh -c 'printf "\nMatch User alice\n  PasswordAuthentication no\n  PubkeyAuthentication no\n  KbdInteractiveAuthentication no\n" >> /etc/ssh/sshd_config.d/99-disable-alice.conf'
cr0x@server:~$ sudo sshd -t
cr0x@server:~$ sudo systemctl reload ssh
cr0x@server:~$ sudo sshd -T -C user=alice,host=server,addr=10.30.4.18 | egrep -i 'pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication'
pubkeyauthentication no
passwordauthentication no
kbdinteractiveauthentication no

Sens : La configuration effective pour cet utilisateur a l’authentification par clé désactivée. Cela bloque SSH même si des clés existent encore.

Décision : Utilisez ceci comme blocage d’urgence pendant que vous recherchez les clés distribuées. Supprimez la règle Match une fois le nettoyage terminé.

Task 11: Confirm file permissions won’t silently break key auth

cr0x@server:~$ sudo namei -l /home/alice/.ssh/authorized_keys
f: /home/alice/.ssh/authorized_keys
drwxr-xr-x root  root  /
drwxr-xr-x root  root  home
drwxr-xr-x alice alice alice
drwx------ alice alice .ssh
-rw------- alice alice authorized_keys

Sens : Cela passe les attentes habituelles de permissions strictes. Si vous voyez des répertoires group-writable ou world-writable, sshd peut ignorer le fichier (selon la configuration).

Décision : Corrigez les permissions avant d’accuser les clés. « La rotation des clés a échoué » est souvent en réalité « sshd a refusé de lire le fichier ».

Task 12: Test client behavior with verbose SSH (the truth serum)

cr0x@server:~$ ssh -vvv -i ~/.ssh/id_ed25519 alice@server
debug1: Offering public key: /home/cr0x/.ssh/id_ed25519 ED25519 SHA256:6Oq2j0J3j7cD4Yp8v0Fh7u2i9lXkYxJr3tZx0mQy7xM explicit
debug1: Server accepts key: /home/cr0x/.ssh/id_ed25519 ED25519 SHA256:6Oq2j0J3j7cD4Yp8v0Fh7u2i9lXkYxJr3tZx0mQy7xM explicit
debug1: Authentication succeeded (publickey).
Welcome to Debian GNU/Linux

Sens : Vous voyez quelle clé a été proposée, si le serveur l’accepte, et si l’authentification a réussi.

Décision : Si la mauvaise clé est proposée, corrigez le client (agent, config, fichiers d’identité). Si le serveur accepte une vieille clé, elle est toujours autorisée quelque part.

Task 13: Remove a specific key safely by matching the key body, not the comment

cr0x@server:~$ sudo grep -n 'AAAAC3NzaC1lZDI1NTE5AAAAIFakeKeyBodyGoesHereButLooksRealToHumans' /home/alice/.ssh/authorized_keys
3:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFakeKeyBodyGoesHereButLooksRealToHumans old-laptop
cr0x@server:~$ sudo sed -i '3d' /home/alice/.ssh/authorized_keys
cr0x@server:~$ sudo tail -n +1 /home/alice/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINewKeyBodyLooksDifferent new-laptop

Sens : Vous avez trouvé la ligne exacte par le corps de la clé et l’avez supprimée par numéro de ligne.

Décision : C’est plus sûr que de chercher par commentaire. Après suppression, testez la connexion et vérifiez les logs pour d’éventuelles alternatives inattendues.

Task 14: Detect duplicate keys across the host (cheap sprawl detector)

cr0x@server:~$ sudo find /home /root /srv -xdev -name authorized_keys -type f -print0 2>/dev/null | xargs -0 awk '{print $1" "$2}' | sort | uniq -c | sort -nr | head
      4 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDuplicateKeyBodyExample
      2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQAnotherDupExample

Sens : La même clé publique apparaît plusieurs fois dans des comptes/chemins différents.

Décision : Les clés dupliquées sont presque toujours un problème de gouvernance. Décidez si c’est une clé de bot partagée (mauvaise mais courante) ou une réutilisation accidentelle (pire). Dans tous les cas, prévoyez de séparer les identités.

Task 15: Confirm sshd will reject passwords and keyboard-interactive

cr0x@server:~$ sudo sshd -T | egrep -i 'passwordauthentication|kbdinteractiveauthentication|usepam'
passwordauthentication no
kbdinteractiveauthentication no
usepam yes

Sens : Mot de passe et keyboard-interactive sont désactivés, mais PAM est encore utilisé (souvent pour la configuration de session).

Décision : Bon socle pour l’authentification par clé. Si vous activez provisoirement des méthodes interactives pendant le dépannage, mettez un rappel pour les désactiver ensuite — les exceptions temporaires se fossilient vite.

Task 16: Spot and stop agent forwarding on servers where it shouldn’t exist

cr0x@server:~$ sudo sshd -T | egrep -i 'allowagentforwarding|allowtcpforwarding|permittty'
allowagentforwarding yes
allowtcpforwarding yes
permittty yes

Sens : L’agent forwarding et le forwarding TCP sont autorisés par défaut ici.

Décision : Sur des serveurs de production, surtout ceux qui peuvent atteindre d’autres systèmes sensibles, songez à désactiver le forwarding ou à le limiter via des règles Match. Le forwarding élargit le rayon d’impact d’une session compromise.

Blague #2 : Si vous ne faites pas tourner vos clés SSH, elles ne « vieillissent pas comme le vin ». Elles vieillissent comme du lait dans une salle serveur.

Trois micro-histoires d’entreprise tirées du terrain

Micro-histoire 1 : L’incident causé par une mauvaise hypothèse

L’entreprise avait une politique : « Toutes les clés SSH sont gérées par la gestion de configuration. » Tout le monde y croyait parce que c’était vrai pour la flotte principale d’applications. Les SRE ont fait tourner une clé développeur compromise et l’ont retirée du dépôt CM. Ils ont déclaré victoire, rédigé la note post-incident et sont passés à autre chose.

Une semaine plus tard, un auditeur a posé une question simple : « Cette clé peut-elle encore atteindre quelque chose ? » Quelqu’un a tenté un SSH depuis une machine mise en quarantaine (sûrement, avec approbations) et est entré — sur une machine de reporting de base de données. Pas la base principale. Une machine de reporting « temporaire » créée pour un projet de fin de trimestre des années auparavant n’avait jamais été correctement intégrée au CM.

La mauvaise hypothèse n’était pas technique ; elle était organisationnelle. Ils ont supposé que la couverture de leur outil correspondait à leur modèle mental. Ce n’était pas le cas. La clé vivait dans /root/.ssh/authorized_keys sur un hôte que personne ne patchait régulièrement parce que « ce n’était pas de la production ». Cela suffisait à être de la production.

La correction n’a pas été héroïque. Ils ont écrit un job qui énumère les empreintes de authorized_keys sur tous les hôtes atteignables et compare les empreintes à une liste approuvée. La première exécution fut embarrassante. La deuxième exécution fut exploitable. La troisième exécution fut routinière.

Leçon : si vous ne pouvez pas mesurer où sont les clés, vous n’avez pas de gestion des clés. Vous avez de l’espoir.

Micro-histoire 2 : L’optimisation qui s’est retournée contre eux

Une équipe plateforme a décidé de centraliser rapidement les clés SSH. Ils ont construit un AuthorizedKeysCommand qui interrogeait un service HTTP interne : donnez un nom d’utilisateur, recevez des clés. Bonne idée, déployée vite, applaudie en réunion.

Puis est arrivé le premier véritable incident. Le service de clés a eu une défaillance partielle : l’API était up, mais la latence a explosé à cause d’un problème sur une base de données en aval. Les connexions SSH ne « plantaient » pas. Elles restaient bloquées lors de l’authentification. Les ingénieurs ne pouvaient pas entrer pour corriger l’incident qui causait la latence. Pendant ce temps, l’automatisation basée sur SSH commençait à échouer lentement et de façon imprévisible.

L’équipe avait optimisé pour « source unique de vérité » et oublié d’ingénier la tolérance aux pannes. Pas de cache, pas de fallback, pas de circuit breaker, pas de chemin d’urgence local. Ils avaient déplacé le problème de « clés distribuées » vers « dépendance centrale pour chaque connexion ».

Ils ont récupéré en restaurant temporairement des authorized_keys locaux pour les on-call et comptes break-glass, puis en retravaillant le service de clés : cache sur les hôtes, timeouts stricts, et un design qui échoue fermé pour les utilisateurs normaux mais s’ouvre pour le break-glass dans des conditions contrôlées (avec alarmes).

Leçon : la centralisation n’est pas un plat gratuit. C’est échanger un bazar que vous pouvez greper contre un service que vous devez gérer sérieusement — parce que c’est important.

Micro-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une entreprise proche des finances exploitait une petite flotte mais avait une habitude douloureusement conservatrice : chaque rotation de clé avait un runbook et une « fenêtre de chevauchement à deux clés ». Ils maintenaient aussi un petit processus de break-glass testé chaque trimestre. Les gens se plaignaient que c’était lent. Les gens se plaignent toujours des choses qui fonctionnent.

Un après-midi, un laptop avec des clés SSH a été volé dans la voiture d’un ingénieur. L’ingénieur l’a signalé immédiatement. La sécurité a déclaré une compromission d’identifiants et demandé une preuve que l’accès était révoqué en production.

La personne d’astreinte a suivi le runbook : identifier les empreintes depuis les clés publiques connues de l’ingénieur, bloquer l’utilisateur via un fichier Match sur les bastions en quelques minutes, puis pousser une mise à jour CM supprimant les empreintes sur tous les hôtes de production. La fenêtre de chevauchement n’était pas nécessaire ; c’était une révocation ferme. Ils ont validé la révocation en tentant une authentification depuis un environnement contrôlé et en vérifiant les logs sshd pour des empreintes rejetées.

Les preuves d’audit se sont écrites toutes seules : tickets de changement, diff CM, logs de déploiement, et journaux système montrant les tentatives rejetées. L’incident est resté petit parce que la pratique était ennuyeuse, documentée et répétée.

Leçon : les contrôles de sécurité les plus efficaces sont souvent ceux que votre équipe peut exécuter sous stress sans improviser.

Erreurs courantes : symptôme → cause racine → correction

Voici les modes de défaillance récurrents qui rendent la rotation des clés maudite. La plupart sont prévisibles. C’est une bonne nouvelle.

1) Symptom: “We removed the key, but it still logs in”

Cause racine : La clé existe dans le authorized_keys d’un autre compte, dans un autre chemin défini par AuthorizedKeysFile, ou est récupérée par AuthorizedKeysCommand. Parfois c’est la même clé privée utilisée ailleurs via l’agent forwarding.

Correction : Identifiez par empreinte dans les logs sshd, puis recherchez cette empreinte/corps de clé sur toute la flotte. Vérifiez aussi les bastions et comptes partagés. Désactivez l’agent forwarding là où ce n’est pas nécessaire.

2) Symptom: “New key doesn’t work on one server, works everywhere else”

Cause racine : Permissions/ownership sur ~/.ssh ou authorized_keys trop permissives, ou le répertoire home de l’utilisateur n’a pas les perms corrects.

Correction : Utilisez namei -l pour vérifier chaque composant de chemin. Corrigez propriétaires et modes. Confirmez la config effective de sshd et le comportement de StrictModes.

3) Symptom: “CI deploys started failing right after rotation”

Cause racine : L’automatisation utilisait une clé de déploiement partagée qui n’a pas été tournée, ou elle était épinglée dans un magasin de secrets et pas mise à jour partout. Parfois le runner CI utilise un agent SSH avec plusieurs identités et propose maintenant la mauvaise clé en premier.

Correction : Inspectez les logs du job CI pour la clé proposée. Épinglez la clé exacte avec IdentitiesOnly yes et IdentityFile explicite sur le runner. Faites tourner les clés de bot séparément avec un basculement étagé.

4) Symptom: “After centralizing keys, SSH logins randomly hang”

Cause racine : AuthorizedKeysCommand dépend d’un service lent. Le chemin d’authentification est maintenant couplé au réseau et sensible à la latence.

Correction : Ajoutez du cache, des timeouts et de l’observabilité. Assurez-vous que la commande échoue vite. Envisagez des snapshots de clés locaux mis à jour régulièrement.

5) Symptom: “People keep appending keys and never remove them”

Cause racine : Pas de propriétaire, pas de processus, pas de visibilité. La suppression paraît risquée parce que personne ne sait ce que cela cassera.

Correction : Faites-en sorte que ce soit géré via CM ou un magasin central. Ajoutez des rapports (clés par compte, âge, dernier usage via les logs). Exigez une date d’expiration ou un passage en revue régulier.

6) Symptom: “Host key warnings popped up during the change”

Cause racine : Vous avez tourné des clés d’hôte (ou reconstruit des serveurs) sans plan de distribution pour known_hosts, ou vous réutilisez des DNS/IP causant des incompatibilités.

Correction : Séparez la gestion des clés d’hôte de la rotation des clés utilisateur. Utilisez des mécanismes stables de distribution des clés d’hôte ou des mises à jour soigneusement gérées de known_hosts dans l’automatisation.

Listes de contrôle / plan étape par étape

Ceci est le plan qui fonctionne quand vous êtes fatigué, occupé et entouré de systèmes qui se moquent de vos sentiments.

Checklist A: Controlled rotation (planned change)

  1. Définir l’étendue : quels utilisateurs, quels hôtes, quels comptes d’automatisation.
  2. Extraire les empreintes des anciennes clés à retirer (conservez-les dans le ticket de changement).
  3. Inventorier les chemins d’autorisation : sshd -T, trouver les fichiers authorized_keys, identifier tout AuthorizedKeysCommand.
  4. Préparer les nouvelles clés : ajoutez les nouvelles clés partout où nécessaire ; ne retirez pas encore les anciennes.
  5. Valider l’accès : utilisez ssh -vvv pour des clients représentatifs ; vérifiez journalctl -u ssh pour les empreintes acceptées.
  6. Fixer la fenêtre de grâce : communiquer la date butoir ; gardez-la courte.
  7. Basculement : retirez les anciennes empreintes ; rechargez sshd si la config a changé.
  8. Prouver la révocation : tentez une connexion avec l’ancienne clé depuis un environnement contrôlé ; vérifiez les logs pour un rejet.
  9. Nettoyage : retirez les blocs Match temporaires, les tickets et les fichiers de clés obsolètes. Mettez à jour l’inventaire.

Checklist B: Emergency revocation (suspected compromise)

  1. Identifier les empreintes des clés suspectes (depuis l’inventaire des appareils de l’employé, les logs ou les magasins de clés).
  2. Bloquer vite aux points de restriction : bastions en premier. Utilisez Match User ou DenyUsers comme mesure tampon immédiate.
  3. Désactiver l’émission si vous utilisez des certificats ; sinon supprimez les clés du magasin central/CM.
  4. Chasser les duplicata : les clés de déploiement partagées et les clés copiées sont courantes. Ne supposez pas qu’il n’y a qu’un seul emplacement.
  5. Valider via les logs : vérifiez les tentatives rejetées pour l’empreinte.
  6. Nettoyage post-incident : tournez les clés de bot, réduisez le forwarding, contraignez les options de clé, et corrigez le manque d’inventaire qui a permis la prolifération.

Checklist C: Anti-sprawl baseline for Debian 13 sshd

  • Authentification par mot de passe désactivée sauf raison solide.
  • Centraliser les décisions d’autorisation (CM, commande de clés centralisée, ou certificats).
  • Restreindre l’accès réseau SSH (bastion/VPN seulement).
  • Désactiver agent/tcp forwarding par défaut ; activer par rôle via Match.
  • Journaliser suffisamment pour l’audit (et exporter les logs hors hôte).
  • L’accès break-glass existe, est minimal et est testé.

FAQ

1) Do I need to rotate SSH keys regularly, even without a breach?

Oui, mais pas aveuglément. Faites tourner lors de changements de rôle, départs, perte d’un appareil, et selon des intervalles basés sur la politique pour les accès à risque élevé. Si vous pouvez passer à des certificats SSH courts, la rotation devient essentiellement automatique.

2) What’s the cleanest way to revoke access for one user right now?

Bloquez le SSH pour cet utilisateur avec une règle Match User sur les bastions (ou directement sur l’hôte si nécessaire), puis retirez ses clés de la vraie source d’autorisation. Validez avec les logs et une tentative de connexion contrôlée.

3) If I lock the Linux account, does that block SSH key login?

Pas de façon fiable. Le verrouillage de compte affecte l’authentification par mot de passe et parfois le comportement PAM, mais l’authentification par clé publique peut encore réussir selon la configuration. Traitez le verrouillage de compte comme un coupe-circuit, pas comme la solution complète.

4) How do I know which key was used in a login?

Consultez les logs sshd : les lignes d’authentification publique réussie incluent le type de clé et l’empreinte. Sur Debian, journalctl -u ssh est généralement le moyen le plus rapide.

5) We have hundreds of servers. Is grepping authorized_keys everywhere the only option?

C’est l’option « fonctionne aujourd’hui », pas celle qui scale. À l’échelle d’une flotte, utilisez l’enforcement par gestion de configuration, une commande de clés autorisées centralisée avec cache, ou — mieux — des certificats utilisateur SSH.

6) Are SSH certificates complicated to run?

Ils sont opérationnellement différents, pas intrinsèquement plus difficiles. Vous échangez la distribution de clés contre des opérations CA : signature sécurisée, politiques, synchronisation temporelle et workflows d’émission. Si vous gérez déjà une PKI de production ou des systèmes d’identité, c’est un ajustement naturel.

7) Should we allow agent forwarding?

Par défaut non. Autorisez-le seulement là où il réduit significativement la distribution de clés et où les hôtes cibles sont fiables et durcis. L’agent forwarding transforme un serveur compromis en tremplin.

8) What’s the fastest way to detect key sprawl on a single host?

Exécutez sshd -T pour confirmer le mécanisme d’auth, puis énumérez les fichiers authorized_keys et comptez les corps/empreintes de clés dupliquées entre eux. Les duplicata sont votre premier signal d’alarme.

9) Why do we still see old keys in files after we “migrated to centralized keys”?

Parce que les migrations sont souvent partielles. Si AuthorizedKeysFile est toujours activé et que les fichiers existent encore, sshd peut toujours les honorer. Décidez d’un chemin, puis appliquez-le, y compris en supprimant ou en ignorant les fichiers hérités.

10) How do we prove to auditors that a key was revoked?

Conservez l’empreinte dans le dossier de changement, montrez le diff/suppression dans la source d’autorisation, et capturez les logs sshd montrant le rejet/l’absence d’acceptation après le basculement.

Conclusion : prochaines étapes qui tiennent

Si vous retenez une leçon du cas n°13, que ce soit celle-ci : la rotation des clés est un problème de gouvernance déguisé en crypto. Debian 13 vous donne les mêmes outils tranchants ; votre travail est de les manier de façon cohérente.

Faites ceci ensuite, dans l’ordre :

  1. Choisissez votre modèle d’autorisation (fichiers locaux gérés, clés centralisées ou certificats) et cessez de mélanger au hasard.
  2. Construisez un inventaire basé sur les empreintes pour pouvoir répondre à « qui a accès » sans deviner.
  3. Entraînez la révocation d’urgence en utilisant des points de contrôle bastion et des règles Match testées.
  4. Raccourcissez la durée de vie des identifiants partout où c’est possible — TTL de certificats, options de clés plus strictes, moins de clés partagées.
  5. Mesurez la prolifération : nombre de clés par compte, duplicata, et clés non vues dans les logs depuis des mois.

Rendez l’hygiène des clés ennuyeuse. Votre futur vous en astreinte, en plein service à une heure déraisonnable, vous en sera reconnaissant — et se plaindra toujours, mais avec moins d’incidents.

← Précédent
Problèmes MTU sur les réseaux Docker : pourquoi les grosses requêtes échouent et comment corriger MTU/MSS
Suivant →
Debian 13 : SSHFS vs NFS — choisissez celui qui ne se fige pas (et configurez-le correctement)

Laisser un commentaire