Guide Pratique : Automatiser vos Certificats SSL/TLS avec cert-manager sur Kubernetes

Dans une architecture Kubernetes, la gestion manuelle des Secret tls est une source majeure de failles de sécurité et de pannes. cert-manager s’impose comme l’opérateur de référence pour automatiser l’émission, la validation et le renouvellement des certificats (via Let’s Encrypt, HashiCorp Vault ou une PKI interne d’entreprise).

1. Les CRD Clés de cert-manager

Avant le déploiement, il est essentiel de comprendre la dynamique entre les ressources personnalisées (CRDs) introduites par cert-manager :

  • Issuer / ClusterIssuer : Définit l’autorité de certification (CA) qui signera les certificats. L’Issuer fonctionne au niveau d’un seul namespace, tandis que le ClusterIssuer est disponible à l’échelle de tout le cluster (idéal pour les environnements de production multi-tenant).
  • Certificate : Une ressource déclarative décrivant le certificat souhaité (noms de domaine, durée de validité, algorithme de clé, secret cible).
  • Secret : Le secret Kubernetes natif généré automatiquement par cert-manager pour stocker la clé privée et le certificat au format tls.crt / tls.key.

2. Étape 1 : Installation de cert-manager via Helm

L’installation recommandée se fait via Helm 3. Elle inclut l’injection automatique des CRDs.

Bash

# 1. Ajouter le dépôt Helm de Jetstack
helm repo add jetstack https://charts.jetstack.io
helm repo update

# 2. Installer cert-manager dans un namespace dédié avec les CRDs
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

# 3. Vérifier que les pods sont prêts (Status: Running)
kubectl get pods --namespace cert-manager

3. Étape 2 : Configuration du ClusterIssuer

Voici deux cas d’usage industriels : le challenge ACME HTTP-01 (exposé à Internet) et l’intégration avec une PKI interne d’entreprise (Vault).

Cas A : ACME Let’s Encrypt (Production – HTTP-01)

Ce manifeste configure un émetteur global utilisant l’environnement de production de Let’s Encrypt.

YAML

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # Adresse email pour les notifications d'expiration d'urgence
    email: secops@aminejafjaf.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Secret Kubernetes qui stockera la clé privée du compte ACME
      name: letsencrypt-prod-account-key
    solvers:
    - http01:
        ingress:
          class: nginx

Cas B : PKI d’Entreprise / HashiCorp Vault (Environnement Bancaire / Réseau Privé)

Pour les infrastructures privées ou sans accès direct à l’Internet public, cert-manager s’interface nativement avec Vault.

YAML

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: vault-internal-issuer
spec:
  vault:
    server: "https://vault.internal.net:8200"
    path: "pki_internal/sign/banking-role"
    auth:
      tokenSecretRef:
        name: vault-token
        key: token

Appliquez votre configuration :

Bash

kubectl apply -f cluster-issuer.yaml

4. Étape 3 : Automatisation des certificats pour les applications

Il existe deux méthodes pour demander et attacher un certificat : automatique via l’Ingress Controller ou déclarative via le manifeste Certificate.

Méthode 1 : Automatisation directe via l’Ingress (Recommandée pour le Web)

Il suffit d’ajouter une annotation sur votre Ingress natif. cert-manager interceptera la ressource et créera automatiquement le certificat.

YAML

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-banking-ingress
  namespace: production
  annotations:
    # Déclenche cert-manager et spécifie le ClusterIssuer à utiliser
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    # Optionnel: force le rechargement sans coupure Nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - api.aminejafjaf.com
    secretName: api-banking-tls-secret # Le secret sera créé par cert-manager
  rules:
  - host: api.aminejafjaf.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: banking-core-service
            port:
              number: 8080

Méthode 2 : Déclaration explicite avec le CRD Certificate

Utile pour sécuriser du trafic inter-services (mTLS) ou exporter un certificat pour un Load Balancer externe.

YAML

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: internal-secops-cert
  namespace: production
spec:
  secretName: internal-secops-tls
  duration: 2160h # 90 jours
  renewBefore: 360h # Renouvellement automatique 15 jours avant expiration
  subject:
    organizations:
      - Amine Jafjaf SecOps
  isCA: false
  privateKey:
    algorithm: RSA
    encoding: PKCS1
    size: 4096
  dnsNames:
    - secops.internal.local
    - *.secops.internal.local
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer

5. Inspection et Diagnostic (Troubleshooting)

En tant qu’ingénieur SecOps, la validation de la chaîne d’émission et l’audit des événements sont cruciaux.

Bash

# 1. Lister les certificats et vérifier l'état READY (True)
kubectl get certificate -n production

# 2. Inspecter les étapes d'émission d'un certificat
kubectl describe certificate api-banking-tls-secret -n production

# 3. Inspecter les requêtes de certificat sous-jacentes (CertificateRequest)
kubectl get certificaterequest -n production

# 4. Examiner les challenges ACME en cours (en cas de blocage HTTP-01/DNS-01)
kubectl get challenges -n production

6. Bonnes Pratiques SecOps pour la Production

  1. Privilégier le Challenge DNS-01 pour la sécurité maximale : Le challenge HTTP-01 nécessite d’ouvrir le port 80 sur l’extérieur. Dans des environnements bancaires stricts, préférez le challenge DNS-01 (via Cloudflare, Route53 ou Infoblox) pour émettre des certificats Wildcard (*.domaine.com) sans exposer vos pods au web public.
  2. Rotation des clés privées : Activez la rotation automatique des clés privées à chaque renouvellement dans cert-manager en ajoutant rotationPolicy: Always dans la spécification de votre Certificate.
  3. Supervision Prometheus / Grafana : Exposez les métriques natives de cert-manager pour surveiller la métrique certmanager_certificate_expiration_timestamp_seconds et créer des alertes Slack/PagerDuty en cas d’échec de renouvellement à J-7.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Retour en haut