Introduction
Le contrôle d'accès basé sur les rôles (RBAC, Role-Based Access Control) est le mécanisme d'autorisation principal de Kubernetes. Il régit qui peut effectuer quelles actions sur quelles ressources au sein d'un cluster. Lorsque les politiques RBAC sont mal configurées, les utilisateurs et les comptes de service rencontrent des erreurs frustrantes telles que forbidden, cannot list resource, ou User "system:serviceaccount:default:my-sa" cannot get resource. Ces erreurs peuvent bloquer les déploiements d'applications, casser les pipelines CI/CD et dérouter les opérateurs.
Ce guide se concentre sur les erreurs RBAC courantes et leurs correctifs pratiques. Il est écrit pour les développeurs, les ingénieurs DevOps et les équipes techniques de startups qui gèrent des clusters Kubernetes. Nous explorerons comment identifier le comportement spécifique à la version, inspecter les permissions actuelles, appliquer le plus petit changement sûr et vérifier que le correctif fonctionne. L'objectif est la sécurité opérationnelle : observer avant de changer, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets et documenter les étapes de récupération.
Tout au long de cet article, vous verrez des commandes concrètes, des sorties attendues et des signaux d'échec. Nous utiliserons les namespaces, les rôles, les liaisons de rôles (RoleBindings), les rôles de cluster (ClusterRoles) et les liaisons de rôles de cluster (ClusterRoleBindings) pour démontrer les problèmes de permissions à la fois dans un namespace et à l'échelle du cluster. À la fin, vous disposerez d'une liste de contrôle de dépannage systématique pour résoudre les erreurs RBAC en toute confiance.
Inventaire de la version et de l'environnement
Avant de modifier toute configuration RBAC, vous devez comprendre votre environnement de cluster. Le comportement RBAC de Kubernetes peut varier selon les versions en raison des changements d'API, des dépréciations et des nouveaux modes d'accès. Commencez par identifier la version installée et les composants impliqués.
Identifier la version du cluster et la disponibilité de l'API
Exécutez la commande suivante pour vérifier la version du serveur Kubernetes :
kubectl version --short
Sortie attendue (exemple) :
Client Version: v1.27.3
Kustomize Version: v5.0.1
Server Version: v1.28.2
Les versions d'API RBAC rbac.authorization.k8s.io/v1 sont devenues stables dans Kubernetes 1.8. Si vous utilisez un cluster plus ancien (peu probable en production), vous pourriez avoir besoin de v1beta1. La plupart des clusters actuels prennent en charge v1.
Ensuite, vérifiez que le mode d'autorisation RBAC est activé. Vérifiez les drapeaux du serveur d'API (si vous y avez accès) ou interrogez les ressources d'API :
kubectl api-resources | grep rbac
Sortie attendue :
roles rbac.authorization.k8s.io/v1 true Role
rolebindings rbac.authorization.k8s.io/v1 true RoleBinding
clusterroles rbac.authorization.k8s.io/v1 false ClusterRole
clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding
Ces ressources doivent toujours être présentes. Si le RBAC est désactivé, le serveur d'API peut utiliser le mode hérité ABAC ou toujours autoriser, ce qui est rare et non sécurisé.
Confirmer votre identité et le contexte actuel
Les décisions RBAC dépendent de l'identité de l'utilisateur ou du compte de service à l'origine de la demande. Déterminez qui vous êtes et quel contexte vous utilisez :
kubectl config current-context
kubectl auth whoami
La deuxième commande nécessite le plugin kubectl whoami (disponible via krew ou intégré dans les versions plus récentes). S'il n'est pas disponible, vous pouvez vérifier les détails de votre certificat ou jeton. Pour les comptes de service, l'identité est généralement system:serviceaccount:<namespace>:<nom-du-compte-de-service>.
Exemple : Si un pod dans le namespace default avec le compte de service default tente de lister les pods et échoue, le message d'erreur inclut souvent l'identité. Connaître l'identité exacte vous aide à créer la liaison de rôle correcte.
Observation en lecture seule avant les changements
Pour tout problème RBAC suspecté, observez d'abord l'état actuel sans rien modifier. Utilisez des commandes en lecture seule :
kubectl get pods -n <namespace> -o wide
kubectl describe pod <nom-du-pod> -n <namespace>
Si l'échec se produit dans une charge de travail, examinez ses journaux et événements :
kubectl logs <nom-du-pod> -n <namespace> --previous
kubectl get events -n <namespace> --sort-by=.metadata.creationTimestamp
Pour un déploiement qui dépend des permissions, vérifiez son état de déploiement :
kubectl rollout status deployment/<nom-du-déploiement> -n <namespace>
Ces commandes ne modifient pas l'état. Elles fournissent des indices pour déterminer si le problème est réellement l'autorisation ou autre chose (image manquante, contraintes d'ordonnancement, etc.).
Maintenir les tests isolés
Lorsque vous testez des modifications RBAC, commencez dans un namespace dédié. Créez un petit pod de test ou utilisez kubectl auth can-i pour évaluer les permissions avant d'appliquer des manifestes permanents. Par exemple :
kubectl create namespace rbac-test
kubectl auth can-i list pods --as=system:serviceaccount:rbac-test:test-sa -n rbac-test
Le drapeau --as simule un utilisateur ou un compte de service sans modifier les liaisons existantes. C'est inestimable pour vérifier ce qu'une identité spécifique peut faire.
Chemin de configuration sûr
Une fois que vous avez une image claire de l'environnement, vous pouvez appliquer un correctif. Le chemin le plus sûr est d'apporter le plus petit changement qui accorde exactement les permissions requises. Évitez les permissions larges comme cluster-admin sauf si c'est absolument nécessaire.
Comprendre les rôles et les rôles de cluster
- Role : Accorde des permissions dans un seul namespace.
- ClusterRole : Accorde des permissions à l'échelle du cluster ou dans tous les namespaces pour les ressources à portée de namespace. Il est également requis pour les ressources sans namespace comme les nœuds, les volumes persistants et les namespaces eux-mêmes.
Si une application n'a besoin d'accéder qu'à son propre namespace, utilisez un Role avec un RoleBinding. Si elle a besoin d'un accès en lecture à l'échelle du cluster aux pods, utilisez un ClusterRole avec un ClusterRoleBinding.
Exemple : Corriger "forbidden" pour un compte de service qui liste des pods
Problème : Un pod s'exécutant avec le compte de service my-app-sa dans le namespace production journalise :
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:production:my-app-sa" cannot list resource "pods" in API group "" in the namespace "production"
Solution : Créez un Role qui permet de lister les pods et liez-le à ce compte de service.
- Créer le Role (enregistrez sous
pod-reader-role.yaml) :
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
Appliquez-le :
kubectl apply -f pod-reader-role.yaml
- Créer le RoleBinding (enregistrez sous
pod-reader-binding.yaml) :
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: production
subjects:
- kind: ServiceAccount
name: my-app-sa
namespace: production
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Appliquez-le :
kubectl apply -f pod-reader-binding.yaml
- Vérifier avec
kubectl auth can-i:
kubectl auth can-i list pods --as=system:serviceaccount:production:my-app-sa -n production
Sortie attendue :
yes
Si la sortie est no, continuez à déboguer (vérifiez les fautes de frappe, les incohérences de namespace ou l'existence du compte de service).
Éviter les permissions trop larges
Une erreur courante est d'accorder cluster-admin à un compte de service pour résoudre rapidement une erreur de permission. Cela viole le principe du moindre privilège. Au lieu de cela, énumérez les ressources et verbes exacts nécessaires. Par exemple, un contrôleur d'ingress peut avoir besoin de get, list, watch sur services, endpoints et ingresses. Accordez uniquement ceux-là.
Utiliser les commandes kubectl create pour des corrections rapides
Pour des tests temporaires, vous pouvez créer des rôles et des liaisons avec des commandes en une ligne :
kubectl create role pod-reader --verb=get,list,watch --resource=pods -n production
kubectl create rolebinding read-pods --role=pod-reader --serviceaccount=production:my-app-sa -n production
Ces commandes génèrent conceptuellement le même YAML. Cependant, pour la reproductibilité, stockez les manifestes dans un système de contrôle de version.
Vérifier avec un pod de test
Après avoir appliqué le correctif, exécutez un pod de courte durée utilisant le même compte de service pour confirmer que l'opération réussit. Par exemple :
kubectl run test-pod --image=busybox --restart=Never --serviceaccount=my-app-sa -n production -- sleep 3600
Ensuite, exécutez une commande dans le pod et essayez l'appel API en utilisant le jeton du compte de service. Mais une vérification plus simple est d'utiliser kubectl auth can-i, ce qui est généralement suffisant.
Vérification et diagnostics
Après avoir effectué un changement, vous devez vérifier que l'erreur est résolue et qu'aucune permission inattendue n'a été ajoutée. Cette section détaille les commandes et techniques de diagnostic.
Vérifier les permissions effectives avec kubectl auth can-i
La commande kubectl auth can-i est le moyen le plus rapide de tester les permissions. Elle prend en charge le drapeau --as pour usurper l'identité de n'importe quel utilisateur ou compte de service, et --namespace pour limiter la portée de la vérification.
Exemples :
# L'utilisatrice jane peut-elle créer des déploiements dans le namespace dev ?
kubectl auth can-i create deployments --as=jane -n dev
# Le compte de service default dans le namespace kube-system peut-il obtenir des secrets ?
kubectl auth can-i get secrets --as=system:serviceaccount:kube-system:default -n kube-system
# Que peut faire l'utilisateur bob dans le namespace prod ?
kubectl auth can-i --list --as=bob -n prod
Le drapeau --list affiche toutes les actions autorisées, ce qui est utile pour l'audit.
Inspecter les RoleBindings et ClusterRoleBindings
Affichez les liaisons pour vous assurer qu'elles référencent les bons sujets et rôles :
kubectl get rolebindings -n production
kubectl describe rolebinding read-pods -n production
La sortie de description attendue inclut :
Name: read-pods
Namespace: production
Labels: <none>
Annotations: <none>
Role:
Kind: Role
Name: pod-reader
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount my-app-sa production
Vérifiez que le genre (kind) et le nom du sujet correspondent exactement. Les comptes de service sont référencés comme system:serviceaccount:<namespace>:<name>, mais dans la liaison vous spécifiez kind: ServiceAccount et name: <name> avec le namespace s'il est dans un namespace différent.
Consulter les journaux d'audit pour les demandes refusées
Les journaux d'audit Kubernetes enregistrent les décisions d'autorisation. Si vous avez accès au plan de contrôle, examinez le journal d'audit pour les événements forbidden. Recherchez l'utilisateur et la ressource spécifiques :
grep "system:serviceaccount:production:my-app-sa" /var/log/kubernetes/audit.log | grep "pods" | grep "forbidden"
Les journaux d'audit fournissent la demande API exacte, y compris le verbe et la ressource, ce qui vous aide à élaborer la règle précise.
Tester avec une charge de travail réelle
Parfois, kubectl auth can-i dit yes, mais l'application échoue toujours. Cela peut arriver si l'application utilise un groupe API différent ou une sous-ressource (comme pods/log). Pour les sous-ressources, vous devez accorder explicitement les permissions. Par exemple, pour autoriser la lecture des journaux de pods, le Role doit inclure :
rules:
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
Utilisez kubectl auth can-i avec la sous-ressource :
kubectl auth can-i get pods/log --as=system:serviceaccount:production:my-app-sa -n production
Si cela renvoie no, ajoutez la sous-ressource au Role.
Modes de défaillance et récupération
Les modifications RBAC peuvent introduire de nouveaux problèmes. Planifiez les échecs et sachez comment récupérer rapidement.
Modes de défaillance courants
- Permissions trop restrictives : L'utilisateur obtient toujours
forbiddenaprès l'application du correctif. Cela se produit souvent parce que le Role n'inclut pas le bon groupe API ou le bon nom de ressource. Par exemple, les déploiements sont dans le groupe APIapps, pas dans le groupe core. Un Role accordantresources: ["deployments"]avecapiGroups: [""]échouera. Il doit êtreapiGroups: ["apps"].
- Liaison au mauvais sujet : Le RoleBinding référence
name: my-samais le compte de service est dans un namespace différent. Si le sujet est un compte de service, vous devez spécifier son namespace dans le bloc sujet (s'il diffère du namespace du RoleBinding).
- Confusion ClusterRole vs Role : Un RoleBinding dans le namespace
defaultpeut lier un ClusterRole à un sujet, n'accordant des permissions que dans ce namespace. Un ClusterRoleBinding est nécessaire pour un accès à l'échelle du cluster. Mal comprendre cela peut entraîner des permissions insuffisantes.
- Verbes manquants : Certaines opérations nécessitent plusieurs verbes. Par exemple, pour utiliser
kubectl exec, vous avez besoin decreatesurpods/exec. Pour utiliserkubectl logs -f, vous avez besoin degetsurpods/logetwatch.
Étapes de récupération immédiate
Si vous appliquez un changement restrictif et cassez une application, vous pouvez revenir en arrière en supprimant la liaison ou le rôle :
kubectl delete rolebinding read-pods -n production
kubectl delete role pod-reader -n production
Ou, si vous utilisez GitOps, annulez le commit. Gardez toujours une sauvegarde des objets RBAC précédents. Vous pouvez les exporter avec :
kubectl get role pod-reader -n production -o yaml > pod-reader-backup.yaml
Restauration d'accès d'urgence
Dans le pire des cas où un compte de service critique perd l'accès et que le cluster est inaccessible, vous devrez peut-être utiliser les informations d'identification d'administration du cluster (par exemple, le kubeconfig d'origine avec cluster-admin) pour restaurer les permissions. Ne stockez jamais les informations d'identification d'administration dans le cluster ; gardez-les hors ligne comme mesure de secours.
Si le serveur d'API lui-même est mal configuré et que le RBAC refuse toutes les demandes (y compris l'administration), vous devrez peut-être accéder directement au plan de contrôle et modifier les drapeaux d'autorisation RBAC ou passer temporairement à AlwaysAllow (non recommandé pour la production). Cela est rare et devrait faire partie de votre plan de reprise après sinistre.
Liste de contrôle des opérations
Utilisez cette liste de contrôle pour dépanner systématiquement les erreurs RBAC :
- Identifier l'identité en échec : À partir du message d'erreur, notez l'utilisateur ou le compte de service. Exemple :
User "system:serviceaccount:default:my-sa".
- Confirmer l'action demandée : Quel verbe et quelle ressource ? Exemple :
list podsoucreate deployments.
- Vérifier les permissions actuelles : Utilisez
kubectl auth can-i --list --as=<identité> -n <namespace>pour voir les actions autorisées.
- Inspecter les rôles et liaisons existants : Exécutez
kubectl get roles,rolebindings -n <namespace>et décrivez-les pour trouver les règles manquantes.
- Déterminer le type de rôle correct : Ressource namespace dans un seul namespace -> Role ; à l'échelle du cluster ou sans namespace -> ClusterRole.
- Créer le Role/ClusterRole minimal : Écrivez le YAML avec les
apiGroups,resourcesetverbsexacts. Incluez les sous-ressources si nécessaire.
- Lier le rôle à l'identité : Créez un RoleBinding (à portée de namespace) ou un ClusterRoleBinding (à l'échelle du cluster).
- Vérifier avec
kubectl auth can-i: Simulez l'action exacte.
- Tester avec une charge de travail réelle : Déployez un pod de test utilisant le même compte de service et exécutez l'opération.
- Documenter le correctif : Enregistrez le YAML dans le contrôle de version et notez la raison.
Exemple d'exécution de la liste de contrôle pour une erreur courante
Erreur : Error from server (Forbidden): deployments.apps is forbidden: User "developer" cannot create resource "deployments" in API group "apps" in the namespace "dev"
- Identité :
developer(un utilisateur) - Action :
create deploymentsdans le namespacedev - Vérifier :
kubectl auth can-i create deployments --as=developer -n devrenvoieno - Inspecter :
kubectl get rolebindings -n devne montre aucune liaison pour developer - Type de rôle : Role à portée de namespace
- Créer le Role :
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev
name: developer
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["create", "get", "list", "update", "patch", "delete"]
- Lier :
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-binding
namespace: dev
subjects:
- kind: User
name: developer
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
- Vérifier :
kubectl auth can-i create deployments --as=developer -n devrenvoieyes - Tester : developer peut maintenant créer des déploiements.
Conclusion
Les erreurs RBAC Kubernetes sont courantes mais gérables avec une approche systématique. En commençant par un inventaire approfondi de l'environnement, en appliquant des permissions minimales et spécifiques, et en vérifiant avec kubectl auth can-i, vous pouvez résoudre la plupart des problèmes sans recourir à un accès trop large.
N'oubliez pas que le RBAC est une couche de sécurité critique. Chaque changement doit être versionné, observable et réversible lorsque cela est possible. Testez toujours d'abord dans un namespace non productif, utilisez l'usurpation d'identité pour simuler des identités et conservez des sauvegardes des objets RBAC.
Comme prochaine étape, prenez une erreur RBAC à faible risque de votre cluster et appliquez cette liste de contrôle. Enregistrez l'état actuel, exécutez les commandes de diagnostic, apportez le plus petit changement et vérifiez le résultat. Passez en revue les dépendances telles que le groupe API et les sous-ressources pour garantir l'exhaustivité.
Un flux de travail technique fiable rend les échecs visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision.