Introduction
Les certificats TLS constituent le fondement des communications sécurisées sur Internet, mais leur architecture sous-jacente semble souvent opaque pour les développeurs et les opérateurs. Une chaîne de certificats mal configurée, un certificat feuille expiré ou un certificat intermédiaire oublié peuvent mettre un service hors ligne instantanément. Ce guide démystifie les certificats TLS en reliant les concepts architecturaux à des commandes pratiques, des sorties attendues et des procédures de récupération. Que vous gériez Nginx, Kubernetes Ingress ou une application personnalisée, vous apprendrez à inspecter, valider et exploiter les certificats TLS en toute sécurité.
Nous mettrons l'accent sur la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier chaque résultat et documenter les chemins de récupération. Chaque section comprend des commandes OpenSSL concrètes, des scénarios de panne réalistes et des listes de contrôle que vous pourrez adapter à votre environnement.
Inventaire des versions et de l'environnement
Avant de toucher à une configuration TLS, vous avez besoin d'un inventaire complet de votre environnement. Commencez par identifier :
- La version d'OpenSSL installée et les protocoles pris en charge (TLS 1.2, TLS 1.3).
- La topologie de déploiement (équilibreurs de charge, proxys inverses, services backend).
- Les fichiers de certificats et leurs emplacements.
- Les clés privées et leurs contrôles d'accès.
Exécutez ces commandes en lecture seule pour capturer l'état actuel :
openssl version -a
Exemple de sortie :
OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
built on: Thu Mar 17 14:48:56 2022 UTC
platform: debian-amd64
options: bn(64,64) md2(int) rc4(16x,int) des(int) blowfish(ptr)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG
Notez la version exacte ; les versions plus anciennes peuvent ne pas prendre en charge TLS 1.3 ou les suites de chiffrement modernes.
Ensuite, listez tous les fichiers de certificats sur le système avec leurs horodatages :
find /etc/ssl /etc/nginx /etc/kubernetes -name '*.pem' -o -name '*.crt' -o -name '*.key' 2>/dev/null | xargs ls -l
Cela vous donne les permissions des fichiers, la propriété et les dates de modification. Vérifiez toujours que les clés privées ne sont lisibles que par le compte de service (par exemple, mode 600).
Critique : capturez l'état actuel dans un journal horodaté, y compris les empreintes de certificats et les périodes de validité. Utilisez la commande suivante pour chaque certificat :
openssl x509 -in <certificat.pem> -noout -subject -issuer -serial -dates -fingerprint -sha256
Exemple de sortie :
subject=C = US, ST = California, L = San Francisco, O = Example Corp, CN = api.example.com
issuer=C = US, O = Let's Encrypt, CN = R3
serial=04C8D2E3A1B4F5
notBefore=Jan 1 00:00:00 2025 GMT
notAfter=Mar 31 23:59:59 2025 GMT
SHA256 Fingerprint=A1:B2:C3:D4:E5:F6:07:08:09:0A:0B:0C:0D:0E:0F:10:11:12:13:14:15:16:17:18:19:1A
Stockez cette sortie dans un système de notes sécurisé. Cette base de référence devient inestimable lors des interventions sur incident.
Chemin de configuration sûr
Modifier les paramètres TLS est risqué ; suivez un processus rigoureux pour minimiser les interruptions. Le principe fondamental : séparez l'observation de l'intervention. Ne mélangez jamais une lecture d'état avec un changement d'état.
Commandes d'inspection en lecture seule
Avant de modifier quoi que ce soit, inspectez le certificat et la clé actuels :
# Voir les détails du certificat (sans modification)
openssl x509 -in /etc/nginx/ssl/api.example.com.crt -noout -text | head -30
Cela affiche le certificat entièrement analysé. Vérifiez les noms alternatifs de sujet (SAN) :
openssl x509 -in /etc/nginx/ssl/api.example.com.crt -noout -ext subjectAltName
Exemple de sortie :
X509v3 Subject Alternative Name:
DNS:api.example.com, DNS:api.internal.example.com, IP Address:10.0.0.10
Si le nom d'hôte que vous servez est absent, les clients rejetteront le certificat.
Testez un point de terminaison distant sans rien changer :
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts < /dev/null
Recherchez deux lignes critiques dans la sortie :
Verify return code: 0 (ok)
et le protocole négocié :
Protocol : TLSv1.3
Si la vérification échoue, notez le code d'erreur. Un code 19 signifie un certificat auto-signé dans la chaîne, tandis que 20 signifie l'impossibilité d'obtenir le certificat de l'émetteur local.
Validation de chaîne hors ligne
Avant de déployer un nouveau certificat, validez la chaîne hors ligne :
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt -untrusted /etc/nginx/ssl/intermediate.crt /etc/nginx/ssl/api.example.com.crt
Succès attendu :
api.example.com.crt: OK
Si vous recevez une erreur telle que unable to get local issuer certificate, le certificat intermédiaire est manquant ou non fiable. Incluez la chaîne complète (feuille + intermédiaires) dans la configuration de votre serveur, mais n'incluez jamais la racine ; les clients l'ont déjà.
Changement minimal et vérification
Lorsque vous devez modifier quelque chose, effectuez une petite modification réversible. Par exemple, si vous mettez à jour le chemin du certificat de Nginx :
Modifiez /etc/nginx/sites-available/api.example.com :
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/nginx/ssl/api.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/api.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
}
Après la modification, testez la configuration avant de recharger :
nginx -t
Sortie attendue :
nginx: configuration file /etc/nginx/nginx.conf test is successful
Rechargez ensuite, puis vérifiez immédiatement avec s_client et votre comparaison d'empreinte de référence. Conservez une sauvegarde du certificat et de la clé précédents pour permettre un retour en arrière.
Vérification et diagnostics
Cette section vous propose une approche systématique pour diagnostiquer les problèmes TLS. Traitez chaque diagnostic comme une expérience avec un résultat attendu clair.
Étape 1 : Vérifier les fichiers de certificat
Exécutez la commande openssl x509 de la section d'inventaire sur chaque certificat. Vérifiez :
notBeforeetnotAfter: assurez-vous que l'heure actuelle est dans la plage.subjectetissuer: confirmez l'autorité de certification prévue.X509v3 Key UsageetExtended Key Usage: pour les certificats de serveur, ils doivent inclureDigital Signature, Key EnciphermentetTLS Web Server Authentication.
Utilisez openssl x509 -purpose pour obtenir une évaluation rapide :
openssl x509 -in api.example.com.crt -noout -purpose
S'il indique Certificate purposes: SSL server : Yes, tout va bien.
Étape 2 : Vérifier la correspondance de la clé privée
Assurez-vous que la clé publique du certificat correspond à la clé privée :
openssl x509 -in api.example.com.crt -noout -pubkey > cert.pub
openssl pkey -in api.example.com.key -pubout > key.pub
diff cert.pub key.pub
Si diff ne produit aucune sortie, elles correspondent. Sinon, vous avez une paire incompatible et les clients verront des échecs de négociation.
Étape 3 : Tester le point de terminaison en direct
Utilisez openssl s_client avec une sortie de débogage pour voir les détails de la négociation :
openssl s_client -connect api.example.com:443 -servername api.example.com -state -msg
L'option -state affiche les états de négociation ; -msg montre les messages de protocole. Recherchez des anomalies telles que alert certificate expired.
Pour tester une version TLS spécifique :
openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_2
Si vous voulez vérifier que TLS 1.0 est désactivé (ce qui devrait être le cas), utilisez -no_tls1 ou spécifiez -tls1 et attendez-vous à un échec.
Étape 4 : Examiner la chaîne présentée par le serveur
Dans la sortie de s_client, trouvez la section Certificate chain :
Certificate chain
0 s:C = US, ST = California, L = San Francisco, O = Example Corp, CN = api.example.com
i:C = US, O = Let's Encrypt, CN = R3
1 s:C = US, O = Let's Encrypt, CN = R3
i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
Si le serveur n'envoie pas le certificat intermédiaire 1, de nombreux clients (en particulier mobiles) ne pourront pas construire la chaîne. Assurez-vous que la configuration de votre serveur inclut le fichier de chaîne complète.
Étape 5 : Vérifier la révocation du certificat (facultatif)
Si votre environnement utilise OCSP (Online Certificate Status Protocol), interrogez le répondeur :
openssl ocsp -issuer intermediate.crt -cert api.example.com.crt -url http://r3.o.lencr.org -text
Recherchez Response verify OK et Cert Status: good.
Modes de défaillance et récupération
Les pannes TLS affichent souvent des messages d'erreur cryptiques. Voici des scénarios courants, leurs causes et les étapes de récupération.
Certificat expiré
Symptômes : les navigateurs affichent NET::ERR_CERT_DATE_INVALID, s_client renvoie alert certificate expired, ou votre surveillance alerte sur la date notAfter.
Diagnostic :
openssl x509 -in api.example.com.crt -noout -dates
La sortie affiche :
notBefore=Jan 1 00:00:00 2025 GMT
notAfter=Mar 31 23:59:59 2025 GMT
La date actuelle est après le 31 mars. Récupération : obtenez un nouveau certificat auprès de votre autorité de certification, installez-le et rechargez le service. Vérifiez immédiatement avec s_client. Pour éviter toute récidive, mettez en place un renouvellement automatisé (par exemple, certbot avec un timer systemd) et surveillez l'expiration avec un service comme UptimeRobot ou un script personnalisé.
Nom d'hôte incompatible
Symptômes : les navigateurs affichent ERR_CERT_COMMON_NAME_INVALID, et s_client renvoie alert bad certificate.
Diagnostic :
openssl s_client -connect api.example.com:443 -servername api.example.com < /dev/null | openssl x509 -noout -ext subjectAltName
La sortie peut afficher :
X509v3 Subject Alternative Name:
DNS:api.olddomain.com
Votre client attend api.example.com. Récupération : demandez un nouveau certificat avec les bons SAN, ou si vous utilisez un certificat générique, assurez-vous que le motif correspond (par exemple, *.example.com couvre api.example.com mais pas api.internal.example.com).
Chaîne incomplète
Symptômes : certains clients se connectent correctement (par exemple, les navigateurs de bureau) tandis que d'autres échouent (applications mobiles, API). openssl s_client peut renvoyer verify error:num=20:unable to get local issuer certificate.
Diagnostic : vérifiez la chaîne envoyée par le serveur :
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts < /dev/null
Comptez les certificats sous Certificate chain. Si un seul certificat est affiché (la feuille), l'intermédiaire est manquant. Récupération : concaténez la feuille et l'intermédiaire dans un fichier de chaîne complète :
cat api.example.com.crt intermediate.crt > fullchain.crt
Pointez la directive ssl_certificate de votre serveur vers fullchain.crt et rechargez.
Permission de clé privée refusée
Symptômes : le service ne démarre pas avec une erreur comme cannot load certificate key.
Diagnostic :
ls -l /etc/nginx/ssl/api.example.com.key
Si les permissions sont trop restrictives (par exemple, -rw------- appartenant à root) mais que Nginx s'exécute en tant que www-data, il ne peut pas lire. Récupération : définissez la propriété et les permissions appropriées, par exemple chown root:www-data et chmod 640. Redémarrez ensuite le service.
Incompatibilité de protocole ou de chiffrement
Symptômes : la négociation échoue avec no protocols available ou sslv3 alert handshake failure.
Diagnostic : utilisez s_client pour tester des versions de protocole spécifiques :
openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_3
Si cela échoue mais que TLS 1.2 fonctionne, le serveur peut ne pas prendre en charge TLS 1.3. Récupération : examinez les paramètres ssl_protocols et ssl_ciphers de votre serveur. Pour une large compatibilité, utilisez TLSv1.2 TLSv1.3 et une liste de chiffrement moderne. Rechargez ensuite et retestez.
Plan de retour en arrière
Ayez toujours un plan de retour en arrière avant de déployer des modifications de certificat. Conservez une sauvegarde des fichiers de certificat et de clé précédents, ainsi qu'une copie de la configuration fonctionnelle. Pour Nginx, vous pouvez utiliser une sauvegarde horodatée :
cp api.example.com.crt api.example.com.crt.backup-$(date +%Y%m%d)
cp api.example.com.key api.example.com.key.backup-$(date +%Y%m%d)
cp /etc/nginx/sites-available/api.example.com /etc/nginx/sites-available/api.example.com.backup-$(date +%Y%m%d)
Si la nouvelle configuration échoue, restaurez les sauvegardes et rechargez :
cp api.example.com.crt.backup-20250101 api.example.com.crt
cp api.example.com.key.backup-20250101 api.example.com.key
cp /etc/nginx/sites-available/api.example.com.backup-20250101 /etc/nginx/sites-available/api.example.com
nginx -s reload
Liste de contrôle des opérations
Utilisez cette liste de contrôle pour les opérations courantes sur les certificats et attribuez un responsable unique pour chaque élément. Décidez d'une fréquence de révision : hebdomadaire pour les services à fort trafic, mensuelle pour les services internes ou trimestrielle pour les certificats à longue durée de vie. Le responsable doit vérifier chaque élément selon le calendrier et documenter le résultat.
| Tâche | Responsable | Fréquence | Commande ou vérification | Résultat attendu |
|---|---|---|---|---|
| Vérifier l'expiration du certificat | Priya Shah, responsable ingénierie | Hebdomadaire | openssl x509 -in cert.pem -noout -dates et comparer à la date | notAfter au moins 30 jours dans le futur |
| Vérifier la complétude de la chaîne de certificats | Marcus Chen, ingénieur DevOps | Mensuelle | openssl s_client -showcerts et compter les entrées de chaîne | Au moins 2 certificats (feuille + intermédiaire) |
| Tester la correspondance de la clé privée | Priya Shah, responsable ingénierie | Trimestrielle | openssl x509 -pubkey vs openssl pkey -pubout diff | Aucune sortie de diff |
| Valider la couverture des noms d'hôte | Marcus Chen, ingénieur DevOps | Trimestrielle | openssl x509 -ext subjectAltName | Tous les domaines servis sont listés |
| Examiner le support des protocoles | Priya Shah, responsable ingénierie | Mensuelle | openssl s_client -tls1_3 et -tls1_2 | Les deux se connectent avec succès |
| Vérifier les certificats révoqués | Marcus Chen, ingénieur DevOps | Mensuelle | openssl ocsp -issuer ... -cert ... | Cert Status: good |
| Tester le processus de renouvellement en environnement de préproduction | Priya Shah, responsable ingénierie | Avant chaque renouvellement | Test à blanc avec certbot ou client ACME manuel | Le renouvellement se termine sans erreur |
| Vérifier le plan de sauvegarde et de retour en arrière | Marcus Chen, ingénieur DevOps | Semestrielle | Restaurer à partir de la sauvegarde dans un environnement de test | Le service revient à l'état fonctionnel |
Stockez cette liste de contrôle dans un document partagé ou un système de tickets. Après chaque vérification, le responsable enregistre le résultat et tout écart. Si un écart survient, traitez-le comme un incident et suivez les procédures de récupération des pannes.
Pièges courants et comment les éviter
Comprendre les erreurs courantes peut faire gagner des heures de débogage. Voici cinq pièges fréquents, pourquoi ils surviennent et comment les prévenir ou s'en remettre.
1. Ignorer l'expiration du certificat jusqu'à ce qu'il soit trop tard
Pourquoi cela arrive : les certificats ont une longue validité (jusqu'à 1 an), donc les équipes oublient. Aucune surveillance n'est en place.
Comment éviter : mettez en place une surveillance automatisée avec des alertes à 30, 14 et 7 jours avant l'expiration. Utilisez un outil de surveillance ou un simple cron :
# Vérifier tous les certificats dans /etc/nginx/ssl et avertir s'ils expirent dans les 30 jours
find /etc/nginx/ssl -name '*.crt' -exec openssl x509 -in {} -noout -checkend 2592000 \; -print
Si la sortie est vide, tous les certificats expirent dans plus de 30 jours.
Comment récupérer : ayez un processus de renouvellement testé. Automatisez avec des clients ACME (certbot, lego) qui s'exécutent périodiquement.
2. Utiliser un certificat générique là où il ne convient pas
Pourquoi cela arrive : les certificats génériques comme *.example.com sont pratiques mais ne couvrent pas les sous-domaines à plusieurs niveaux (a.b.example.com) ni les domaines racine différents (example.net).
Comment éviter : avant l'acquisition, listez tous les noms d'hôte que vous devez couvrir. Utilisez un certificat SAN si plusieurs noms exacts sont nécessaires. Vérifiez avec openssl x509 -ext subjectAltName.
Comment récupérer : si vous découvrez des lacunes de couverture, obtenez un nouveau certificat avec les bons SAN et redéployez.
3. Confondre les fichiers de clé privée et de certificat
Pourquoi cela arrive : des noms de fichiers et des extensions similaires (.pem, .key, .crt) prêtent à confusion.
Comment éviter : maintenez une convention de nommage claire : service.example.com.key, service.example.com.crt, service.example.com.fullchain.crt. Stockez-les dans des répertoires séparés si nécessaire. Utilisez régulièrement la vérification de correspondance de clé.
Comment récupérer : si vous écrasez accidentellement un fichier, restaurez à partir de la sauvegarde. S'il n'y a pas de sauvegarde, vous devrez peut-être générer une nouvelle paire de clé et de certificat (et révoquer l'ancienne).
4. Permissions de clé privée trop permissives
Pourquoi cela arrive : par commodité, les développeurs définissent les clés en mode 644 ou 777.
Comment éviter : définissez toujours les clés privées à 600 (ou 640 avec accès de groupe pour le service). Auditez régulièrement les permissions :
find /etc/ssl /etc/nginx -name '*.key' -exec ls -l {} \;
Comment récupérer : si une clé a été exposée, traitez-la comme compromise : révoquez le certificat correspondant, générez une nouvelle clé et un nouveau certificat, et mettez à jour toutes les références.
5. Coder en dur les valeurs de configuration TLS sans contrôle de version
Pourquoi cela arrive : des corrections rapides sont apportées directement sur les serveurs ; les modifications ne sont pas suivies.
Comment éviter : stockez toute la configuration liée à TLS (Nginx, HAProxy, ingress Kubernetes) dans un système de contrôle de version (Git). Utilisez la gestion de configuration (Ansible, Terraform) pour déployer.
Comment récupérer : si la configuration d'un serveur est perdue, vous pouvez redéployer à partir du dépôt. Assurez-vous que les secrets (clés privées) ne sont pas commités ; utilisez un gestionnaire de secrets.
Conclusion
L'architecture des certificats TLS ne concerne pas seulement le chiffrement ; elle relève de la discipline opérationnelle. En suivant les pratiques de ce guide — observer avant de modifier, valider les chaînes hors ligne, tester les points de terminaison, maintenir des listes de contrôle et préparer des plans de retour en arrière — vous pouvez éviter la plupart des pannes liées aux certificats.
Commencez par une tâche à faible risque : exécutez les commandes d'inventaire sur l'un de vos services de production. Enregistrez les détails actuels du certificat, vérifiez la date d'expiration et validez la chaîne. Ensuite, examinez votre surveillance de l'expiration des certificats et assurez-vous d'avoir des alertes automatisées. Attribuez un responsable à la vérification hebdomadaire des certificats et documentez la procédure.
Un flux de travail TLS fiable rend les pannes visibles, protège les clés sensibles, limite les modifications à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision. Avec ces outils, vous pouvez garder vos services sécurisés et disponibles.