Que fait Audit RBAC du cluster Kubernetes ?
Quand utiliser
- Lors d'évaluations de sécurité de clusters Kubernetes (EKS, GKE, AKS ou autogérés)
- Lors de la validation que les politiques RBAC appliquent le moindre privilège pour les utilisateurs et les comptes de service
- Lors de l'investigation de mouvements latéraux potentiels ou d'escalade de privilèges au sein d'un cluster Kubernetes
- Lorsque des audits de conformité exigent une documentation des contrôles d'accès et des permissions
- Lors de l'intégration de nouvelles équipes à un cluster partagé et de la définition de politiques RBAC appropriées
Ne pas utiliser pour l'audit des politiques réseau (utiliser les outils Cilium ou Calico), pour l'analyse d'images conteneurisées (utiliser Trivy ou Grype), ou pour la surveillance de sécurité au moment de l'exécution (utiliser Falco ou Sysdig Secure).
Prérequis
- kubectl configuré avec les permissions cluster-admin ou des permissions de lecture équivalentes sur le cluster cible
- rbac-tool installé (
kubectl krew install rbac-toolou binaire depuis GitHub) - KubiScan installé (
pip install kubiscan) - Kubeaudit installé (
brew install kubeauditou depuis les releases GitHub) - Accès aux journaux d'audit du cluster pour corréler les résultats RBAC avec les accès API réels
Workflow
Étape 1 : Énumérer les ClusterRoles et Roles avec des permissions dangereuses
Identifier les rôles avec des permissions wildcard, un accès aux secrets, pod exec ou des capacités d'escalade.
# Lister tous les ClusterRoles avec un accès verbe wildcard
kubectl get clusterroles -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for role in data['items']:
name = role['metadata']['name']
for rule in role.get('rules', []):
verbs = rule.get('verbs', [])
resources = rule.get('resources', [])
if '*' in verbs or '*' in resources:
print(f'ClusterRole : {name}')
print(f' Verbes : {verbs}')
print(f' Ressources : {resources}')
print(f' Groupes API : {rule.get(\"apiGroups\", [])}')
print()
"
# Trouver les rôles pouvant lire les secrets
kubectl get clusterroles -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for role in data['items']:
name = role['metadata']['name']
for rule in role.get('rules', []):
resources = rule.get('resources', [])
verbs = rule.get('verbs', [])
if ('secrets' in resources or '*' in resources) and ('get' in verbs or 'list' in verbs or '*' in verbs):
if not name.startswith('system:'):
print(f'ClusterRole : {name} -> peut accéder aux secrets (verbes : {verbs})')
"
# Trouver les rôles avec permissions pod/exec (risque d'évasion de conteneur)
kubectl get clusterroles -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for role in data['items']:
name = role['metadata']['name']
for rule in role.get('rules', []):
resources = rule.get('resources', [])
if 'pods/exec' in resources or 'pods/*' in resources:
print(f'ClusterRole : {name} -> a accès pods/exec')
"
Étape 2 : Auditer les ClusterRoleBindings et RoleBindings
Examiner les liaisons pour identifier qui a un accès élevé et détecter les attributions de groupes trop larges.
# Lister tous les ClusterRoleBindings avec leurs sujets
kubectl get clusterrolebindings -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for binding in data['items']:
name = binding['metadata']['name']
role = binding['roleRef']['name']
subjects = binding.get('subjects', [])
for subject in subjects:
kind = subject.get('kind', '')
subj_name = subject.get('name', '')
ns = subject.get('namespace', 'cluster-wide')
print(f'{name} -> Rôle : {role} | {kind} : {subj_name} ({ns})')
" | sort
# Trouver les liaisons à cluster-admin
kubectl get clusterrolebindings -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for binding in data['items']:
if binding['roleRef']['name'] == 'cluster-admin':
print(f\"Liaison : {binding['metadata']['name']}\")
for subject in binding.get('subjects', []):
print(f\" {subject.get('kind')} : {subject.get('name')} (ns : {subject.get('namespace', 'N/A')})\")
"
# Trouver les liaisons accordant l'accès à tous les utilisateurs authentifiés
kubectl get clusterrolebindings -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for binding in data['items']:
for subject in binding.get('subjects', []):
if subject.get('name') in ['system:authenticated', 'system:unauthenticated']:
print(f\"ATTENTION : {binding['metadata']['name']} accorde {binding['roleRef']['name']} à {subject['name']}\")
"
Étape 3 : Analyser avec rbac-tool pour une analyse complète
Utiliser rbac-tool pour une analyse RBAC automatisée, incluant les requêtes who-can et la génération de politiques.
# Qui peut get des secrets dans tous les namespaces
kubectl rbac-tool who-can get secrets
# Qui peut créer des pods (risque d'évasion de conteneur)
kubectl rbac-tool who-can create pods
# Qui peut exec dans les pods
kubectl rbac-tool who-can create pods/exec
# Qui peut escalader les privilèges (verbes bind/escalate)
kubectl rbac-tool who-can bind clusterroles
kubectl rbac-tool who-can escalate clusterroles
# Générer un rapport de politique RBAC
kubectl rbac-tool analysis
# Visualiser les relations RBAC
kubectl rbac-tool viz --outformat dot > rbac-graphe.dot
dot -Tpng rbac-graphe.dot -o rbac-graphe.png
Étape 4 : Exécuter KubiScan pour la détection des permissions risquées
Utiliser KubiScan pour identifier automatiquement les comptes de service, pods et configurations RBAC risqués.
# Exécuter KubiScan pour trouver les rôles risqués
python3 -m kubiscan -rroles # Lister les Roles risqués
python3 -m kubiscan -rcr # Lister les ClusterRoles risqués
python3 -m kubiscan -rrb # Lister les RoleBindings risqués
python3 -m kubiscan -rcrb # Lister les ClusterRoleBindings risqués
# Trouver les comptes de service risqués
python3 -m kubiscan -rs # Comptes de service risqués
# Trouver les pods exécutés avec des comptes de service risqués
python3 -m kubiscan -rp # Pods risqués
# Vérifier les chemins d'escalade de privilèges
python3 -m kubiscan -pe # Vecteurs d'escalade de privilèges
# Générer un rapport complet
python3 -m kubiscan -a # Toutes les vérifications
Étape 5 : Auditer le montage et l'utilisation des tokens des comptes de service
Vérifier les montages inutiles de tokens de comptes de service qui pourraient permettre un mouvement latéral à partir de pods compromis.
# Trouver les pods avec montage automatique de token de compte de service
kubectl get pods --all-namespaces -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for pod in data['items']:
name = pod['metadata']['name']
ns = pod['metadata']['namespace']
sa = pod['spec'].get('serviceAccountName', 'default')
automount = pod['spec'].get('automountServiceAccountToken', True)
if automount and sa != 'default':
print(f'{ns}/{name} -> SA : {sa} (token monté automatiquement)')
"
# Trouver les comptes de service avec des secrets de token non par défaut
kubectl get serviceaccounts --all-namespaces -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for sa in data['items']:
name = sa['metadata']['name']
ns = sa['metadata']['namespace']
secrets = sa.get('secrets', [])
if name != 'default' and len(secrets) > 0:
print(f'{ns}/{name} : {len(secrets)} secret(s) lié(s)')
"
# Vérifier les pods exécutés en mode privilégié ou avec accès hôte
kubectl get pods --all-namespaces -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for pod in data['items']:
name = pod['metadata']['name']
ns = pod['metadata']['namespace']
for container in pod['spec'].get('containers', []):
sc = container.get('securityContext', {})
if sc.get('privileged', False) or sc.get('runAsUser', 1) == 0:
print(f'RISQUE : {ns}/{name}/{container[\"name\"]} - privilégié={sc.get(\"privileged\",False)} runAsRoot={sc.get(\"runAsUser\",\"non défini\")==0}')
"
Étape 6 : Exécuter Kubeaudit pour la validation RBAC et des politiques de sécurité
Exécuter Kubeaudit pour des vérifications de sécurité complètes, y compris les résultats liés au RBAC.
# Exécuter toutes les vérifications kubeaudit
kubeaudit all --kubeconfig ~/.kube/config
# Exécuter des vérifications spécifiques liées au RBAC
kubeaudit privesc # Vérifier allowPrivilegeEscalation
kubeaudit rootfs # Vérifier readOnlyRootFilesystem
kubeaudit nonroot # Vérifier runAsNonRoot
kubeaudit capabilities # Vérifier les capabilities dangereuses
# Sortie au format JSON pour traitement
kubeaudit all --kubeconfig ~/.kube/config -f json > kubeaudit-resultats.json
Concepts clés
| Terme | Définition |
|---|---|
| RBAC | Contrôle d'accès basé sur les rôles dans Kubernetes, méthode de régulation de l'accès aux ressources du cluster en fonction des rôles des utilisateurs ou des comptes de service |
| ClusterRole | Définition de rôle à l'échelle du cluster qui spécifie les permissions (verbes sur les ressources) applicables à tous les namespaces |
| ClusterRoleBinding | Associe un ClusterRole à des sujets (utilisateurs, groupes, comptes de service) au niveau du cluster |
| Service Account | Identité associée aux pods pour s'authentifier auprès du serveur API Kubernetes, montée automatiquement sauf si désactivée |
| automountServiceAccountToken | Champ de spécification du pod contrôlant si le token du compte de service est automatiquement monté dans le système de fichiers du pod |
| Escalade de privilèges | Verbes RBAC (bind, escalate, impersonate) qui permettent à un utilisateur de s'accorder ou d'accorder à d'autres des permissions élevées |
Outils & systèmes
- kubectl: CLI principal pour interroger les ressources RBAC Kubernetes (rôles, liaisons, comptes de service)
- rbac-tool: Plugin kubectl pour l'analyse RBAC, incluant les requêtes who-can, la visualisation et la génération de politiques
- KubiScan: Outil Python pour analyser le RBAC Kubernetes à la recherche de permissions risquées et de chemins d'escalade de privilèges
- Kubeaudit: Outil d'audit de sécurité qui vérifie les pods et les charges de travail pour détecter les anti-patrons de sécurité, y compris les problèmes RBAC
- rakkess: Plugin kubectl affichant la matrice d'accès pour l'utilisateur actuel sur tous les types de ressources
Scénarios courants
Scénario : Auditer un cluster EKS partagé par plusieurs équipes de développement
Contexte : Un cluster EKS partagé dessert quatre équipes de développement. Le RBAC a été configuré lors de la configuration initiale mais n'a pas été revu depuis 12 mois. Les équipes signalent pouvoir accéder aux namespaces des autres équipes.
Approche :
- Lister tous les ClusterRoleBindings pour identifier les liaisons accordant un accès large aux utilisateurs authentifiés
- Exécuter
kubectl rbac-tool who-can get secretspour trouver les sujets pouvant lire les secrets dans tous les namespaces - Découvrir qu'un ClusterRoleBinding accorde
editàsystem:authenticated, donnant à tous les utilisateurs un accès en écriture à l'échelle du cluster - Exécuter KubiScan pour identifier les comptes de service avec des permissions risquées et les pods exécutés avec des comptes de service élevés
- Remplacer le ClusterRoleBinding par des RoleBindings limités au namespace pour chaque équipe
- Désactiver automountServiceAccountToken pour les charges de travail qui n'ont pas besoin d'accès API
- Créer une NetworkPolicy pour isoler le trafic des namespaces entre les équipes
Pièges : La suppression de ClusterRoleBindings peut casser les pipelines CI/CD et les opérateurs qui dépendent d'un accès à l'échelle du cluster. Toujours auditer quelles charges de travail utilisent les liaisons avant de les supprimer. EKS mappe les rôles IAM aux groupes Kubernetes via la ConfigMap aws-auth, donc les modifications RBAC doivent être coordonnées avec les mappings de rôles IAM.
Format de sortie
Rapport d'audit RBAC Kubernetes
=================================
Cluster : production-eks (EKS 1.28)
Date d'audit : 2026-02-23
Namespaces : 12
INVENTAIRE RBAC :
ClusterRoles : 48 (18 personnalisés, 30 système)
ClusterRoleBindings : 32 (12 personnalisées, 20 système)
Roles (par namespace) : 24
RoleBindings (par namespace) : 36
Comptes de service : 67
CONSTATATIONS CRITIQUES :
[RBAC-001] ClusterRoleBinding accorde edit à system:authenticated
Liaison : authenticated-edit
Effet : TOUS les utilisateurs authentifiés ont un accès en édition à TOUS les namespaces
Risque : Tout utilisateur peut modifier des ressources dans n'importe quel namespace
Correction : Remplacer par des RoleBindings limités au namespace par équipe
[RBAC-002] ClusterRole personnalisé avec permissions wildcard
ClusterRole : developer-admin
Règles : verbes=["*"], ressources=["*"], apiGroups=["*"]
Liaisons : 4 utilisateurs via developer-admin-binding
Risque : Équivalent à cluster-admin sans le nom
Correction : Limiter aux ressources et verbes spécifiques nécessaires
RÉSUMÉ :
Entités avec cluster-admin : 6 (recommandé : <= 3)
Rôles avec permissions wildcard : 4
Comptes de service avec accès aux secrets : 12
Pods avec tokens montés automatiquement : 45 / 67
Conteneurs privilégiés : 8