## 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 curl et openssl

- 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 -issuer et assurez-vous que le serveur envoie le bon certificat

- Protocole/chiffrement : curl -v --tls-max 1.2 https://app.local pour 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.crt retourne HTTP/1.1 ou HTTP/2 200 OK pour le vhost TLS

- openssl s_client -connect app.local:443 -servername app.local montre une chaîne avec l'émetteur = lab-root-ca et une date Not After valide dans le futur

- nginx -t réussit et nginx -s reload se 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.local comme 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.