8.8 KiB
PKI Interne pour les Sites Internes
Vue d'ensemble
Cette architecture implémente une PKI (Public Key Infrastructure) privée pour gérer les certificats TLS des sites internes (domaines .local), tout en conservant Let's Encrypt pour les sites publics (domaines .fr).
Architecture
Stratégie hybride
-
Sites publics (
.fr) → Let's Encrypt (letsencrypt-prod)- Nécessite un accès Internet
- Validation via HTTP-01 challenge
- Certificats reconnus par tous les navigateurs
-
Sites internes (
.local) → PKI Interne (ca-issuer)- Pas besoin d'accès Internet
- Contrôle total sur les certificats
- Certificats signés par votre propre CA root
Composants
1. CA Root (ca-root-issuer)
Génère la Certificate Authority root de votre PKI interne.
ClusterIssuer: ca-root-issuer
Certificate: ca-root-certificate
Secret: ca-root-secret
Durée de vie : 10 ans (configurable)
2. CA Issuer (ca-issuer)
Utilise la CA root pour signer les certificats des applications internes.
ClusterIssuer: ca-issuer
3. Distribution du certificat CA root
Le certificat CA root doit être distribué aux clients (navigateurs, applications) pour qu'ils fassent confiance aux certificats signés.
ConfigMap : ca-root-certificate dans le namespace certificates-ops
Avantages de la PKI Interne
✅ Pas d'accès Internet requis - Les clusters DEV/RCT/PRD peuvent générer des certificats sans Internet
✅ Contrôle total - Vous gérez la durée de vie, les politiques, etc.
✅ Pas de limites de taux - Pas de restrictions comme Let's Encrypt (50 certificats/semaine)
✅ Domaines internes - Support natif pour .local, .internal, etc.
✅ Sécurité renforcée - Certificats uniquement pour votre infrastructure interne
✅ Renouvellement automatique - cert-manager gère le renouvellement automatiquement
Utilisation
Pour un site interne (.local)
Créez un Certificate qui utilise ca-issuer :
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: harbor-tls
namespace: certificates-ops
annotations:
# IMPORTANT: Ce certificat doit être créé après que ca-issuer soit prêt
# ca-issuer a sync-wave "1", donc ce certificat doit avoir sync-wave "2" ou plus
argocd.argoproj.io/sync-wave: "2"
spec:
secretName: harbor-tls
issuerRef:
name: ca-issuer
kind: ClusterIssuer
dnsNames:
- harbor.gkdomaine.local
- harbor.dev.gkdomaine.local
⚠️ Important : N'oubliez pas l'annotation argocd.argoproj.io/sync-wave: "2" pour que le certificat soit créé après l'initialisation de la PKI.
Pour un site public (.fr)
Utilisez letsencrypt-prod comme avant :
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: homarr-dev-tls
namespace: certificates-ops
spec:
secretName: homarr-dev-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- homarr.dev.gkdomaine.fr
Installation
Étape 1 : Déployer la CA root
Les ressources sont déployées automatiquement via ArgoCD :
# Vérifier que la CA root est créée
kubectl get certificate ca-root-certificate -n certificates-ops --context=cluster-ops
# Vérifier le ClusterIssuer CA
kubectl get clusterissuer ca-issuer --context=cluster-ops
Étape 2 : Extraire le certificat CA root
# Extraire le certificat CA root
kubectl get secret ca-root-secret -n certificates-ops \
--context=cluster-ops \
-o jsonpath='{.data.tls\.crt}' | base64 -d > ca-root.crt
# Vérifier le certificat
openssl x509 -in ca-root.crt -text -noout
Étape 3 : Distribuer le certificat CA root
Option A : Ajouter au ConfigMap (pour distribution dans Kubernetes)
# Mettre à jour le ConfigMap avec le certificat CA
kubectl create configmap ca-root-certificate \
--from-file=ca.crt=ca-root.crt \
-n certificates-ops \
--context=cluster-ops \
--dry-run=client -o yaml | kubectl apply -f -
Option B : Installer sur les machines clientes
Windows :
# Importer dans le magasin de certificats Windows
Import-Certificate -FilePath ca-root.crt -CertStoreLocation Cert:\LocalMachine\Root
Linux :
# Copier dans le magasin de certificats système
sudo cp ca-root.crt /usr/local/share/ca-certificates/gkdomaine-ca-root.crt
sudo update-ca-certificates
macOS :
# Importer dans le trousseau système
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca-root.crt
Option C : Configurer dans les navigateurs
- Chrome/Edge : Paramètres → Confidentialité et sécurité → Gérer les certificats → Autorités de certification → Importer
- Firefox : Paramètres → Confidentialité et sécurité → Certificats → Afficher les certificats → Autorités → Importer
Étape 4 : Synchroniser le ConfigMap vers les autres clusters
Le ConfigMap ca-root-certificate peut être synchronisé vers les clusters DEV/RCT/PRD pour que les pods puissent faire confiance aux certificats :
# Synchroniser vers cluster-dev
kubectl get configmap ca-root-certificate -n certificates-ops \
--context=cluster-ops -o yaml | \
kubectl apply --context=cluster-dev -f -
Vérification
Vérifier la CA root
# Vérifier le certificat CA root
kubectl get certificate ca-root-certificate -n certificates-ops --context=cluster-ops
# Vérifier le secret CA root
kubectl get secret ca-root-secret -n certificates-ops --context=cluster-ops
# Voir les détails du certificat
kubectl get secret ca-root-secret -n certificates-ops \
--context=cluster-ops \
-o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
Vérifier un certificat signé par la CA
# Vérifier un certificat d'application
kubectl get certificate harbor-tls -n certificates-ops --context=cluster-ops
# Vérifier la chaîne de certificats
kubectl get secret harbor-tls -n certificates-ops \
--context=cluster-ops \
-o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
# Vérifier que le certificat est signé par la CA root
kubectl get secret harbor-tls -n certificates-ops \
--context=cluster-ops \
-o jsonpath='{.data.tls\.crt}' | base64 -d | \
openssl verify -CAfile <(kubectl get secret ca-root-secret -n certificates-ops \
--context=cluster-ops -o jsonpath='{.data.tls\.crt}' | base64 -d)
Migration des certificats existants
Pour migrer un certificat de Let's Encrypt vers la PKI interne :
- Modifier le Certificate pour utiliser
ca-issuerau lieu deletsencrypt-prod - Supprimer l'ancien secret pour forcer la régénération
- Vérifier que le nouveau certificat est généré et signé par la CA root
Exemple pour Harbor :
# 1. Modifier le Certificate (dans Git)
# issuerRef.name: ca-issuer
# 2. Supprimer l'ancien secret
kubectl delete secret harbor-tls -n certificates-ops --context=cluster-ops
# 3. Vérifier la régénération
kubectl get certificate harbor-tls -n certificates-ops --context=cluster-ops -w
Sécurité
Bonnes pratiques
- 🔒 Protéger la clé privée CA root - Stockée dans
ca-root-secret, ne jamais exposer - 🔄 Rotation périodique - Planifier la rotation de la CA root avant expiration (tous les 10 ans)
- 📋 Audit régulier - Vérifier régulièrement les certificats émis
- 🚫 Isolation - Ne jamais utiliser la CA interne pour des sites publics
- 🔐 Backup - Sauvegarder régulièrement le secret
ca-root-secret
Rotation de la CA root
Quand la CA root approche de son expiration :
- Créer une nouvelle CA root (
ca-root-certificate-v2) - Créer un nouveau ClusterIssuer (
ca-issuer-v2) - Migrer progressivement les certificats vers la nouvelle CA
- Mettre à jour les clients avec le nouveau certificat CA root
Troubleshooting
Le certificat n'est pas généré
# Vérifier les logs de cert-manager
kubectl logs -n cert-manager-ops -l app.kubernetes.io/name=cert-manager --context=cluster-ops --tail=100
# Vérifier le Certificate
kubectl describe certificate <nom-certificat> -n certificates-ops --context=cluster-ops
Le navigateur affiche "Certificat non fiable"
- Vérifier que le certificat CA root est installé sur la machine cliente
- Vérifier que le certificat est bien signé par la CA root
- Vérifier la date de validité du certificat
Erreur "certificate signed by unknown authority"
- Le certificat CA root n'est pas installé sur le client
- Vérifier que le ConfigMap
ca-root-certificateest synchronisé vers le cluster cible