Aller au contenu
English
Conteneurs & Orchestration medium

Kubernetes RBAC : gérer les accès en sécurité

50 min de lecture

logo kubernetes

Quand on gère un cluster Kubernetes, la question de la sécurité se pose très vite : comment limiter l'accès aux ressources pour que seul ce qui est nécessaire soit autorisé ? C'est là qu'entre en jeu RBAC (Role-Based Access Control), un système de contrôle d'accès basé sur les rôles.

RBAC permet de définir qui peut effectuer quelle action sur quelles ressources. Imaginez que vous gérez une entreprise : certains employés peuvent consulter des données sensibles, d'autres non. Dans un cluster Kubernetes, c'est pareil. Avec RBAC, vous pouvez attribuer des rôles spécifiques aux utilisateurs, aux groupes ou aux applications, pour qu'ils aient seulement les permissions nécessaires à leurs tâches.

  • Distinguer les quatre objets RBAC, et surtout Role de ClusterRole
  • Créer un utilisateur authentifié par certificat, que Kubernetes ne sait pas fabriquer lui-même
  • Lui accorder des permissions minimales, puis vérifier ce qu'il peut et ne peut pas faire
  • Lire un message Forbidden, qui nomme toujours le sujet, le verbe et la ressource refusés

Une surprise attend qui découvre RBAC : Kubernetes n'a pas d'objet User. Vous ne créerez jamais un utilisateur avec kubectl create user, la commande n'existe pas. Un « utilisateur » n'est qu'un nom que l'API server lit dans le champ CN d'un certificat client signé par la CA du cluster, ou que lui transmet un fournisseur d'identité externe.

Cette absence explique la longueur du lab plus bas : créer un utilisateur revient à fabriquer et signer un certificat, puis à l'inscrire dans un kubeconfig. Les ServiceAccounts, eux, sont de vrais objets Kubernetes, et c'est pourquoi ils sont l'identité des applications, jamais des humains.

Pour comprendre comment utiliser RBAC dans Kubernetes, il est essentiel de saisir ses concepts fondamentaux et son fonctionnement. RBAC repose sur quatre ressources principales : Role, ClusterRole, RoleBinding et ClusterRoleBinding. Chaque élément joue un rôle précis dans la gestion des permissions au sein du cluster.

RBAC est activé par défaut sur toutes les distributions Kubernetes actuelles, vous n'avez rien à installer. Une commande le confirme sur n'importe quel cluster :

Fenêtre de terminal
kubectl api-versions | grep rbac
Sortie
rbac.authorization.k8s.io/v1

Retenez aussi le principe qui gouverne tout le reste : RBAC refuse par défaut. Tout ce qui n'est pas explicitement accordé est interdit, et il n'existe aucune règle de refus à écrire, contrairement à ce que proposent beaucoup de pare-feux.

Ces deux types de ressources définissent les permissions applicables aux utilisateurs, groupes ou comptes de service.

  • Role : Un Role est limité à un namespace spécifique. Il permet de définir des permissions sur les ressources de ce namespace uniquement. Par exemple, on peut créer un rôle qui permet à un utilisateur de lister et lire les pods dans le namespace default.

  • ClusterRole : un ClusterRole n'appartient à aucun namespace. C'est ce qui lui permet de décrire des droits sur les ressources sans namespace, les nœuds ou les volumes persistants par exemple. Mais sa portée réelle est décidée par le binding qui l'accompagne, pas par lui : associé à un ClusterRoleBinding, il vaut sur tout le cluster ; associé à un RoleBinding, le même ClusterRole ne vaut que dans ce namespace. C'est ce troisième cas qui permet de définir une fois un rôle de lecture et de l'accorder namespace par namespace.

Exemple d'un Role :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]

Exemple d'un ClusterRole :

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-reader-cluster
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]

Ces ressources permettent d'associer un rôle à un utilisateur, un groupe ou un compte de service.

  • RoleBinding : Lie un Role à un utilisateur ou groupe pour un namespace donné. Il est idéal pour appliquer des permissions limitées à une équipe ou un projet spécifique.

  • ClusterRoleBinding : Lie un ClusterRole à un utilisateur ou groupe à l'échelle du cluster. Utilisé pour donner des droits globaux ou accéder à des ressources hors d'un namespace.

Exemple d'un RoleBinding :

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: bind-pod-reader
namespace: default
subjects:
- kind: User
name: "johndoe" # Utilisateur à qui on attribue le rôle
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader # Le rôle défini précédemment
apiGroup: rbac.authorization.k8s.io

Exemple d'un ClusterRoleBinding :

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-pod-reader-binding
subjects:
- kind: User
name: "admin-user" # Utilisateur avec des droits globaux
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: pod-reader-cluster
apiGroup: rbac.authorization.k8s.io

Les verbs définissent les actions autorisées sur les ressources. Voici les verbs les plus utilisés dans Kubernetes :

  • get : Lire une ressource.
  • list : Lister les ressources.
  • create : Créer une ressource.
  • update : Modifier une ressource existante.
  • delete : Supprimer une ressource.
  • watch : Observer les modifications sur une ressource en temps réel.

Ces verbs sont utilisés dans les règles des Roles et ClusterRoles pour définir précisément les actions autorisées.

Le lab : donner des droits à un utilisateur, de bout en bout

Section intitulée « Le lab : donner des droits à un utilisateur, de bout en bout »

Ce lab se joue sur le cluster kind de la formation. Il enchaîne huit étapes, de la création du namespace jusqu'à la vérification qu'une action interdite l'est vraiment. Toutes les sorties publiées ci-dessous ont été relevées sur ce cluster.

Trois outils, et une précision qui compte : vous aurez besoin d'un accès à la clé privée de la CA du cluster, ce qui suppose d'être administrateur de la machine qui l'héberge. C'est précisément pour cette raison que signer des certificats à la main est un geste de lab et de dépannage, pas une méthode d'administration courante.

OutilRôle ici
un cluster kindle cluster de la formation, dont la CA est accessible par docker exec
kubectlcréer les objets et basculer d'identité
OpenSSLgénérer la clé, la demande de signature et le certificat

Confirmez d'abord que vous parlez au bon cluster et que vous y êtes administrateur : tout ce qui suit suppose le contexte par défaut, celui qui a tous les droits. C'est précisément l'identité que vous allez quitter à l'étape 7.

Fenêtre de terminal
kubectl get nodes
Sortie
NAME STATUS ROLES AGE VERSION
doc-k8s-control-plane Ready control-plane 40h v1.37.0
doc-k8s-worker Ready <none> 40h v1.37.0

Pour organiser les ressources RBAC, créez un namespace spécifique nommé rbac-lab :

Fenêtre de terminal
kubectl create namespace rbac-lab

Vérifiez qu'il est bien créé :

Fenêtre de terminal
kubectl get namespaces
NAME STATUS AGE
default Active 10m
kube-node-lease Active 10m
kube-public Active 10m
kube-system Active 10m
rbac-lab Active 10m

Ajoutez des pods de test pour simuler un environnement réel.

Fichier YAML : nginx-pods.yaml

apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: rbac-lab
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.28@sha256:146adea4768b83c607d0bdfa4188464e3da6e0a3ad4475db1d1d8f64f27c29cc
ports:
- containerPort: 80

Appliquez le fichier :

Fenêtre de terminal
kubectl apply -f nginx-pods.yaml

Vérifiez que les pods sont en cours d'exécution :

Fenêtre de terminal
kubectl get pods -n rbac-lab
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 10m

Créez un Role pour permettre de lire les pods dans le namespace rbac-lab.

Fichier YAML : role-pod-reader.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: rbac-lab
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]

Appliquez le Role :

Fenêtre de terminal
kubectl apply -f role-pod-reader.yaml

Ensuite, liez ce Role à un utilisateur fictif nommé test-user via un

RoleBinding.

Fichier YAML : rolebinding-pod-reader.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: rbac-lab
subjects:
- kind: User
name: test-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io

Appliquez le RoleBinding :

Fenêtre de terminal
kubectl apply -f rolebinding-pod-reader.yaml

C'est ici que se joue le point que le début de ce guide annonçait : comme Kubernetes n'a pas d'objet User, l'identité test-user n'existera que parce qu'un certificat signé par la CA du cluster porte ce nom dans son champ CN.

  1. Exporter la CA du cluster. Sur un nœud kind, la CA vit à l'emplacement standard de kubeadm, /etc/kubernetes/pki/. Le nœud étant un conteneur, on y accède par docker exec :

    Fenêtre de terminal
    docker exec doc-k8s-control-plane cat /etc/kubernetes/pki/ca.crt > ca.crt
    docker exec doc-k8s-control-plane cat /etc/kubernetes/pki/ca.key > ca.key

    La clé privée de la CA signe toutes les identités du cluster. Traitez ces deux fichiers comme ce qu'ils sont, le secret le plus sensible de votre installation, et supprimez-les dès la fin du lab.

  2. Générer une clé privée pour test-user Créez une clé privée :

    Fenêtre de terminal
    openssl genrsa -out test-user.key 2048
  3. Générer une demande de signature de certificat (CSR) Créez un fichier CSR pour test-user :

    Fenêtre de terminal
    openssl req -new -key test-user.key -out test-user.csr -subj "/CN=test-user"
  4. Signer le certificat avec la CA du cluster :

    Fenêtre de terminal
    openssl x509 -req -in test-user.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out test-user.crt -days 365
    Sortie
    Certificate request self-signature ok
    subject=CN = test-user

    Le certificat obtenu porte bien test-user comme sujet, et la CA du cluster comme émetteur. C'est cette paire qui fait l'identité :

    Fenêtre de terminal
    openssl x509 -in test-user.crt -noout -subject -issuer
    Sortie
    subject=CN = test-user
    issuer=CN = kubernetes

Étape 6 : Ajouter l'Utilisateur dans le kubeconfig

Section intitulée « Étape 6 : Ajouter l'Utilisateur dans le kubeconfig »

Ajoutez l'utilisateur test-user à la configuration de Kubernetes pour qu'il puisse interagir avec le cluster.

  1. Configurer les informations d'authentification de test-user :

    Fenêtre de terminal
    kubectl config set-credentials test-user \
    --client-certificate=test-user.crt \
    --client-key=test-user.key
  2. Créer un contexte pour test-user dans le namespace rbac-lab. Le nom du cluster n'est pas libre, il doit être celui déjà présent dans votre kubeconfig, kind-doc-k8s ici. kubectl config get-clusters le donne :

    Fenêtre de terminal
    kubectl config set-context test-user-context \
    --cluster=kind-doc-k8s \
    --namespace=rbac-lab \
    --user=test-user
  3. Basculer vers le contexte de test-user :

    Fenêtre de terminal
    kubectl config use-context test-user-context

Une fois le contexte configuré, testez les permissions attribuées à test-user :

  1. Lister les pods du namespace rbac-lab, ce que le Role autorise :

    Fenêtre de terminal
    kubectl get pods
    Sortie
    NAME READY STATUS RESTARTS AGE
    nginx 1/1 Running 0 1s
  2. Tenter de créer un Pod, ce que le Role n'autorise pas :

    Fenêtre de terminal
    kubectl run unauthorized-pod --image=nginx:1.30@sha256:d5792f71a9496b833bc08ea834a758c46e2b6a6306c10f4be926f38a656cdc1c
    Sortie
    Error from server (Forbidden): pods is forbidden: User "test-user" cannot
    create resource "pods" in API group "" in the namespace "rbac-lab"
  3. Tenter de lister les Pods d'un autre namespace, pour vérifier que le Role est bien cantonné au sien :

    Fenêtre de terminal
    kubectl get pods -n default
    Sortie
    Error from server (Forbidden): pods is forbidden: User "test-user" cannot
    list resource "pods" in API group "" in the namespace "default"

Ces deux erreurs ont exactement la même structure, et c'est ce qui les rend utiles : un message Forbidden nomme toujours le sujet refusé, le verbe et la ressource, puis le namespace. Comparez-les et la différence saute aux yeux, create contre list, rbac-lab contre default : le premier refus vient d'un verbe absent du Role, le second d'un namespace hors de sa portée. Lisez le message en entier avant de modifier quoi que ce soit, il contient déjà le diagnostic.

Étape 8 : Vérifier les permissions sans tâtonner

Section intitulée « Étape 8 : Vérifier les permissions sans tâtonner »

Deviner par essais successifs n'est pas nécessaire : l'utilisateur peut demander lui-même ce à quoi il a droit.

Fenêtre de terminal
kubectl auth can-i --list
Sortie
Resources Non-Resource URLs Resource Names Verbs
selfsubjectreviews.authentication.k8s.io [] [] [create]
selfsubjectaccessreviews.authorization.k8s.io [] [] [create]
selfsubjectrulesreviews.authorization.k8s.io [] [] [create]
pods [] [] [get list]
[/api/*] [] [get]

Une seule ligne vient de votre Role, celle des pods en [get list]. Les autres sont accordées à tout le monde par le ClusterRole system:basic-user : elles permettent uniquement à un utilisateur de poser des questions sur lui-même, ce qui est justement le mécanisme derrière auth can-i.

Le namespace emporte le Role et le RoleBinding avec lui, mais le kubeconfig et les fichiers de certificats survivent : ce sont eux qu'il ne faut pas oublier.

Fenêtre de terminal
kubectl config use-context kind-doc-k8s
kubectl delete namespace rbac-lab
kubectl config delete-context test-user-context
kubectl config unset users.test-user

Supprimez enfin les fichiers produits, la clé de la CA en premier :

Fenêtre de terminal
rm -f ca.key ca.crt ca.srl test-user.key test-user.csr test-user.crt

Sept questions sur les distinctions qui coûtent le plus cher : la portée réelle d'un ClusterRole selon le binding qui l'accompagne, et ce qu'un message Forbidden désigne exactement.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

7 questions
5 min.
90% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  1. Kubernetes n'a pas d'objet User : une identité humaine est un CN dans un certificat signé par la CA du cluster, ou un compte d'un fournisseur externe.
  2. Role et ClusterRole définissent des permissions, RoleBinding et ClusterRoleBinding les accordent à quelqu'un. Ce sont deux gestes séparés.
  3. Le préfixe Cluster dit la portée de l'objet, pas celle des droits : un ClusterRole associé par un RoleBinding ne vaut que dans un namespace.
  4. RBAC refuse par défaut : tout ce qui n'est pas explicitement accordé est interdit, et il n'existe aucune règle de refus à écrire.
  5. Un message Forbidden porte son diagnostic : le sujet, le verbe, la ressource et le namespace y figurent tous les quatre.
  6. kubectl auth can-i --list évite le tâtonnement et répond sans qu'on ait à tenter l'action.
  7. La clé privée de la CA signe toutes les identités du cluster : la sortir d'un nœud pour signer un certificat est un geste de lab, à effacer derrière soi.
  • AppArmor et Seccomp : Restreindre ce qu'un conteneur peut demander au noyau, une fois ses droits d'API réglés.
  • Pod Security Standards : Imposer un niveau de privilèges à tout un namespace, en complément des droits RBAC.
  • Admission Controllers : Comprendre pourquoi une requête autorisée par RBAC peut malgré tout être rejetée.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn