## Introduction Les comptes de service (Service Accounts) sont le mécanisme d'identité pour les charges de travail qui s'exécutent dans Kubernetes. Ils authentifient les pods auprès de l'API Kubernetes et des systèmes externes, et leur configuration affecte directement la posture de sécurité, l'auditabilité et la fiabilité opérationnelle. Pourtant, de nombreuses équipes traitent les comptes de service comme une tâche de configuration unique et ne les revoient que lors d'incidents. Cet article fournit une liste de contrôle des opérations de production pour les comptes de service Kubernetes, avec des exemples pratiques qui relient chaque étape à des commandes, des sorties attendues, des signaux de défaillance et des décisions de récupération. Il s'adresse aux développeurs, consultants DevOps et équipes techniques de startups qui gèrent des clusters Kubernetes en production et ont besoin d'un flux de travail reproductible et à faible risque. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier le résultat et documenter comment récupérer si l'état attendu n'est pas atteint. Chaque section suit la même structure : une observation en lecture seule, la plus petite modification justifiée et une commande de vérification. Tous les exemples sont limités à une version spécifique et évitent d'exposer des valeurs sensibles. ## Inventaire des versions et de l'environnement Avant de modifier une configuration de compte de service, documentez la version de Kubernetes installée, la topologie de déploiement et le composant exact inspecté. Cela évite d'exécuter des commandes sur le mauvais cluster ou une version d'API non prise en charge. Commencez par un inventaire en lecture seule. ```bash kubectl version kubectl get nodes -o wide kubectl get serviceaccounts --all-namespaces ``` La sortie attendue comprend les versions client et serveur, l'état et les rôles des nœuds, et la liste des comptes de service dans chaque espace de noms. Notez le groupe d'API pour les comptes de service : `v1` dans Kubernetes 1.24 et versions ultérieures, `v1beta1` dans les versions plus anciennes. Si vous utilisez `kubectl describe serviceaccount `, la sortie montre les secrets associés uniquement jusqu'à Kubernetes 1.23 ; à partir de 1.24, les jetons de compte de service sont gérés séparément via l'API TokenRequest. Une erreur courante ici est de supposer que tous les espaces de noms ont les mêmes valeurs par défaut pour les comptes de service. Vérifiez le compte de service par défaut dans chaque espace de noms et son comportement d'automontage. ```bash kubectl get serviceaccount default -n -o yaml ``` Recherchez `automountServiceAccountToken: false`. Si la valeur est `true`, chaque pod de cet espace de noms reçoit un jeton même s'il n'en a pas besoin, ce qui augmente la surface d'attaque. Lors de la planification des modifications, limitez le rayon d'impact. Appliquez un manifeste à la fois et inspectez les ressources générées. Par exemple, pour désactiver l'automontage dans un espace de noms spécifique, créez un correctif qui cible uniquement le compte de service par défaut de cet espace. ```bash kubectl patch serviceaccount default -n -p '{"automountServiceAccountToken": false}' ``` Vérifiez avec : ```bash kubectl get serviceaccount default -n -o jsonpath='{.automountServiceAccountToken}' ``` La sortie attendue est `false`. Si elle renvoie `true` ou aucune valeur, le correctif n'a pas été appliqué ; vérifiez vos autorisations RBAC et le nom de l'espace de noms. ## Chemin de configuration sécurisé Le chemin de configuration sécurisé pour les comptes de service implique trois couches : le compte de service lui-même, la politique RBAC qui lui accorde des autorisations et la charge de travail qui l'utilise. Chaque couche a ses propres étapes d'observation et de modification. ### Couche 1 : Définition du compte de service Observez la définition actuelle. ```bash kubectl get serviceaccount -n -o yaml ``` Recherchez les annotations et les étiquettes qui peuvent affecter le comportement. Par exemple, l'annotation `eks.amazonaws.com/role-arn` est utilisée sur AWS EKS pour associer un rôle IAM au compte de service. Si vous n'êtes pas sur EKS, cette annotation n'est pas pertinente. Exemple de modification minimale : ajoutez une étiquette pour le suivi de la propriété. ```yaml apiVersion: v1 kind: ServiceAccount metadata: name: payment-sa namespace: payments labels: team: checkout app: payment-processor ``` Appliquez-le et vérifiez. ```bash kubectl apply -f sa.yaml kubectl get serviceaccount payment-sa -n payments --show-labels ``` La sortie attendue comprend `team=checkout,app=payment-processor`. ### Couche 2 : Politique RBAC RBAC lie le compte de service aux autorisations via les rôles (Role) et les liaisons de rôle (RoleBinding) dans un espace de noms, ou via les rôles de cluster (ClusterRole) et les liaisons de rôle de cluster (ClusterRoleBinding) à l'échelle du cluster. Observez les liaisons actuelles. ```bash kubectl get rolebinding,clusterrolebinding --all-namespaces | grep ``` Recherchez les liaisons qui accordent plus d'autorisations que nécessaire. Par exemple, une liaison au ClusterRole `cluster-admin` pour un compte de service utilisé par une application web est une grave erreur de configuration. Exemple de modification : créez un rôle à privilèges minimaux pour un compte de service qui n'a besoin que de lire les ConfigMaps dans son espace de noms. ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: config-reader namespace: payments rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: payment-sa-config-reader namespace: payments subjects: - kind: ServiceAccount name: payment-sa namespace: payments roleRef: kind: Role name: config-reader apiGroup: rbac.authorization.k8s.io ``` Appliquez et vérifiez. ```bash kubectl apply -f rbac.yaml kubectl auth can-i get configmaps --as=system:serviceaccount:payments:payment-sa -n payments ``` La sortie attendue est `yes`. Pour vérifier une action refusée : ```bash kubectl auth can-i create deployments --as=system:serviceaccount:payments:payment-sa -n payments ``` La sortie attendue est `no`. ### Couche 3 : Utilisation par la charge de travail Observez quels pods utilisent le compte de service. ```bash kubectl get pods -n payments -o json | jq '.items[] | select(.spec.serviceAccountName == "payment-sa") | .metadata.name' ``` Exemple de modification : mettez à jour un déploiement (Deployment) pour utiliser le compte de service. ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: payment-processor namespace: payments spec: template: spec: serviceAccountName: payment-sa automountServiceAccountToken: true ``` Appliquez et vérifiez. ```bash kubectl apply -f deployment.yaml kubectl rollout status deployment/payment-processor -n payments ``` Sortie attendue : `deployment "payment-processor" successfully rolled out`. ## Vérification et diagnostics La vérification des comptes de service va au-delà de la simple existence. Vous devez confirmer que l'identité prévue fonctionne, que les jetons ont les bonnes revendications et que la piste d'audit est propre. ### Inspection des jetons Pour inspecter un jeton de compte de service sans l'exposer, utilisez l'API TokenRequest. ```bash kubectl create token payment-sa -n payments --duration=1h ``` Cela imprime un JWT. Décodez la charge utile (ne la partagez pas) pour inspecter les revendications. ```bash echo | cut -d. -f2 | base64 -d 2>/dev/null | jq . ``` La sortie attendue comprend des champs comme `sub: system:serviceaccount:payments:payment-sa`, `namespace: payments`, et les horodatages d'expiration. ### Diagnostic de l'identité du pod Si une application signale des erreurs d'authentification, vérifiez le jeton projeté monté dans le pod. ```bash kubectl exec -it -n payments -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ``` Puis décodez-le comme ci-dessus. Si le jeton est manquant, vérifiez la spécification du pod pour `automountServiceAccountToken: false` ou un `serviceAccountName` manquant. ### Corrélation avec les journaux d'audit Si la journalisation d'audit est activée, recherchez les requêtes effectuées par le compte de service. ```bash grep 'system:serviceaccount:payments:payment-sa' /var/log/kubernetes/audit.log | tail -n 20 ``` Recherchez les appels d'API inattendus ou les refus d'autorisation. Signal de défaillance courant : des erreurs `403 Forbidden` répétées provenant du même compte de service indiquent un rôle (Role) ou une liaison de rôle (RoleBinding) manquant. ## Modes de défaillance et récupération Les comptes de service échouent de manière prévisible. Voici les problèmes de production les plus courants, leurs symptômes et les étapes de récupération. ### Défaillance 1 : Compte de service manquant Symptôme : le pod ne démarre pas avec `Error creating: pods "x" is forbidden: error looking up service account ns/sa: serviceaccount "sa" not found`. Récupération : créez le compte de service ou corrigez le `serviceAccountName` dans la spécification du pod. ```bash kubectl create serviceaccount -n ``` Puis redémarrez le pod. ### Défaillance 2 : Mauvaise configuration de l'automontage Symptôme : l'application ne peut pas s'authentifier car aucun jeton n'est monté. Diagnostic : ```bash kubectl exec -n -- ls /var/run/secrets/kubernetes.io/serviceaccount/ ``` Si le répertoire est vide ou manquant, l'automontage est désactivé quelque part. Vérifiez la spécification du pod et le compte de service. Récupération : définissez `automountServiceAccountToken: true` dans la spécification du pod ou le compte de service, puis recréez le pod. ### Défaillance 3 : Compte de service sur-privilégié compromis Symptôme : activité API inhabituelle d'un compte de service, comme une tentative de lister les secrets dans tous les espaces de noms. Réponse immédiate : révoquez le jeton en supprimant le secret du compte de service (Kubernetes <1.24) ou en redémarrant le pod pour invalider le jeton projeté si la rotation des jetons est définie, puis remplacez RBAC par le moindre privilège. Étapes de récupération : 1. Identifiez le compte de service : `kubectl get pods -n -o json | jq -r '.items[] | select(.spec.serviceAccountName == "") | .metadata.name'` 2. Supprimez le pod pour forcer un nouveau jeton. 3. Examinez et renforcez RBAC. 4. Auditez les journaux pour la fenêtre temporelle de la compromission. ### Défaillance 4 : Expiration du jeton Symptôme : les journaux d'application affichent `Token has expired`. Diagnostic : vérifiez l'expiration du jeton dans la charge utile JWT. Si vous utilisez des secrets statiques, ils peuvent ne pas expirer ; si vous utilisez des jetons projetés, ils expirent en fonction de `expirationSeconds`. Récupération : pour les secrets statiques, supprimez et recréez le secret. Pour les jetons projetés, redémarrez le pod pour obtenir un nouveau jeton. Envisagez d'activer la porte de fonctionnalité `LegacyServiceAccountTokenNoAutoGeneration` pour empêcher la génération automatique de jetons statiques et forcer les jetons projetés. ## Liste de contrôle des opérations Voici une liste de contrôle concise pour la maintenance des comptes de service en production. Chaque élément comprend un responsable et une fréquence d'examen. | # | Élément de la liste de contrôle | Commande / Vérification | Responsable | Fréquence d'examen | |---|----------------|------------------------|-------|----------------| | 1 | Inventorier tous les comptes de service par espace de noms | `kubectl get serviceaccounts --all-namespaces` | Responsable de plateforme (par exemple, Priya Shah, responsable ingénierie) | Mensuelle | | 2 | Vérifier que l'automontage est désactivé là où ce n'est pas nécessaire | `kubectl get serviceaccount -o json | jq '.items[] | {name: .metadata.name, automount: .automountServiceAccountToken}'` | Ingénieur sécurité (par exemple, Alex Chen) | Trimestrielle | | 3 | Auditer les liaisons RBAC pour le moindre privilège | `kubectl get rolebindings,clusterrolebindings --all-namespaces` et examiner chaque sujet | Responsable de plateforme | Trimestrielle | | 4 | Vérifier les comptes de service inutilisés | Comparer `kubectl get serviceaccounts` avec l'utilisation des pods : `kubectl get pods --all-namespaces -o json | jq -r '.items[].spec.serviceAccountName' | sort -u` | Consultant DevOps (par exemple, Marcus Johnson) | Mensuelle | | 5 | Inspecter les paramètres d'expiration des jetons | `kubectl get pods -o json | jq '.items[].spec.volumes[]? | select(.projected.sources[].serviceAccountToken.expirationSeconds) | .projected.sources[].serviceAccountToken.expirationSeconds'` | Ingénieur sécurité | Mensuelle | | 6 | Tester l'accès à l'API en tant que compte de service | `kubectl auth can-i --list --as=system:serviceaccount:: -n ` | Développeur d'astreinte | Hebdomadaire | | 7 | Examiner les journaux d'audit pour activité anormale | Rechercher les noms de compte de service dans les journaux d'audit | Ingénieur sécurité | Hebdomadaire | | 8 | S'assurer que les comptes de service sont inclus dans les plans de sauvegarde et de reprise après sinistre | Vérifier que les procédures de restauration de sauvegarde du cluster incluent les comptes de service et RBAC | Responsable de plateforme | Semestrielle | Chaque responsable est une seule personne imputable, pas un groupe. Elle est responsable d'exécuter la vérification, de documenter les résultats et de lancer les suivis. La fréquence d'examen peut être ajustée en fonction de la taille de l'équipe et du profil de risque, mais elle doit être explicite et suivie dans un calendrier ou un système de tickets. ## Pièges courants et comment les éviter ### Piège 1 : Utiliser le compte de service par défaut pour les charges de travail Le compte de service par défaut dans chaque espace de noms n'a généralement pas d'autorisations explicites mais peut avoir l'automontage activé, donnant à chaque pod un jeton. Si un pod est compromis, l'attaquant peut utiliser ce jeton pour interagir avec l'API (même de manière limitée). Évitement : définissez `automountServiceAccountToken: false` sur le compte de service par défaut et créez des comptes de service dédiés pour chaque charge de travail. Récupération : si vous découvrez des pods utilisant le compte de service par défaut, migrez-les vers un compte dédié et corrigez le déploiement, puis redémarrez les pods. ### Piège 2 : Accorder des autorisations à l'échelle du cluster à des charges de travail d'un espace de noms Utiliser des ClusterRoleBindings pour un compte de service qui n'a besoin d'accéder qu'à un seul espace de noms est une erreur courante de sur-attribution. Par exemple, lier le compte de service d'une application web au ClusterRole `view` expose les ressources de tous les espaces de noms. Évitement : utilisez un RoleBinding avec un Role d'espace de noms chaque fois que possible. Réservez les ClusterRoleBindings aux contrôleurs au niveau du cluster comme les contrôleurs d'entrée ou les agents de surveillance. ### Piège 3 : Coder en dur les jetons de compte de service dans la configuration de l'application Les applications lisent parfois le jeton de compte de service depuis une ConfigMap ou une variable d'environnement, contournant le jeton monté. Cela crée un problème de prolifération des secrets et casse la rotation des jetons. Évitement : utilisez toujours le jeton projeté monté à `/var/run/secrets/kubernetes.io/serviceaccount/token`. Si l'application a besoin d'un jeton à longue durée de vie pour un usage externe, utilisez un mécanisme distinct comme un Secret dédié ou un fournisseur d'identité externe. ### Piège 4 : Ignorer l'expiration des jetons dans les travaux de longue durée Un travail par lots de longue durée utilisant un jeton de compte de service statique peut échouer après l'expiration du jeton (si le cluster applique l'expiration). Évitement : pour les travaux de longue durée, utilisez un compte de service dédié avec un jeton projeté ayant un `expirationSeconds` long (jusqu'au maximum autorisé) ou configurez le travail pour gérer le renouvellement du jeton. ## Conclusion Une liste de contrôle des opérations de production pour les comptes de service Kubernetes transforme la gestion des identités d'une tâche de configuration unique en un processus vérifié en continu. En suivant le principe d'observer avant de modifier, en limitant le rayon d'impact et en utilisant des commandes de vérification concrètes, les équipes peuvent éviter les défaillances courantes de sécurité et de fiabilité. Commencez par une vérification à faible risque : inventoriez vos comptes de service, vérifiez les paramètres d'automontage et examinez une liaison RBAC. Documentez l'état actuel, exécutez la vérification, comparez le résultat avec le signal attendu et attribuez un responsable avec une date d'examen. Ensuite, élargissez la liste de contrôle pour couvrir tous les espaces de noms et inclure l'examen des journaux d'audit. Un flux de travail technique fiable rend la défaillance visible, protège les valeurs sensibles, limite les modifications à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision. Les comptes de service sont une petite partie du plan de contrôle Kubernetes, mais leur configuration a un impact démesuré sur la sécurité du cluster et la fiabilité des charges de travail.