Introduction
Un laboratoire TLS local permet de s'exercer à la génération de certificats, à la configuration de serveur et au débogage sans risquer d'affecter la production. Dans ce guide, vous allez :
- Créer une autorité de certification (CA) locale
- Émettre un certificat serveur pour
app.local(127.0.0.1) - Configurer un reverse proxy Nginx avec TLS et des valeurs par défaut sécurisées
- Valider avec
curletopenssl - Ajouter optionnellement l'authentification mutuelle TLS (certificats clients)
- Voir comment réutiliser ces artefacts dans un Ingress Kubernetes
L'accent est mis sur une configuration étroite et testable que vous pouvez inspecter entièrement sur votre machine. Restez local, restez simple, et n'ajoutez de la complexité qu'après avoir mis en place des vérifications fiables.
Vue d'ensemble du flux de travail
Un flux de travail clair et par étapes réduit le retravail et accélère l'apprentissage :
Choisissez des noms d'hôte qui ne résolvent jamais publiquement, par exemple app.local et api.local. Associez-les à 127.0.0.1 dans votre fichier hosts :
- Nommez vos points de terminaison locaux
- Linux/macOS :
/etc/hosts - Windows :
C:\Windows\System32\drivers\etc\hosts
Exemple d'entrées :
127.0.0.1 app.local
127.0.0.1 api.local
Vous avez deux options courantes. Choisissez-en une.
- Créez une CA locale et émettez un certificat serveur
Option A : OpenSSL (fonctionne partout)
mkdir -p certs
openssl genrsa -out certs/rootCA.key 4096
openssl req -x509 -new -nodes -key certs/rootCA.key -sha256 -days 3650 -out certs/rootCA.crt -subj "/CN=lab-root-ca"
openssl genrsa -out certs/app.local.key 2048
openssl req -new -key certs/app.local.key -out certs/app.local.csr -subj "/CN=app.local"
cat > certs/app.local.ext <<'EOF'
subjectAltName = @alt_names
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = app.local
DNS.2 = localhost
IP.1 = 127.0.0.1
EOF
openssl x509 -req -in certs/app.local.csr -CA certs/rootCA.crt -CAkey certs/rootCA.key -CAcreateserial -out certs/app.local.crt -days 825 -sha256 -extfile certs/app.local.ext
Option B : mkcert (CA locale pratique)
mkcert -install
mkcert -cert-file certs/app.local.crt -key-file certs/app.local.key app.local 127.0.0.1 localhost
mkcert crée aussi sa CA racine (l'emplacement varie selon l'OS) et l'ajoute au magasin de confiance du système.
Créez un serveur Nginx minimal qui termine le TLS et sert une réponse simple. Adaptez les chemins selon vos besoins.
- Configurez Nginx avec TLS
nginx.conf (ou un fichier de site que vous incluez) :
server {
listen 443 ssl http2;
server_name app.local;
ssl_certificate /chemin/absolu/certs/app.local.crt;
ssl_certificate_key /chemin/absolu/certs/app.local.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;
# HSTS pour le lab : sûr si vous n'utilisez app.local qu'en local
add_header Strict-Transport-Security "max-age=31536000" always;
location / {
return 200 'hello tls lab\n';
add_header Content-Type text/plain;
}
}
server {
listen 80;
server_name app.local;
return 301 https://$host$request_uri;
}
Rechargez Nginx après avoir testé la configuration :
nginx -t && nginx -s reload
# ou avec systemd
# sudo systemctl reload nginx
Vous pouvez faire confiance à votre CA racine au niveau système (optionnel) ou indiquer explicitement les outils vers celle-ci.
- Validez avec curl et OpenSSL
Confiance système (optionnel ; nécessite des privilèges d'administration) :
- macOS :
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain certs/rootCA.crt
- Debian/Ubuntu :
sudo cp certs/rootCA.crt /usr/local/share/ca-certificates/lab-root-ca.crt
sudo update-ca-certificates
- Windows (exécuter en tant qu'administrateur dans cmd ou PowerShell) :
certutil -addstore -f "Root" certs\rootCA.crt
Validation directe sans confiance système :
# Utilisez le fichier hosts et la CA explicitement
curl -vkI https://app.local --cacert certs/rootCA.crt
# Inspectez le certificat servi
openssl s_client -connect app.local:443 -servername app.local -showcerts < /dev/null | openssl x509 -noout -subject -issuer -dates
Optionnel : activer le TLS mutuel (certificats clients)
Créez un certificat client signé par la même CA :
openssl genrsa -out certs/client.key 2048
openssl req -new -key certs/client.key -out certs/client.csr -subj "/CN=lab-client"
cat > certs/client.ext <<'EOF'
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
EOF
openssl x509 -req -in certs/client.csr -CA certs/rootCA.crt -CAkey certs/rootCA.key -CAcreateserial -out certs/client.crt -days 365 -sha256 -extfile certs/client.ext
Extrait Nginx pour mTLS :
ssl_client_certificate /chemin/absolu/certs/rootCA.crt;
ssl_verify_client optional; # ou 'on' pour exiger tous les requêtes
location /secure/ {
if ($ssl_client_verify != SUCCESS) { return 403; }
return 200 'hello mtls client\n';
add_header Content-Type text/plain;
}
Testez le mTLS :
# Sans certificat client : attendez 403 pour /secure/
curl -vk https://app.local/secure/ --cacert certs/rootCA.crt
# Avec certificat client : attendez 200
curl -vk https://app.local/secure/ --cacert certs/rootCA.crt --cert certs/client.crt --key certs/client.key
Étendre à un Ingress Kubernetes (optionnel)
Si vous exécutez déjà un cluster local (kind, minikube, etc.) avec un contrôleur Ingress, réutilisez le même certificat et la même clé.
Créez un secret TLS :
kubectl create namespace demo
kubectl -n demo create secret tls app-local-tls --cert=certs/app.local.crt --key=certs/app.local.key
Manifeste Ingress (exemple nginx Ingress) :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-local
namespace: demo
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- app.local
secretName: app-local-tls
rules:
- host: app.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-svc
port:
number: 80
Pointez app.local vers le point de terminaison de l'Ingress (NodePort, LoadBalancer, ou port-forward). Exemple avec port-forwarding du contrôleur vers localhost :
# Adaptez les noms à votre service de contrôleur
kubectl -n ingress-nginx port-forward svc/ingress-nginx-controller 8443:443
# Puis :
curl -vkI https://app.local:8443 --resolve app.local:8443:127.0.0.1 --cacert certs/rootCA.crt
Faire tourner les certificats en toute sécurité
- Émettez un nouveau certificat serveur avec les mêmes SAN
- Mettez à jour les chemins de fichiers de façon atomique (ou écrasez les fichiers)
- Validez la configuration Nginx et rechargez
openssl x509 -in certs/app.local.crt -noout -enddate
nginx -t && nginx -s reload
Dépannage : gains rapides
- Incompatibilité de nom d'hôte : vérifiez les SAN avec
openssl x509 -in certs/app.local.crt -noout -text | grep -A1 "Subject Alternative Name" - Chaîne incorrecte : confirmez l'émetteur avec
-issueret assurez-vous que le serveur envoie le bon certificat - Protocole/chiffrement :
curl -v --tls-max 1.2 https://app.localpour forcer la vérification des versions - Journaux Nginx : consultez le journal d'erreurs pour les erreurs de handshake ou de certificat
Plan pilote local
Objectif : un nom d'hôte (app.local) en TLS sur localhost avec des vérifications mesurables.
Périmètre
- Serveur unique : Nginx sur
127.0.0.1 - Un nom d'hôte :
app.local - Une CA, un certificat serveur
Étapes
- Ajoutez une entrée hosts pour
app.local->127.0.0.1 - Créez une CA locale et un certificat serveur (commandes OpenSSL ci-dessus)
- Configurez Nginx avec TLS
- Validez avec curl et OpenSSL
Critères de succès (mesurables)
curl -skI https://app.local --cacert certs/rootCA.crtretourne HTTP/1.1 ou HTTP/2 200 OK pour le vhost TLSopenssl s_client -connect app.local:443 -servername app.localmontre une chaîne avec l'émetteur =lab-root-caet une date Not After valide dans le futurnginx -tréussit etnginx -s reloadse termine sans erreurs
Timebox
- 45 à 60 minutes de bout en bout, validation incluse
Étirement optionnel
- Ajoutez le mTLS pour
/secure/et vérifiez 403 sans certificat client et 200 avec
Prochaine extension après succès
- Ajoutez
api.localcomme second nom d'hôte en utilisant la même CA et répétez les vérifications
Conclusion
Vous avez construit un petit laboratoire TLS sûr que vous pouvez réutiliser pour les tests, le dépannage et les expériences. Vous avez créé une CA locale, émis des certificats serveur et client, configuré Nginx avec des valeurs par défaut sécurisées, et validé le comportement avec curl et OpenSSL. Procédez par améliorations incrémentales : scriptez l'émission et la rotation des certificats, ajoutez d'autres noms d'hôte, et réutilisez éventuellement les mêmes artefacts dans un Ingress Kubernetes. Définissez toujours des vérifications locales claires pour pouvoir valider chaque changement avant de passer à la suite.