# Configuration Let's Encrypt avec cert-manager Ce document explique comment générer et utiliser des certificats Let's Encrypt avec cert-manager dans votre cluster Kubernetes. ## Architecture - **cert-manager** : Opérateur Kubernetes qui gère automatiquement les certificats TLS - **ClusterIssuer** : Ressource qui définit comment obtenir des certificats (Let's Encrypt Production ou Staging) - **Certificate** : Ressource Kubernetes qui demande un certificat pour un domaine spécifique - **Traefik** : Ingress Controller qui utilise les certificats générés ## Installation ### 1. Déployer cert-manager cert-manager est déployé via ArgoCD via l'ApplicationSet `cert-manager-apps`. Le chart inclut : - cert-manager (controller, webhook, cainjector) - ClusterIssuer pour Let's Encrypt Production (`letsencrypt-prod`) - ClusterIssuer pour Let's Encrypt Staging (`letsencrypt-staging`) ### 2. Vérifier l'installation ```bash # Vérifier que cert-manager est déployé kubectl get pods -n cert-manager # Vérifier les ClusterIssuers kubectl get clusterissuers # Vérifier le statut d'un ClusterIssuer kubectl describe clusterissuer letsencrypt-prod ``` ## Configuration ### ClusterIssuers Deux ClusterIssuers sont créés : 1. **letsencrypt-prod** : Pour les certificats de production - Serveur : `https://acme-v02.api.letsencrypt.org/directory` - Limite de taux : 50 certificats par semaine par domaine 2. **letsencrypt-staging** : Pour les tests - Serveur : `https://acme-staging-v02.api.letsencrypt.org/directory` - Limite de taux : 300 certificats par semaine par domaine - ⚠️ Les certificats staging ne sont pas fiables par les navigateurs ### Modifier l'email L'email utilisé pour l'enregistrement ACME est défini dans : - `helm/cert-manager/dev/templates/cluster-issuer-letsencrypt-prod.yaml` - `helm/cert-manager/dev/templates/cluster-issuer-letsencrypt-staging.yaml` Modifiez la ligne `email: admin@gkdomaine.fr` avec votre email. ## Utilisation ### Méthode 1 : Via annotations Ingress (Recommandé) Ajoutez les annotations suivantes à votre Ingress : ```yaml ingress: enabled: true className: traefik hosts: - host: monapp.dev.gkdomaine.fr paths: - path: / tls: - secretName: monapp-dev-tls hosts: - monapp.dev.gkdomaine.fr annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" # ou "letsencrypt-staging" pour les tests ``` ### Méthode 2 : Via ressource Certificate (Pour plus de contrôle) Créez une ressource Certificate : ```yaml apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: monapp-dev-tls namespace: monapp-dev spec: secretName: monapp-dev-tls issuerRef: name: letsencrypt-prod kind: ClusterIssuer dnsNames: - monapp.dev.gkdomaine.fr ``` Puis référencez le secret dans votre Ingress : ```yaml ingress: tls: - secretName: monapp-dev-tls hosts: - monapp.dev.gkdomaine.fr ``` ## Validation HTTP-01 cert-manager utilise la méthode HTTP-01 pour valider la propriété du domaine : 1. cert-manager crée un challenge HTTP 2. Traefik expose le challenge sur `/.well-known/acme-challenge/` 3. Let's Encrypt vérifie que le challenge est accessible 4. Le certificat est émis et stocké dans un Secret Kubernetes ### Prérequis - Le domaine doit pointer vers l'IP publique de Traefik (LoadBalancer) - Le port 80 doit être accessible depuis Internet - Traefik doit être configuré pour gérer les ingress avec la classe `traefik` ## Vérification ### Vérifier le statut d'un certificat ```bash # Lister les certificats kubectl get certificates --all-namespaces # Détails d'un certificat kubectl describe certificate monapp-dev-tls -n monapp-dev # Vérifier les challenges ACME kubectl get challenges --all-namespaces ``` ### Vérifier le secret TLS ```bash # Le secret est créé automatiquement quand le certificat est émis kubectl get secret monapp-dev-tls -n monapp-dev # Voir les détails du certificat kubectl get secret monapp-dev-tls -n monapp-dev -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout ``` ## Renouvellement automatique cert-manager renouvelle automatiquement les certificats avant expiration (30 jours avant la date d'expiration). Les certificats Let's Encrypt sont valides pendant 90 jours. ## Dépannage ### Le certificat n'est pas émis 1. Vérifier les logs de cert-manager : ```bash kubectl logs -n cert-manager deployment/cert-manager ``` 2. Vérifier les challenges : ```bash kubectl describe challenge -n monapp-dev ``` 3. Vérifier que le domaine est accessible : ```bash curl http://monapp.dev.gkdomaine.fr/.well-known/acme-challenge/test ``` ### Erreur "rate limit exceeded" Let's Encrypt a des limites de taux : - Production : 50 certificats par semaine par domaine - Staging : 300 certificats par semaine par domaine Solution : Utilisez `letsencrypt-staging` pour les tests, ou attendez la fin de la période de limitation. ### Le certificat n'est pas utilisé par Traefik Vérifiez que : 1. Le secret TLS existe dans le même namespace que l'Ingress 2. L'Ingress référence correctement le secret dans `spec.tls[].secretName` 3. Traefik peut accéder au secret (même namespace ou RBAC approprié) ## Exemples de configuration ### Homarr Voir `helm/homarr/dev/values.yaml` pour un exemple complet avec annotations cert-manager. ### Traefik Dashboard Pour sécuriser le dashboard Traefik, ajoutez TLS à l'IngressRoute : ```yaml apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard namespace: traefik-dev annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: entryPoints: - websecure routes: - match: Host(`traefik.dev.gkdomaine.fr`) kind: Rule services: - name: api@internal kind: TraefikService tls: secretName: traefik-dashboard-tls ``` ## Références - [cert-manager Documentation](https://cert-manager.io/docs/) - [Let's Encrypt Documentation](https://letsencrypt.org/docs/) - [Traefik ACME Documentation](https://doc.traefik.io/traefik/https/acme/)