Kubernetes - Le controle d'accès basé sur les rôles (RBAC) - Partie 1
Publié le : 17 janvier 2022 | Mis à jour le : 27 juin 2023Le 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.
Je vais reprendre le même principe que j’ai appliqué pour le billet sur
l’écriture des premiers
manifests. Nous utiliserons le
mode dry-run de la commande kubectl associé à la sortie au format yaml
pour les générer. Je vous rappelle que les commandes kubectl explain <ressource>
et kubectl <command> --help
sont vos amies.
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 subjects: Group, User, Service Account.
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 :
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.
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 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) :
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
:
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 :
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
subjects:
- 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 :
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 :
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
:
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:
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 :
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 :
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.
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
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: bob
Voilà pour aujourd’hui en espérant que cela est clair pour vous désormais. Dans un prochain billet je reviendrais sur ClusterRole et ClusterRoleBinding.