Aller au contenu

Kubernetes et les RBAC

logo kubernetes

Le contrôle d’accès basé sur les rôles (RBAC) est un mécanisme de sécurité dans lequel chaque autorisation d’accès est basée sur des rôles qui sont attribués à un utilisateur. Avec ce système, il est donc possible de restreindre l’accès aux ressources d’un cluster Kubernetes (namespaces, pods, jobs) à des applications ou des utilisateurs.

Kubernetes RBAC : concepts

Dans Kubernetes, les stratégies RBAC peuvent être utilisées pour gérer aussi bien les droits d’accès d’un utilisateur système (User ou Group) que ceux des comptes de service (Service Account).

Un rôle permet de définir des autorisations d’accès via des verbes sur certains objets de l’API de Kubernetes, tels que des pods, des nodes, des deployments, des ConfigMaps, …

Kubernetes possède quatre objets liés aux RBAC qui peuvent être combinés pour définir les autorisations d’accès aux ressources du cluster. Il s’agit de Role, ClusterRole, RoleBinding et ClusterRoleBinding.

Role et ClusterRole

Comme leur nom l’indique, ces objets définissent les types d’accès que vous attribuez aux rôles.

  • Le Role est là pour gérer les autorisations pour accéder aux ressources d’un espace de noms uniquement.
  • Le ClusterRole est lui sans espaces de noms et donc permet de définir des autorisations à des ressources à l’échelle du cluster.

RoleBinding et ClusterRoleBinding

Les Binding’s permettent d’attribuer des rôles (Role et ClusterRole) à des

Création des ressources RBAC

Je ne documenterai pour le moment la création du role et du rolebinding. Avant vérifions que RBAC est bien activé sur le cluster :

Terminal window
kubectl get cm -n kube-system kubeadm-config -o yaml | grep RBAC
authorization-mode: Node,RBAC

Oui, c’est le cas. Nous avons bien RBAC dans authorization-mode.

Création d’un Role

Commençons par la création d’un rôle avec la commande kubectl create role. Cette commande ne fonctionne que si on lui indiquons les deux options --verb et --resource. Je ne connais pas les verbes pour le moment donc je mets ”*”

Avant comme nous manipulons des rôles, nous allons créer un namespace de test.

Terminal window
kubectl create namespace test
kubectl -n test create role pod-read --dry-run=client --verb=* --resource=pod -o yaml

La commande create role ne fonctionne que si on lui donne les deux options —verb et —resource. Ici j’ai mis une étoile sur verbe, car je ne connais pas les verbes qui lui sont attachés (pour le moment). Ce qui donne :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: pod-read
namespace: test
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- '*'

On voit que nous devons définir les apiGroup, les resources et les verbs.

Pour retrouver la liste des api nous allons utiliser la commande kubectl api-ressources -o wide permet de lister l’ensemble des ressources et les verbes associés. Par exemple listons les ressources de l’apiGroup "", dont fait partie la ressource pods, qui peuvent être utilisé dans le cas d’un rôle (namespaced) :

Terminal window
kubectl api-resources --api-group="" --namespaced -o wide |grep pod
NAME SHORTNAMES APIVERSION NAMESPACED KIND VERBS
pods po v1 true Pod [create delete deletecollection get list patch update watch]
podtemplates v1 true PodTemplate [create delete deletecollection get list patch update watch]

Donc nous voyons que la ressource pods est lié à l’api Core de Kubernetes, celle sans nom (""). On peut restreindre les verbes de cette ressource parmi : create, delete, deletecollection, get, list, patch, update et watch.

Par exemple si nous voulons que notre utilisateur ne puisse que lister les pods nous lui donnerions l’autorisation d’utiliser le verbe list. Pour en afficher le contenu get et ainsi de suite …

Pour mon exemple je vais lui donner les droits list et get :

Terminal window
kubectl -n test create role pod-read --dry-run=client --verb=get,list

Création d’un RoleBinding

Je vais créer le rolebinding permettant d’attribuer le role pod-read à un utilisateur système bob que je créerai par la suite :

Terminal window
kubectl -n test create rolebinding pod-read-bob --role=pod-read --user=bob --dry-run=client -o yaml

Ce qui donne :

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: pod-read-bob
namespace: test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-read
- apiGroup: rbac.authorization.k8s.io
kind: User
name: bob

Donc on peut voir que le rôle est défini avec la clé roleRef et que les droits sont donnés à des subjects. Ces sujets peuvent être de type kind : user, group ou serviceaccount.

Créons notre rolebinding :

Terminal window
kubectl -n test create rolebinding pod-read-bob --role=pod-read --user=bob
rolebinding.rbac.authorization.k8s.io/pod-read-bob created

Création d’un user système ayant seulement accès à un namespace

Nous allons voir comment il est possible de créer un utilisateur système en ne lui donnant à notre namespace test. J’utilise ma Sandbox pour cet exemple.

Sur ma VM controller je vais commencer par créer un user bob :

Terminal window
ssh controller
sudo useradd --create-home -s /bin/bash bob
sudo mkdir -p /home/bob/.kube

Maintenant je dois lui créer sa configuration (KUBECONFIG). Je me connecte sur le nœud master, car je vais utiliser les commandes kubectl et kubeadm pour créer et signer cette configuration. Cette méthode est bien plus rapide que de créer à la main le certificat avec openssl :

Terminal window
ssh master1
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl get cm -n kube-system kubeadm-config -o jsonpath='{ .data.ClusterConfiguration }' > cluster-configuration.yaml
sudo kubeadm kubeconfig user --client-name bob --config=cluster-configuration.yaml

À la sortie nous obtenons bien une configuration qu’il faut donner à notre user :

apiVersion: v1
clusters:
- cluster:
certificate-authority-data:
...
server: https://10.240.0.10:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: bob
name: bob@kubernetes
current-context: bob@kubernetes
kind: Config
preferences: {}
users:
- name: bob
user:
client-certificate-data:
...
client-key-data:
...

J’ai enlevé les clés des certificats que cela n’apporte rien à notre exemple. On retourne sur notre node controller où nous avons créé le user bob. Nous allons lui donner cette configuration en la copiant/collant dans le fichier ~/.kube/config. Ensuite nous modifierons le context pour qu’il pointe sur le namespace test:

Terminal window
ssh controller
vagrant@controller:~$sudo su - bob
bob@controller:~$ vi ~/.kube/config # copier/coller le fichier généré au dessus

Maintenant testons notre accès :

Terminal window
bob@controller:~$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "bob" cannot list resource "pods" in API group "" in the namespace "default"

On voit que le user bob n’a pas les autorisations de lister les ressources de type pods de l’apiGroup "" du namespace default. Changeons de namespaces et relançons :

Terminal window
bob@controller:~$ kubectl config set-context --current --namespace=test
Context "bob@kubernetes" modified.
bob@controller:~$ kubectl get pod
No resources found in test namespace.

Cette fois, nous avons bien les droits. Essayons de créer un pod.

Terminal window
bob@controller:~$ kubectl run busybox --image=busybox
Error from server (Forbidden): pods is forbidden: User "bob" cannot create resource "pods" in API group "" in the namespace "test": RBAC: role.rbac.authorization.k8s.io "pod-read" not found

Donc si on devait lui donner les droits de création de pods il faudrait écrire ce rôle en plus et l’attribuer via le rolebinding :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: pod-write-bob
namespace: test
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- update
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: pod-write-bob
namespace: test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-write
- apiGroup: rbac.authorization.k8s.io
kind: User
name: bob

Voilà pour aujourd’hui en espérant que cela est clair pour vous désormais.