RBAC : Role-based access control
RBAC, ou Role-Based Access Control, est une méthode de gestion des autorisations dans Kubernetes. Il permet de définir qui peut faire quoi dans un cluster Kubernetes en attribuant des rôles et des règles à des utilisateurs ou à des groupes d'utilisateurs.
Composants clés de RBAC Kubernetes :
-
Roles (rôles avec une porté namespace) : Les rôles définissent les autorisations (par exemple, la lecture, la création, la mise à jour ou la suppression) sur un ou plusieurs types de ressources (par exemple, pods, services, configmaps) dans un namespace spécifique.
-
ClusterRoles (rôles avec une portée cluster) : Les rôles avec portée cluster sont similaires aux rôles, mais ils s'appliquent à l'ensemble du cluster, indépendamment de l'espace de noms.
-
RoleBindings (liaisons de rôles) : Association des rôles à des utilisateurs ou à des groupes d'utilisateurs spécifiques dans un namespace donné.
-
ClusterRoleBindings (liaisons avec une portée cluster) : Les liaisons de rôles au niveau du cluster associent des rôles au niveau du cluster à des utilisateurs ou à des groupes d'utilisateurs spécifiques dans l'ensemble du cluster.
-
Service Account : Fournit une identité pour les processus qui s'exécutent dans un pod et est mappé à un objet Role/ClusterRole. Lorsque vous vous authentifiez auprès du serveur API, vous vous identifiez en tant qu'utilisateur particulier. Kubernetes reconnaît le concept d'utilisateur, cependant, Kubernetes lui-même ne dispose pas d'API utilisateur
Attention!
- Dans tous les namesapces, un serviceAcount default est créé et donne accès à l'api server. Il faut donc créer un autre service account pour cahque workload en désactivant son token: automountServiceAccountToken = false
- Les workloads metier generalement n'ont pas besoin d'acceder à l'api server. IL faut donc toujours mettre automountServiceAccountToken = false sur leur serviceAcount car il est true par defaut.
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
automountServiceAccountToken: false # desactive l'accès à l'api server
- Création d'un Role et RoleBinding :
- Création d'une idententité pour un pod :
Créez un utilisateur (dans le cadre de l'authentification Kubernetes, cela peut être un ServiceAccount) et liez-le au rôle que vous avez créé. Voici comment créer un utilisateur et une liaison de rôles (RoleBinding) :
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: role-get-pods
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: stagiaire-serviceaccount
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rolebinding-list-pods
namespace: default
subjects:
- kind: ServiceAccount
name: stagiaire-serviceaccount
roleRef:
kind: Role
name: role-get-pods
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Pod
metadata:
name: kubectl-pod
spec:
serviceAccountName: stagiaire-serviceaccount
containers:
- name: kubectl-container
image: bitnami/kubectl:latest # Utilisez l'image kubectl de Bitnami
command: ["sleep"] # Utilisez une commande qui attend pour maintenir le pod en vie
args: ["3600"] # Par exemple, faire dormir le pod pendant 1 heure (3600 secondes)
-
- Le Role role-get-pods limite les doirts aux ressources pods ou un stagiaire et avec uniquement la possibilité de les lister(get).
- Le service account statgiaire-serviceaccount est un compte que sera utilisé par le pod ou utilisateur pour s'autentifier aux près de l'api kube.
- Le RoleBinding rolebinding-list-pods est utilisé pour faire correspondre le le role et le service account.
- Les objets workloads ou utlisateurs qui vont utiliser ce service account seront limités aux droits listés dans le role et uniquement pour le namespace default.
- On peut créer un kubeconfig avec ce service account et le donner à un stagiaire pour limiter ses droits
Mettre l'exemple dans un fichier pods-sa.yaml et l'executer.
kubectl apply -f pods-sa.yaml
kubectl get po,role,rolebinding,sa

On ouvre un shell dans le pode et faire des tests.
kubectl exec -it pods/kubectl-pod -- bash
kubectl get po # marche
kubectl get role # ne marche pas
kubectl get po -n kube-system # ne marche pas car il s'agit d'un role limité au namespace default et non un cluster role

- Création d'un ClusterRole et ClusterRoleBinding :
- Création d'une idententité pour un pod :
Il s'agit du meme exemple mais avec une porté cluster. Ici on augmente les droits pour le manager de l'équipe par exemple.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cr-manager
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: manager-sa
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-cr-binding
subjects:
- kind: ServiceAccount
name: manager-sa
namespace: default
roleRef:
kind: ClusterRole
name: cr-manager
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Pod
metadata:
name: kubectl-pod-manager
namespace: default
spec:
serviceAccountName: manager-sa
containers:
- name: kubectl-container
image: bitnami/kubectl:latest # Utilisez l'image kubectl de Bitnami
command: ["sleep"] # Utilisez une commande qui attend pour maintenir le pod en vie
args: ["3600"] # Par exemple, faire dormir le pod pendant 1 heure (3600 secondes)
- Le ClusterRole cr-manager limite les doirts à toutes les ressources et avec la possibilité d'executer ses verbes: "get", "list", "watch", "create", "update", "patch", "delete".
- Le service account manager-sa est un compte que sera utilisé par le pod/chef d'équipe pour s'autentifier aux près de l'api kube.
- Le ClusterRoleBinding manager-cr-binding est utilisé pour faire correspondre le cluster role et le service account.
- Les objets workloads ou utilisateurs qui vont utiliser ce service account seront limités aux droits listés dans le cluster role et pour les namespaces du cluster.
- On peut créer un kubeconfig avec ce service account et le donner à au manager pour limiter ses droits
Mettre l'exemple dans un fichier pods-cr-sa.yaml et l'executer.
kubectl apply -f pods-cr-sa.yaml
kubectl get po
On ouvre un shell dans le pode et faire des tests.
kubectl exec -it pods/kubectl-pod-manager -- bash
kubectl get po # marche
kubectl get role # ne marche pas
kubectl get po -n kube-system # ne marche pas car il s'agit d'un role limité au namespace default et non un cluster role

Pour plus de restrictions:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: aggregate-cron-tabs-edit
labels:
# Add these permissions to the "admin" and "edit" default roles.
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rules:
- apiGroups: ["stable.example.com"]
resources: ["crontabs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: stagiaire-serviceaccount
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: aggregate-cron-tabs-view
labels:
# Add these permissions to the "view" default role.
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["stable.example.com"]
resources: ["crontabs"]
verbs: ["get", "list", "watch"]
---
apiVersion: v1
kind: Pod
metadata:
name: kubectl-pod
spec:
serviceAccountName: stagiaire-serviceaccount
containers:
- name: kubectl-container
image: bitnami/kubectl:latest # Utilisez l'image kubectl de Bitnami
command: ["sleep"] # Utilisez une commande qui attend pour maintenir le pod en vie
args: ["3600"] # Par exemple, faire dormir le pod pendant 1 heure (3600 secondes)
ServiceAccount / context / kubeconfig
Comme le user va acceder à l'api server, on met automountServiceAccountToken = true ou on enlève tout simplement car activé par defaut.
#!/bin/sh
# Variables de configuration
clustername="test-k8s-kubeadm"
name="manager-sa"
ns="default"
server="https://192.168.1.200:6443"
crb=true # mettre à true si cluster role binding et mettre rb = false
crb_name="manager-cr-binding"
rb=false # mettre à true si role binding et mettre crb = false
rb_name="manager-rolebinding"
# Vérification et création du ServiceAccount
if ! kubectl get sa "$name" -n "$ns" > /dev/null 2>&1; then
kubectl create serviceaccount "$name" -n "$ns"
echo "ServiceAccount $name créé dans le namespace $ns."
else
echo "ServiceAccount $name existe déjà dans le namespace $ns."
fi
# Récupération du nom et UID du ServiceAccount
sa_name=$(kubectl get sa "$name" -n "$ns" -o jsonpath='{.metadata.name}')
sa_uid=$(kubectl get sa "$name" -n "$ns" -o jsonpath='{.metadata.uid}')
# Vérification et création du secret
secret_name="${sa_name}-token-${sa_uid}"
if ! kubectl get secret "$secret_name" -n "$ns" > /dev/null 2>&1; then
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
name: $secret_name
namespace: $ns
annotations:
kubernetes.io/service-account.name: $sa_name
EOF
echo "Secret $secret_name créé pour le ServiceAccount $sa_name."
else
echo "Secret $secret_name existe déjà pour le ServiceAccount $sa_name."
fi
# Gestion des bindings (ClusterRoleBinding ou RoleBinding)
if [ "$crb" = true ] && [ "$rb" = true ]; then
echo "Erreur : Vous ne pouvez pas activer à la fois 'crb' et 'rb'."
exit 1
fi
if [ "$crb" = true ]; then
if kubectl get clusterrolebinding "$crb_name" > /dev/null 2>&1; then
kubectl patch clusterrolebinding "$crb_name" --type='json' -p="[{\"op\": \"add\", \"path\": \"/subjects/-\", \"value\": {\"kind\": \"ServiceAccount\", \"name\": \"$sa_name\", \"namespace\": \"$ns\"}}]"
echo "ClusterRoleBinding $crb_name mis à jour avec le ServiceAccount $sa_name."
else
echo "Erreur : ClusterRoleBinding $crb_name n'existe pas."
exit 1
fi
elif [ "$rb" = true ]; then
if kubectl get rolebinding "$rb_name" -n "$ns" > /dev/null 2>&1; then
kubectl patch rolebinding "$rb_name" -n "$ns" --type='json' -p="[{\"op\": \"add\", \"path\": \"/subjects/-\", \"value\": {\"kind\": \"ServiceAccount\", \"name\": \"$sa_name\", \"namespace\": \"$ns\"}}]"
echo "RoleBinding $rb_name mis à jour avec le ServiceAccount $sa_name dans le namespace $ns."
else
echo "Erreur : RoleBinding $rb_name n'existe pas dans le namespace $ns."
exit 1
fi
fi
# Génération du fichier kubeconfig
ca=$(kubectl get secret "$secret_name" -n "$ns" -o jsonpath='{.data.ca\.crt}')
token=$(kubectl get secret "$secret_name" -n "$ns" -o jsonpath='{.data.token}' | base64 --decode)
kubeconfig_content=$(cat <<EOF
apiVersion: v1
kind: Config
clusters:
- name: ${clustername}
cluster:
certificate-authority-data: ${ca}
server: ${server}
contexts:
- name: ${sa_name}@${clustername}
context:
cluster: ${clustername}
namespace: ${ns}
user: ${sa_name}
users:
- name: ${sa_name}
user:
token: ${token}
current-context: ${sa_name}@${clustername}
EOF
)
config_file="${sa_name}@${clustername}"
echo "$kubeconfig_content" | tee "$config_file"
echo "Fichier kubeconfig généré : $config_file"
ServiceAccount / Cronjob
Comme le pod va acceder à l'api server, on met automountServiceAccountToken = true ou on enlève tout simplement car activé par defaut.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: alertmanager-role
namespace: cattle-monitoring-system # Should be namespace you are granting access to
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["scale", "get", "list", "watch", "create", "update", "patch"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: alertmanager-sa
namespace: cattle-monitoring-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: alertmanager-rolebinding
namespace: cattle-monitoring-system # Should be namespace you are granting access to
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: alertmanager-role # Should match name of Role
subjects:
- namespace: cattle-monitoring-system # Should match namespace where SA lives
kind: ServiceAccount
name: alertmanager-sa # Should match service account name, above
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: alertmanager-scaler-down
namespace: cattle-monitoring-system
spec:
schedule: "*/1 * * * *" # À 09h00 tous les jours
successfulJobsHistoryLimit: 0
jobTemplate:
spec:
template:
spec:
serviceAccountName: alertmanager-sa
containers:
- name: scale-down
image: bitnami/kubectl:latest # Remplacez par votre image personnalisée pour le scaling
command:
- "bash"
- "-c"
- |
kubectl patch statefulset alertmanager-rancher-monitoring-alertmanager -n cattle-monitoring-system --type json -p '[{"op": "remove", "path": "/metadata/labels/app.kubernetes.io~1managed-by"}]'
kubectl scale --replicas=0 statefulset/alertmanager-rancher-monitoring-alertmanager -n cattle-monitoring-system
restartPolicy: OnFailure
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: alertmanager-scaler-up
namespace: cattle-monitoring-system
spec:
schedule: "*/2 * * * *" # À 18h00 tous les jours
successfulJobsHistoryLimit: 0
jobTemplate:
spec:
template:
spec:
serviceAccountName: alertmanager-sa
containers:
- name: scale-up
image: bitnami/kubectl:latest # Remplacez par votre image personnalisée pour le scaling
command:
- "bash"
- "-c"
- |
kubectl scale --replicas=1 statefulset/alertmanager-rancher-monitoring-alertmanager -n cattle-monitoring-system
kubectl patch statefulset alertmanager-rancher-monitoring-alertmanager -n cattle-monitoring-system --type merge -p '{"metadata": {"labels": {"app.kubernetes.io/managed-by": "Helm"}}}'
restartPolicy: OnFailure
💡 Bonnes pratiques :
✅ Toujours appliquer le principe du moindre privilège.
✅ Toujours utiliser un serviceAccount différent du Default sa pour chaque workload. Le default sa à un accès par defaut à lapi server.
✅ Désactiver le automountServiceAccountToken pour tous les serviceAccount sauf si le l'utilisateur doit acceder à l'api server
✅ Privilégier les ClusterRoles pour des accès globaux et les Roles pour des accès spécifiques.
Commentaires
Aucun commentaire pour le moment.