Introduction
L'automatisation de l'approbation des demandes de signature de certificats (Certificate Signing Request, CSR) Kubernetes dans les pipelines CI/CD est un besoin courant pour les équipes qui gèrent leurs propres certificats TLS ou s'intègrent à une infrastructure à clés publiques (PKI) externe. Sans flux de travail contrôlé, les opérateurs approuvent les CSR manuellement (lent et sujet aux erreurs) ou les laissent en attente indéfiniment, ce qui interrompt les déploiements d'applications.
Cet article fournit des conseils pratiques aux développeurs, consultants DevOps et équipes techniques de startups qui souhaitent automatiser l'approbation des CSR en toute sécurité. Il couvre le cycle de vie d'une CSR dans Kubernetes, la configuration du contrôle d'accès basé sur les rôles (RBAC) pour l'automatisation, la construction d'une étape CI/CD qui approuve les CSR, la vérification du certificat émis, et la gestion des échecs et retours en arrière.
Tout au long, nous insistons sur la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, protéger les valeurs sensibles, vérifier les résultats et documenter les chemins de récupération.
Inventaire des versions et de l'environnement
Avant d'automatiser l'approbation des CSR, établissez la version exacte de Kubernetes et les détails de l'environnement. Le comportement des ressources CertificateSigningRequest a changé au fil des versions, notamment concernant les noms de signataires et les autorisations d'approbation.
Prérequis essentiels :
- Un cluster Kubernetes (v1.19 ou ultérieure recommandée ; l'approbation spécifique au signataire a été introduite plus tôt mais a mûri plus tard)
- kubectl configuré avec les autorisations appropriées pour inspecter les CSR
- Si vous utilisez un signataire personnalisé, assurez-vous qu'il est installé et configuré (par exemple, cert-manager, le signataire intégré du kube-controller-manager ou une autorité de certification externe)
- Un compte de service pour l'automatisation CI/CD avec un RBAC minimal
Commencez par une observation en lecture seule :
kubectl version --short
kubectl get csr
La sortie attendue inclut la version du cluster et une liste des CSR avec leurs conditions. Par exemple :
NAME AGE SIGNERNAME REQUESTOR CONDITION
my-app-csr 2m kubernetes.io/kube-apiserver-client system:serviceaccount:default:my-app Pending
Notez le signerName. Les clusters modernes utilisent des noms de signataires comme kubernetes.io/kube-apiserver-client, kubernetes.io/kubelet-serving ou des noms personnalisés. L'automatisation doit faire correspondre le signataire à l'usage prévu ; approuver une CSR pour le mauvais signataire peut délivrer un certificat avec des autorisations non intentionnelles.
Vérifiez la santé des composants :
kubectl get pods -n kube-system | grep -E 'kube-controller-manager|kube-apiserver'
Si le gestionnaire de contrôleurs qui exécute l'approbateur CSR est défaillant, l'automatisation peut sembler s'exécuter mais ne pas aboutir.
Pour les tests locaux, utilisez un cluster à nœud unique (kind, minikube) et appliquez un manifeste CSR à la fois. Vérifiez avec :
kubectl get csr my-csr -o yaml
Avant de passer en production, confirmez que l'API des certificats du cluster est activée (elle l'est par défaut) et que le serveur d'API a --cluster-signing-cert-file et --cluster-signing-key-file définis si vous utilisez le signataire intégré.
Chemin de configuration sûr
L'automatisation de l'approbation des CSR nécessite une configuration RBAC soignée. Le principe du moindre privilège est essentiel : un compte de service CI/CD doit pouvoir approuver uniquement les CSR avec des noms de signataires spécifiques et, idéalement, seulement pour son espace de noms ou un motif de nommage connu.
Étape 1 : Créer un ServiceAccount dédié
apiVersion: v1
kind: ServiceAccount
metadata:
name: csr-approver
namespace: ci-cd
Appliquez-le :
kubectl apply -f sa.yaml
Étape 2 : Définir un ClusterRole avec des autorisations d'approbation limitées
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/approval"]
verbs: ["update"]
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests"]
verbs: ["get", "list", "watch"]
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/status"]
verbs: ["patch", "update"]
Cela permet de visualiser les CSR et de mettre à jour la sous-ressource d'approbation, ce qui est distinct de la modification de la CSR elle-même.
Étape 3 : Lier le ClusterRole au ServiceAccount avec une restriction resourceName si possible
Si vous pouvez prévoir les noms de CSR (par exemple, générés à partir d'un nom de déploiement), utilisez resourceNames pour restreindre l'approbation à des CSR spécifiques :
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csr-approver-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csr-approver
subjects:
- kind: ServiceAccount
name: csr-approver
namespace: ci-cd
Sans resourceNames, le compte peut approuver n'importe quelle CSR avec les verbes autorisés, ce qui est large mais parfois nécessaire si les noms sont dynamiques. Une alternative consiste à utiliser un webhook de validation pour appliquer des motifs de nommage.
Appliquez et vérifiez :
kubectl apply -f rbac.yaml
kubectl auth can-i approve certificatesigningrequests --as=system:serviceaccount:ci-cd:csr-approver
Sortie attendue : yes si les autorisations sont correctes.
Testez le plus petit changement : créez une CSR de test, puis approuvez-la avec les identifiants du compte de service. Utilisez kubectl --as pour usurper l'identité sans créer de fichier kubeconfig :
kubectl create csr test-csr --signer kubernetes.io/kube-apiserver-client --requestor test
kubectl certificate approve test-csr --as=system:serviceaccount:ci-cd:csr-approver
Si l'approbation réussit, la configuration est valide.
Gardez les données sensibles hors de la CI/CD : utilisez des jetons à courte durée de vie ou une identité de charge de travail au lieu de fichiers kubeconfig statiques avec des identifiants à longue durée.
Vérification et diagnostic
Après avoir implémenté l'automatisation, vérifiez que les CSR sont approuvées correctement et que les certificats sont émis.
Inspecter une CSR avant approbation
kubectl get csr my-csr -o yaml
Exemple de sortie condensée :
spec:
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
request: LS0tLS1CRUdJTiBDRV...
status:
conditions: []
Vérifiez que les usages et le signerName correspondent aux attentes. Une CSR d'authentification client ne doit pas être approuvée pour l'authentification serveur.
Approuver via kubectl
kubectl certificate approve my-csr
Sortie attendue :
certificatesigningrequest.certificates.k8s.io/my-csr approved
Vérifier le statut
kubectl get csr my-csr
Si approuvée et signée, la CSR affichera Approved,Issued sous CONDITIONS.
Récupérer le certificat émis
kubectl get csr my-csr -o jsonpath='{.status.certificate}' | base64 -d > client.crt
Vérifiez les détails du certificat :
openssl x509 -in client.crt -text -noout
Recherchez Subject, Issuer, Validity et X509v3 Extended Key Usage pour confirmer que le certificat correspond à la demande.
Diagnostiquer les CSR bloquées
Si une CSR reste Pending, vérifiez les événements :
kubectl describe csr my-csr
Causes courantes :
- Aucun approbateur avec la permission d'approuver ce signataire
- L'approbateur ne fonctionne pas (si vous utilisez un contrôleur personnalisé)
- Mauvaise configuration du certificat/clé du signataire
Pour les pipelines CI/CD, enregistrez le nom et le statut de la CSR après la tentative d'approbation :
STATUS=$(kubectl get csr my-csr -o jsonpath='{.status.conditions[?(@.type=="Approved")].status}')
if [ "$STATUS" != "True" ]; then
echo "CSR non approuvée : $STATUS"
exit 1
fi
Cela empêche la poursuite du pipeline avec un certificat non signé.
Modes de défaillance et récupération
L'approbation automatisée des CSR peut échouer de plusieurs manières. Comprendre chaque cas aide à concevoir la récupération.
Défaillance 1 : La CSR est approuvée mais le certificat n'est pas émis
Symptôme : La CSR affiche Approved mais pas Issued.
Cause : Le contrôleur de signature (le signataire CSR du kube-controller-manager) ne fonctionne pas ou sa clé de signature est manquante.
Diagnostic :
kubectl get pods -n kube-system | grep kube-controller-manager
kubectl logs -n kube-system kube-controller-manager-<node> | grep -i csr
Récupération : Assurez-vous que le gestionnaire de contrôleurs a --cluster-signing-cert-file et --cluster-signing-key-file configurés et que les fichiers existent. Redémarrez le contrôleur si nécessaire.
Défaillance 2 : L'approbateur automatisé ne peut pas approuver la CSR en raison du RBAC
Symptôme : Les journaux du pipeline montrent error: You must be logged in to the server (Unauthorized) ou forbidden.
Cause : Règles RBAC manquantes ou jeton du compte de service expiré.
Diagnostic :
kubectl auth can-i approve certificatesigningrequests --as=system:serviceaccount:ci-cd:csr-approver
Récupération : Examinez le ClusterRole et la liaison. Assurez-vous que le compte de service est dans le bon espace de noms.
Défaillance 3 : Mauvais signataire approuvé
Symptôme : Le certificat émis ne peut pas être utilisé pour son objectif prévu (par exemple, un certificat client utilisé comme certificat serveur).
Cause : L'automatisation a approuvé une CSR avec un nom de signataire qui ne correspond pas aux besoins de l'application.
Récupération : Refusez ou supprimez la CSR et générez-en une nouvelle avec le bon signataire :
kubectl delete csr bad-csr
Prévention : validez les noms de signataires dans le script d'automatisation avant l'approbation.
Défaillance 4 : Le pipeline approuve les CSR de manière trop large
Symptôme : Des CSR non autorisées sont approuvées automatiquement, délivrant potentiellement des identifiants à des attaquants.
Cause : RBAC trop permissif (pas de resourceNames, pas de filtrage par signataire).
Récupération : Révoquez immédiatement la liaison, supprimez le jeton du compte de service et auditez quelles CSR ont été approuvées. Renforcez le RBAC avec des noms de signataires et des noms de ressources spécifiques.
Retour en arrière pour les changements de configuration : gardez tous les fichiers YAML dans le contrôle de version. Si un changement provoque des échecs, revenez au commit précédent et réappliquez.
Exemple de retour en arrière :
git revert <commit-hash>
kubectl apply -f rbac.yaml
Vérifiez toujours le nouvel état avec kubectl auth can-i et une CSR de test.
Liste de contrôle des opérations
Utilisez cette liste avant et après le déploiement de l'automatisation CSR en production.
Avant le déploiement :
- [ ] Version du cluster prise en charge (v1.19+ pour l'approbation spécifique au signataire)
- [ ] ServiceAccount créé dans un espace de noms dédié
- [ ] ClusterRole limité à
certificatesigningrequests/approvalet aux verbes de lecture nécessaires - [ ] ClusterRoleBinding lie le ServiceAccount au ClusterRole
- [ ] Si possible, les resourceNames restreignent l'approbation à des noms de CSR connus
- [ ] Test avec
kubectl auth can-ien tant que compte de service - [ ] Test avec une CSR d'exemple de bout en bout dans un environnement de staging
- [ ] Le script de pipeline enregistre le nom et le statut de la CSR
- [ ] Plan de retour en arrière documenté (revert du commit, réappliquer le RBAC)
Pendant l'exploitation :
- [ ] Surveiller les CSR approuvées de manière inattendue (journaux d'audit)
- [ ] Faire tourner périodiquement les jetons du compte de service (si jetons statiques) ou utiliser une identité de charge de travail
- [ ] Garder les certificats de signature valides et les renouveler avant expiration
- [ ] Examiner régulièrement les autorisations RBAC pour le moindre privilège
Après la récupération d'un échec :
- [ ] Identifier la cause racine et documenter
- [ ] Appliquer une action corrective à l'automatisation
- [ ] Relancer une CSR de test pour confirmer la correction
- [ ] Mettre à jour le manuel opérationnel
Attribuez un propriétaire : par exemple, le responsable de plateforme (par exemple, Priya Shah) possède la configuration de l'automatisation CSR et la révise mensuellement ou après tout changement d'infrastructure.
Pièges courants
Piège 1 : Approuver les CSR manuellement par habitude
Pourquoi cela arrive : L'automatisation n'est pas mise en place ou pas fiable, donc les équipes reviennent à l'approbation manuelle.
Comment éviter : Implémentez l'approbation CI/CD avec journalisation et alertes. Si l'approbation manuelle reste, restreignez-la aux comptes de secours.
Piège 2 : Utiliser cluster-admin pour le compte de service CI/CD
Pourquoi cela arrive : Configuration rapide et sale, ou manque de compréhension du RBAC.
Comment éviter : Utilisez le ClusterRole limité comme indiqué ci-dessus. Testez avec kubectl auth can-i --list pour voir toutes les autorisations.
Piège 3 : Ignorer les noms de signataires
Pourquoi cela arrive : Les anciens clusters utilisaient par défaut un seul signataire, donc les équipes supposent qu'il n'y a pas de distinction.
Comment éviter : Inspectez toujours spec.signerName et faites correspondre la logique d'approbation au signataire attendu.
Piège 4 : Ne pas vérifier le certificat émis
Pourquoi cela arrive : Le pipeline s'arrête après l'approbation, en supposant que l'émission a réussi.
Comment éviter : Vérifiez la condition Issued et décodez le certificat pour valider les usages et l'expiration.
Piège 5 : Stocker un kubeconfig à longue durée dans la CI/CD
Pourquoi cela arrive : Simplicité.
Comment éviter : Utilisez des jetons à courte durée, OIDC ou une identité de charge de travail cloud. Faites tourner les secrets automatiquement.
Conclusion
L'automatisation de l'approbation des CSR Kubernetes dans la CI/CD est réalisable avec un RBAC soigné, des étapes de vérification claires et une gestion robuste des échecs. La clé est de limiter étroitement les autorisations, de valider les noms de signataires et les usages, et de s'assurer que le contrôleur de signature est sain.
Commencez par une implémentation à faible risque : créez une CSR de test, approuvez-la via un compte de service restreint et vérifiez le certificat. Intégrez ensuite l'étape d'approbation dans votre pipeline avec une journalisation et une gestion des erreurs appropriées.
En suivant les pratiques de cet article, vous pouvez réduire la corvée manuelle, prévenir les certificats mal émis et maintenir un processus d'émission de certificats sûr et fiable dans vos clusters Kubernetes.