veylant/docs/runbooks/certificate-expired.md
2026-02-23 13:35:04 +01:00

5.4 KiB

Runbook — Certificat TLS Expiré ou Expirant

Alerte : VeylantCertExpiringSoon (severity: warning, J-30) ou certificat déjà expiré SLA impact : Interruption totale (HTTPS refusé) si certificat expiré Temps de résolution cible : < 20 minutes (renouvellement cert-manager automatique)


Symptômes

  • Alerte VeylantCertExpiringSoon : expiry < 30 jours
  • Erreurs navigateur : NET::ERR_CERT_DATE_INVALID
  • Erreurs curl : SSL certificate has expired ou certificate verify failed
  • k6 / smoke tests échouent avec des erreurs TLS
  • Logs Traefik : "certificate expired" ou "acme: error: 403"

Diagnostic

1. Vérifier l'expiration du certificat en production

# Expiration du certificat TLS externe
echo | openssl s_client -connect api.veylant.ai:443 2>/dev/null | \
  openssl x509 -noout -enddate -subject

# Via kubectl (cert-manager Certificate resource)
kubectl get certificate -n veylant
kubectl describe certificate veylant-tls -n veylant | grep -A5 "Conditions:"

2. Vérifier l'état cert-manager

# État des CertificateRequest en cours
kubectl get certificaterequest -n veylant

# Logs cert-manager
kubectl logs -n cert-manager deploy/cert-manager --since=30m | \
  grep -E "(error|certificate|acme|renewal)"

# Vérifier les ClusterIssuers
kubectl get clusterissuer
kubectl describe clusterissuer letsencrypt-production | grep -A10 "Status:"

3. Diagnostiquer l'échec ACME (Let's Encrypt)

# Vérifier les challenges ACME en cours (HTTP-01 ou DNS-01)
kubectl get challenge -n veylant
kubectl describe challenge -n veylant | grep -A10 "Reason:"

# Si HTTP-01 : vérifier que le chemin /.well-known/acme-challenge/ est accessible
curl -sf https://api.veylant.ai/.well-known/acme-challenge/test-token

Remédiation

A — Renouvellement automatique via cert-manager (normal)

Si le certificat expire dans > 7 jours, cert-manager se charge du renouvellement automatique (renewal 30 jours avant expiry). Aucune action requise — surveiller que le renouvellement s'effectue.

B — Forcer le renouvellement cert-manager

# Supprimer le certificat actuel pour forcer la re-création
kubectl delete certificate veylant-tls -n veylant

# cert-manager recrée automatiquement le certificat
kubectl get certificate -n veylant -w  # Observer la re-création

# Attendre Ready=True (1-2 minutes pour HTTP-01, 1-5 minutes pour DNS-01)
kubectl wait certificate veylant-tls -n veylant \
  --for=condition=Ready --timeout=300s

echo "Certificate renewed successfully"

C — Certificat déjà expiré (urgence)

C1. Renouvellement d'urgence

# Annotate le Certificate pour forcer la re-création immédiate
kubectl annotate certificate veylant-tls -n veylant \
  cert-manager.io/issue-temporary-certificate=true --overwrite

# Si ACME rate-limited (trop de renouvellements) → basculer sur staging Let's Encrypt
kubectl patch clusterissuer letsencrypt-production --type=merge -p \
  '{"spec":{"acme":{"server":"https://acme-staging-v02.api.letsencrypt.org/directory"}}}'

# ATTENTION: staging LE ne génère pas des certs de confiance — maintenance mode obligatoire

C2. Rollback TLS — certificat auto-signé temporaire

Uniquement si le renouvellement ACME échoue et que le service est totalement indisponible.

# Générer un certificat auto-signé valable 7 jours
openssl req -x509 -nodes -days 7 \
  -newkey rsa:2048 \
  -keyout /tmp/tls-emergency.key \
  -out /tmp/tls-emergency.crt \
  -subj "/CN=api.veylant.ai"

# Créer le secret TLS d'urgence
kubectl create secret tls veylant-tls-emergency \
  --cert=/tmp/tls-emergency.crt \
  --key=/tmp/tls-emergency.key \
  -n veylant

# Patcher le déploiement Traefik pour utiliser ce secret temporairement
# (voir documentation Traefik TLS configuration)
kubectl annotate ingress veylant-ingress \
  kubernetes.io/tls-acme=false \
  --overwrite

IMPORTANT : Le certificat auto-signé déclenchera des warnings navigateur. Notifier immédiatement les clients.


Rollback TLS

Si le nouveau certificat pose des problèmes :

# Restaurer l'ancien secret TLS depuis un backup
# (si cert-manager gérait un secret nommé veylant-tls, une copie est dans le backup S3)
aws s3 cp s3://veylant-backups-production/certs/veylant-tls-$(date +%Y%m%d).yaml - | \
  kubectl apply -n veylant -f -

kubectl rollout restart deployment/veylant-proxy-blue -n veylant

Prévention

  • Alerte VeylantCertExpiringSoon déclenchée 30 jours avant expiry (règle Prometheus)
  • cert-manager configuré pour renouveler 30 jours avant expiry (cert-manager default)
  • Rotation automatique — aucun renouvellement manuel nécessaire en fonctionnement normal
  • Vérification quotidienne du certificat dans le smoke test CI

Post-mortem Template

## Post-mortem — Certificat TLS [DATE]

**Certificat :** [domaine]
**Impact :** [durée d'indisponibilité TLS]
**Cause :** [Renouvellement raté / ACME challenge échoué / Rate limit LE]

### Timeline
- HH:MM — Alerte CertExpiringSoon / découverte expiration
- HH:MM — Diagnostic cert-manager
- HH:MM — Action : [forcer renouvellement / rollback]
- HH:MM — Certificat valide rétabli

### Root Cause
[Description]

### Actions correctives
- [ ] Vérifier la configuration ACME challenge
- [ ] Tester le renouvellement en staging mensuellement
- [ ] Ajouter monitoring expiry à J-60 (alerte précoce)