## Introduction

Le contrôle d'accès basé sur les rôles (RBAC) de Kubernetes est le principal mécanisme de régulation des accès aux ressources du cluster. Alors que les rôles (Roles) et les liaisons de rôles (RoleBindings) limitent les autorisations à un seul espace de noms, les rôles de cluster (ClusterRoles) et les liaisons de rôles de cluster (ClusterRoleBindings) accordent des autorisations sur l'ensemble du cluster. Une seule ClusterRoleBinding trop permissive peut exposer des ressources sensibles, permettre une élévation de privilèges ou conduire à une compromission totale du cluster.

Ce guide se concentre sur les étapes pratiques pour renforcer les ClusterRoleBindings. Vous apprendrez à évaluer les liaisons existantes, à appliquer les principes du moindre privilège, à vérifier les modifications et à récupérer en cas d'erreur. Chaque section comprend des commandes concrètes et des exemples de configuration que vous pouvez exécuter dans votre propre environnement, qu'il s'agisse d'un cluster de développement local, d'une offre cloud gérée comme EKS ou GKE, ou d'un système de production sur site.

Nous supposons que vous avez une connaissance de base des concepts Kubernetes tels que les pods, les espaces de noms et les comptes de service. Si vous débutez avec RBAC, la documentation officielle de Kubernetes fournit une bonne base. Cet article va au-delà des notions de base pour montrer des techniques de durcissement concrètes souvent négligées.

## Inventaire de la version et de l'environnement

Avant d'apporter des modifications, vous devez avoir une image claire de votre cluster et des outils disponibles. Cette section liste les prérequis et montre comment recueillir les informations de version et l'état actuel de RBAC.

### Prérequis

- Un cluster Kubernetes en cours d'exécution (version 1.19 ou ultérieure recommandée ; RBAC est stable depuis la v1 et l'API `rbac.authorization.k8s.io/v1` est disponible depuis la 1.8).
- L'outil en ligne de commande `kubectl` configuré avec des privilèges cluster-admin ou suffisants pour afficher et modifier les objets RBAC.
- `jq` (facultatif mais fortement recommandé pour traiter la sortie JSON).
- Accès aux journaux d'audit, si disponibles, pour le diagnostic.

### Vérifier les versions de Kubernetes et de kubectl

Exécutez la commande suivante pour voir les versions du client et du serveur :

```bash
kubectl version --short
```

Exemple de sortie :

```
Client Version: v1.25.3
Server Version: v1.25.3
```

Si la version de votre cluster est antérieure à 1.19, certains champs de l'API peuvent différer. Les exemples de ce guide utilisent `rbac.authorization.k8s.io/v1`, qui est stable depuis Kubernetes 1.8.

### Lister les ClusterRoleBindings existantes

Pour voir toutes les liaisons de rôles à l'échelle du cluster :

```bash
kubectl get clusterrolebindings
```

Cela liste chaque liaison, y compris celles par défaut comme `cluster-admin` et diverses liaisons `system:*`. Notez celles qui ne font pas partie de l'ensemble par défaut. Les liaisons personnalisées créées par des utilisateurs ou des outils tiers ont souvent des noms comme `my-app-binding` ou `developer-access`.

### Vérifier les ressources API pour RBAC

Confirmez que le groupe d'API RBAC est disponible :

```bash
kubectl api-resources | grep rbac
```

La sortie attendue inclut `clusterrolebindings`, `clusterroles`, `roles` et `rolebindings` sous le groupe `rbac.authorization.k8s.io`.

### Capturer l'état actuel

Avant de modifier quoi que ce soit, créez une sauvegarde de toutes les ClusterRoleBindings. C'est crucial pour la récupération.

```bash
kubectl get clusterrolebindings -o yaml > clusterrolebindings-backup-$(date +%Y%m%d).yaml
```

Stockez ce fichier dans un dépôt sous contrôle de version ou un emplacement sécurisé. Vous vous en remercierez plus tard si quelque chose tourne mal.

## Chemin de configuration sécurisé

Cette section fournit une approche étape par étape pour renforcer les ClusterRoleBindings. Nous commençons par examiner les liaisons existantes, puis appliquons des modifications de moindre privilège, et enfin vérifions les résultats.

### Étape 1 : Identifier les liaisons trop permissives

La ClusterRoleBinding intégrée `cluster-admin` accorde des droits de superutilisateur à tout sujet lié. Elle est souvent liée au compte de service par défaut dans l'espace de noms `kube-system` ou à un utilisateur générique. Vérifiez qui a cette liaison :

```bash
kubectl get clusterrolebinding cluster-admin -o yaml
```

Examinez le champ `subjects`. Par exemple, si vous voyez un compte de service de l'espace de noms `default`, c'est un signal d'alarme. La sortie pourrait inclure :

```yaml
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
```

Cela signifie que tout pod s'exécutant avec le compte de service par défaut dans l'espace de noms `default` peut effectuer n'importe quelle action dans le cluster. Ce n'est presque certainement pas intentionnel.

Listez également toutes les liaisons qui référencent le ClusterRole `cluster-admin` :

```bash
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name == "cluster-admin") | .metadata.name'
```

Examinez chaque résultat. Certains peuvent être légitimes, comme une liaison admin de secours, mais chacun doit être justifié.

### Étape 2 : Utiliser des rôles plus spécifiques

Au lieu de lier les utilisateurs à `cluster-admin`, créez ou utilisez des ClusterRoles plus restreints. Par exemple, un utilisateur qui a seulement besoin de voir les nœuds peut être lié à un rôle personnalisé :

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-viewer
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]
```

Créez le rôle :

```bash
kubectl apply -f node-viewer-clusterrole.yaml
```

Créez ensuite une ClusterRoleBinding qui lie ce rôle à un utilisateur ou un groupe spécifique :

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: node-viewer-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: node-viewer
subjects:
- kind: User
  name: jane@example.com
  apiGroup: rbac.authorization.k8s.io
```

Appliquez-la :

```bash
kubectl apply -f node-viewer-binding.yaml
```

Maintenant, `jane@example.com` peut lister les nœuds mais ne peut pas les modifier ni accéder à d'autres ressources.

De même, si un utilisateur a besoin d'un accès en lecture seule aux pods dans tous les espaces de noms, créez un ClusterRole `pod-reader` avec les verbes `get`, `list` et `watch` sur les `pods`, et liez-le en conséquence.

### Étape 3 : Auditer les liaisons de comptes de service

Les comptes de service sont souvent sur-privilégiés car les paramètres par défaut peuvent accorder un accès large, ou les applications peuvent demander plus que nécessaire. Vérifiez tous les comptes de service liés à des rôles de cluster :

```bash
kubectl get clusterrolebindings -o json | jq '.items[] | select(.subjects[]?.kind == "ServiceAccount") | .metadata.name'
```

Pour chaque liaison, inspectez les détails :

```bash
kubectl get clusterrolebinding <binding-name> -o yaml
```

Posez ces questions :

- Le compte de service a-t-il vraiment besoin d'autorisations à l'échelle du cluster, ou une RoleBinding dans un espace de noms spécifique suffirait-elle ?
- Si l'accès à l'échelle du cluster est nécessaire, le rôle est-il limité aux ressources et verbes nécessaires ?
- Le compte de service est-il encore utilisé ? Vérifiez les déploiements et statefulsets qui le référencent : `kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.serviceAccountName == "<sa-name>") | .metadata.name'`

Réduisez les autorisations lorsque c'est possible. Par exemple, si un compte de service a seulement besoin de lire les configmaps dans l'espace de noms `kube-system`, utilisez une Role et une RoleBinding au lieu d'une ClusterRoleBinding.

### Étape 4 : Supprimer les liaisons inutilisées

Listez les liaisons triées par date de création pour trouver celles qui sont anciennes ou inutilisées :

```bash
kubectl get clusterrolebindings --sort-by=.metadata.creationTimestamp
```

Les liaisons plus anciennes sont candidates à la suppression. Avant de supprimer, vérifiez qu'elles ne sont référencées par aucun sujet actif. Pour les liaisons d'utilisateurs, vérifiez si l'utilisateur existe toujours dans votre fournisseur d'identité. Pour les comptes de service, vérifiez si des charges de travail les utilisent (comme indiqué ci-dessus).

Supprimez celles qui ne sont plus nécessaires :

```bash
kubectl delete clusterrolebinding unused-binding-name
```

### Étape 5 : Utiliser des groupes au lieu d'utilisateurs individuels

Lier des rôles à des groupes simplifie la gestion. Au lieu de créer une liaison pour chaque utilisateur, liez un rôle à un groupe et gérez l'appartenance au groupe dans votre fournisseur d'identité (par exemple, Active Directory, LDAP, OIDC).

Exemple de ClusterRoleBinding pour un groupe de développeurs :

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: developer-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: developer-cluster-role
subjects:
- kind: Group
  name: developers
  apiGroup: rbac.authorization.k8s.io
```

Cela lie tous les membres du groupe `developers` au `developer-cluster-role`, qui devrait être limité aux tâches typiques des développeurs comme créer des déploiements, consulter les journaux et accéder aux configmaps. Lorsqu'un développeur part, retirez-le du groupe ; aucune modification du cluster n'est nécessaire.

### Étape 6 : Limiter l'utilisation des caractères génériques

Les caractères génériques (`*`) dans les règles RBAC sont dangereux. Évitez-les autant que possible. Par exemple, une règle comme :

```yaml
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]
```

accorde un accès total à toutes les ressources, ce qui équivaut effectivement à cluster-admin. Même un caractère générique apparemment limité peut être risqué : `resources: ["*"]` inclut les ressources futures qui pourraient être ajoutées au cluster, élargissant potentiellement l'accès involontairement.

Au lieu de cela, listez explicitement les groupes API, les ressources et les verbes nécessaires. Si vous devez utiliser un caractère générique, restreignez-le à un groupe API ou un type de ressource spécifique et documentez la justification.

## Vérification et diagnostic

Après avoir appliqué les modifications, vérifiez que les autorisations correspondent à l'intention et qu'aucun accès non intentionnel n'est accordé.

### Vérifier les autorisations effectives

Utilisez `kubectl auth can-i` pour tester les autorisations d'un utilisateur ou d'un compte de service. Par exemple, vérifiez si l'utilisateur `jane@example.com` peut lister les pods :

```bash
kubectl auth can-i list pods --as jane@example.com
```

Sortie attendue : `yes` ou `no`.

Pour un compte de service, utilisez l'option `--as` avec le nom complet :

```bash
kubectl auth can-i get nodes --as=system:serviceaccount:default:my-sa
```

Vous pouvez également tester des verbes spécifiques sur des ressources spécifiques :

```bash
kubectl auth can-i create deployments --as jane@example.com --namespace my-namespace
```

Pour lister toutes les autorisations d'un sujet, utilisez `--list` :

```bash
kubectl auth can-i --list --as jane@example.com
```

Cela affiche un tableau des ressources et des verbes autorisés.

### Lister tous les rôles pour un sujet

Il n'y a pas de commande directe pour lister tous les rôles d'un sujet, mais vous pouvez utiliser `kubectl` et `jq` pour extraire les liaisons d'un utilisateur ou d'un groupe spécifique. Exemple pour l'utilisateur `jane@example.com` :

```bash
kubectl get clusterrolebindings -o json | jq '.items[] | select(.subjects[]?.kind == "User" and .name == "jane@example.com") | .roleRef.name'
```

Pour un compte de service, remplacez le type et le nom du sujet en conséquence. Vérifiez également les RoleBindings dans les espaces de noms pertinents, car elles sont distinctes.

### Examiner les journaux d'audit

Si la journalisation d'audit est activée, vérifiez les journaux pour les demandes refusées qui pourraient indiquer des autorisations trop restrictives ou des tentatives d'attaque potentielles. Recherchez les entrées avec `responseStatus.code` dans la plage 403 et `user.name` correspondant au sujet concerné.

La plupart des services Kubernetes gérés fournissent des journaux d'audit. Pour les clusters autogérés, assurez-vous que la politique d'audit inclut les événements liés à RBAC. Exemple d'extrait de politique d'audit :

```yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  verbs: ["create", "update", "patch", "delete"]
  resources:
  - group: "rbac.authorization.k8s.io"
    resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"]
```

### Exécuter un outil d'audit RBAC

Des outils comme `kubescape` ou `kube-bench` peuvent analyser les configurations RBAC trop permissives. Exemple avec `kubescape` :

```bash
kubescape scan framework nsa --exclude-namespaces kube-system
```

Examinez les résultats liés à RBAC. `kubescape` signale les règles qui accordent des autorisations excessives et suggère des remédiations.

## Modes de défaillance et récupération

Des erreurs dans les ClusterRoleBindings peuvent verrouiller des utilisateurs ou casser des applications. Cette section couvre les modes de défaillance courants et comment récupérer.

### Suppression accidentelle de l'accès administrateur

Si vous supprimez ou modifiez la liaison `cluster-admin` et vous verrouillez, la récupération dépend d'un autre chemin d'accès admin.

**Prévention :** Maintenez au moins un compte admin d'urgence qui ne fait pas partie des liaisons par défaut. Par exemple, créez un compte de service dédié `break-glass-admin` dans un espace de noms sécurisé, liez-le à `cluster-admin`, et stockez ses identifiants dans un secret scellé ou un gestionnaire de mots de passe avec accès limité. Utilisez-le uniquement en cas d'urgence. Examinez son utilisation chaque trimestre. Le responsable de la sécurité de la plateforme (par exemple, Priya Shah, ingénieure en chef) possède ce compte et doit s'assurer qu'il est renouvelé tous les 90 jours.

**Récupération :** Si vous êtes verrouillé et n'avez pas de compte d'urgence, utilisez l'accès d'urgence du fournisseur cloud ou de l'infrastructure. Pour les clusters gérés (EKS, GKE, AKS), vous pouvez souvent utiliser l'IAM cloud pour réinitialiser le rôle d'admin du cluster. Pour les clusters sur site, vous devrez peut-être accéder à la sauvegarde etcd ou utiliser un fichier de jetons statiques. Ayez toujours une procédure documentée.

### Liaison trop permissive conduisant à un incident de sécurité

Si une liaison est trop large et qu'une violation se produit, révoquez immédiatement la liaison :

```bash
kubectl delete clusterrolebinding over-permissive-binding
```

Ensuite, enquêtez sur l'étendue : vérifiez les journaux d'audit pour les actions effectuées par le sujet compromis, inspectez les pods et les charges de travail pour les modifications non autorisées, et renouvelez les secrets qui ont pu être exposés.

Après l'incident, effectuez une analyse des causes profondes avec l'équipe de sécurité et mettez à jour les politiques RBAC.

### Le compte de service d'une application perd des autorisations nécessaires

Si une application commence à échouer avec `403 Forbidden`, vérifiez les liaisons du compte de service.

```bash
kubectl describe clusterrolebinding <binding-name>
```

Les journaux d'audit peuvent montrer les demandes refusées. Recherchez `responseStatus.code: 403` et `serviceAccountName` dans la demande.

Restaurez les autorisations nécessaires en appliquant la liaison correcte ou en ajoutant le verbe manquant. Testez avec `kubectl auth can-i --as=system:serviceaccount:<namespace>:<sa> <verb> <resource>` avant de redéployer.

### Stratégie de restauration

Sauvegardez toujours les liaisons existantes avant de faire des modifications, comme décrit dans l'étape de capture. Pour restaurer une liaison spécifique à partir du fichier de sauvegarde, extrayez-la avec `kubectl` en utilisant un filtre ou modifiez manuellement le YAML.

Exemple avec `yq` (si installé) :

```bash
yq eval 'select(.metadata.name == "my-binding")' clusterrolebindings-backup-20240101.yaml | kubectl apply -f -
```

Si vous n'avez pas `yq`, utilisez `kubectl get -f` avec un sélecteur d'étiquette, ou ouvrez le fichier de sauvegarde et copiez l'objet pertinent.

Soyez prudent : appliquer toute la sauvegarde peut réintroduire des liaisons indésirables. Ne restaurez que les objets spécifiques dont vous avez besoin.

## Pièges courants et comment les éviter

Au-delà des modes de défaillance ci-dessus, voici des erreurs récurrentes que les équipes commettent avec les ClusterRoleBindings et comment les prévenir.

### 1. Utiliser une ClusterRoleBinding quand une RoleBinding d'espace de noms suffirait

**Piège :** Les développeurs demandent souvent un accès à l'échelle du cluster parce que c'est plus facile que de déterminer les espaces de noms exacts nécessaires. Cela élargit inutilement la surface d'attaque.

**Pourquoi cela arrive :** Manque de connaissance des objets RBAC d'espace de noms, ou outils par défaut qui encouragent les rôles à l'échelle du cluster.

**Évitement :** Avant de créer une ClusterRoleBinding, demandez : « Ce sujet a-t-il besoin d'un accès dans tous les espaces de noms ? » Si seulement quelques espaces de noms sont nécessaires, utilisez une Role et une RoleBinding dans chaque espace de noms, ou utilisez un ClusterRole avec une RoleBinding pour accorder des autorisations à l'échelle du cluster dans un seul espace de noms.

**Récupération :** Convertissez la ClusterRoleBinding en RoleBinding et supprimez la liaison à l'échelle du cluster. Testez avec `kubectl auth can-i` pour les espaces de noms spécifiques.

### 2. Usage excessif des caractères génériques

**Piège :** Utiliser `*` pour apiGroups, ressources ou verbes est pratique mais dangereux. Cela accorde souvent des autorisations dont le sujet n'a pas besoin, y compris l'accès aux ressources futures.

**Pourquoi cela arrive :** Pression temporelle, manque de connaissances RBAC, ou copie d'exemples trouvés sur Internet.

**Évitement :** Listez explicitement les ressources et verbes requis. Utilisez des outils comme `kubectl auth can-i --list` pour déterminer l'ensemble minimal nécessaire. Appliquez des politiques avec OPA ou Kyverno qui rejettent les règles avec caractères génériques en production.

**Récupération :** Remplacez les règles avec caractères génériques par des listes explicites. Testez soigneusement pour vous assurer que l'application fonctionne toujours.

### 3. Oublier de supprimer les liaisons pour les utilisateurs partis

**Piège :** Lorsqu'un utilisateur quitte l'organisation, sa liaison reste, permettant potentiellement un accès non autorisé si ses identifiants sont compromis.

**Pourquoi cela arrive :** Les processus de départ manuels oublient souvent le nettoyage RBAC, surtout pour les liaisons à l'échelle du cluster qui ne sont pas visibles dans les tableaux de bord d'espace de noms.

**Évitement :** Intégrez le nettoyage RBAC dans la liste de contrôle de départ. Utilisez des liaisons de groupe pour que retirer un utilisateur d'un groupe révoque automatiquement l'accès. L'équipe de sécurité informatique doit gérer l'appartenance aux groupes dans le fournisseur d'identité.

**Récupération :** Auditez régulièrement les liaisons pour les utilisateurs inactifs. Vous pouvez écrire un script qui compare les sujets utilisateurs avec votre système RH.

### 4. Liaison au compte de service par défaut

**Piège :** Lier un rôle de cluster au compte de service par défaut dans un espace de noms signifie que chaque pod de cet espace hérite des autorisations à moins que `automountServiceAccountToken` ne soit désactivé. C'est une erreur courante lorsque les développeurs veulent donner à un pod unique des autorisations supplémentaires.

**Pourquoi cela arrive :** Le compte de service par défaut est facile à référencer, et les utilisateurs novices peuvent ne pas réaliser l'implication.

**Évitement :** Créez toujours un compte de service dédié pour les charges de travail qui ont besoin d'autorisations spécifiques, et liez le rôle à ce compte de service uniquement. Désactivez le montage automatique des jetons de compte de service dans les pods qui n'ont pas besoin d'accéder à l'API Kubernetes.

**Récupération :** Supprimez la liaison du compte de service par défaut, créez un nouveau compte de service pour la charge de travail, et mettez à jour le déploiement pour l'utiliser. Testez avec `kubectl auth can-i`.

### 5. Ne pas examiner les installations tierces

**Piège :** Les charts Helm ou les opérateurs peuvent installer des ClusterRoleBindings avec des autorisations excessives. La liaison `cluster-admin` est parfois incluse par défaut.

**Pourquoi cela arrive :** Les fournisseurs privilégient la facilité d'installation par rapport aux meilleures pratiques de sécurité.

**Évitement :** Avant l'installation, inspectez les manifestes RBAC du chart. Utilisez `helm template` pour prévisualiser les ressources. Après l'installation, auditez toutes les nouvelles ClusterRoleBindings et ajustez si nécessaire.

**Récupération :** Si vous trouvez une liaison trop permissive d'une installation tierce, contactez le fournisseur ou modifiez la liaison pour utiliser un rôle plus limité si possible. Certains outils peuvent ne pas fonctionner correctement avec des autorisations réduites, donc testez d'abord dans un environnement de préproduction.

## Liste de contrôle des opérations

Utilisez cette liste de contrôle régulièrement (par exemple, mensuellement ou après des changements majeurs) pour maintenir la sécurité des ClusterRoleBindings. Le responsable de la sécurité de la plateforme (par exemple, Priya Shah, ingénieure en chef) possède cette liste et la révise tous les 30 jours.

| Tâche | Commande / Action |
|------|------------------|
| Lister toutes les ClusterRoleBindings | `kubectl get clusterrolebindings` |
| Identifier les sujets avec cluster-admin | `kubectl get clusterrolebinding cluster-admin -o yaml` |
| Vérifier les comptes de service liés aux rôles de cluster | `kubectl get clusterrolebindings -o json \| jq '.items[] \| select(.subjects[]?.kind == "ServiceAccount") \| .metadata.name'` |
| Supprimer les liaisons inutilisées | Examiner la liste et supprimer avec `kubectl delete clusterrolebinding <name>` |
| Tester les autorisations utilisateur | `kubectl auth can-i --list --as=<user>` |
| Sauvegarder les liaisons actuelles | `kubectl get clusterrolebindings -o yaml > clusterrolebindings-backup.yaml` |
| Examiner les journaux d'audit pour les demandes refusées | Vérifier les journaux d'audit pour les erreurs 403 et les accès inattendus |
| Exécuter un scanner RBAC automatisé | `kubescape scan framework nsa` |
| Examiner le compte admin d'urgence | Vérifier la dernière utilisation et renouveler les identifiants si nécessaire |
| Inspecter les liaisons tierces | `kubectl get clusterrolebindings -l app.kubernetes.io/managed-by=Helm` |

## Conclusion

Renforcer les ClusterRoleBindings Kubernetes est essentiel pour la sécurité du cluster. En suivant les étapes de ce guide, vous pouvez réduire la surface d'attaque, appliquer le moindre privilège et maintenir un inventaire clair de qui peut faire quoi dans le cluster.

Commencez par auditer vos liaisons actuelles, puis appliquez les modifications de configuration sécurisées décrites. Vérifiez toujours les autorisations avec `kubectl auth can-i` et ayez un plan de restauration. Utilisez la liste de contrôle des opérations régulièrement pour garder votre cluster sécurisé au fil du temps. N'oubliez pas que RBAC est un processus continu : révisez les autorisations chaque trimestre, adaptez-vous aux nouvelles charges de travail et restez informé des meilleures pratiques de sécurité Kubernetes.