CKS - Cluster Setup et Hardening
🎯 Objectifs
Tu vas maîtriser le durcissement complet d'un cluster Kubernetes :
- ✅ Implémenter un RBAC granulaire et sécurisé
- ✅ Chiffrer ETCD et les données sensibles
- ✅ Configurer les audit logs pour le compliance
- ✅ Respecter le CIS Kubernetes Benchmark
- ✅ Activer le Network Policy Controller
- ✅ Sécuriser l'accès au API Server
🔐 RBAC - Role-Based Access Control
Pourquoi RBAC ?
Imagine que tu as 100 développeurs, 10 ops, et 5 contractors. Tu ne peux pas donner à chacun les mêmes permissions. La RBAC te permet de dire : "ce développeur peut déployer dans le namespace production-frontend, mais pas toucher à production-database".
Concepts clés
Role : définit les permissions sur des ressources spécifiques dans un namespace
ClusterRole : same, mais au niveau du cluster entier
RoleBinding : lie un utilisateur/groupe à une Role
ClusterRoleBinding : lie un utilisateur/groupe à une ClusterRole
Exercice 1 : Implémenter un RBAC restrictif
Tu as 3 users : alice (dev), bob (ops), carlos (viewer).
# Role pour les devs : peuvent créer/update Deployments et Pods
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: developer
rules:
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["create", "get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["pods", "pods/logs"]
verbs: ["get", "list", "watch"]
---
# RoleBinding : lie alice au role "developer"
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: default
name: alice-developer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: developer
subjects:
- kind: User
name: alice@company.com
apiGroup: rbac.authorization.k8s.ioÀ faire :
- Crée une Role
vieweravec uniquement les permissionsget, list, watch - Bind carlos à cette role
- Teste avec
kubectl auth can-i get pods --as=carlos@company.com
🔒 ETCD Encryption at Rest
Le problème
Par défaut, ETCD stocke tout en clair : Secrets, certificats, tokens. Si quelqu'un accède au disque du control plane, il peut tout lire.
La solution
Chiffrer ETCD avec AES-256-GCM.
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
- configmaps # optionnel mais recommandé
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-bytes-key>
- identity: {} # fallback unencryptedÀ faire :
- Génère une clé de 32 bytes :
head -c 32 /dev/urandom | base64 - Insère-la dans le EncryptionConfiguration
- Redéploie le kube-apiserver avec
--encryption-provider-config - Ajoute une clé 2ème pour rotation
- Mets-à-jour les Secrets existants avec
kubectl patch secret
📋 Audit Logging
Pourquoi ?
Tu dois savoir qui a fait quoi, quand et où. Pour le compliance, pour les investigations de sécurité, pour les audits légaux.
Configuration
# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Enregistre tous les appels secrets en RequestResponse
- level: RequestResponse
verbs: ["get", "list", "create", "update", "patch", "delete"]
resources:
- group: ""
resources: ["secrets"]
# Enregistre les RoleBindings avec prise d'empreinte
- level: RequestResponse
verbs: ["*"]
resources:
- group: "rbac.authorization.k8s.io"
resources: ["clusterroles", "clusterrolebindings"]
# Enregistre tous les autres appels en RequestResponse
- level: RequestResponse
omitStages:
- RequestReceived
# Ignore les health checks
- level: None
userGroups: ["system:unauthenticated"]
omitStages:
- RequestReceivedÀ faire :
- Déploie cette policy
- Redémarrer l'apiserver
- Génère un event :
kubectl delete pod test - Lis le log d'audit :
grep "test" /var/log/pods/kube-system_kube-apiserver*/audit.log
🛡️ CIS Kubernetes Benchmark
C'est quoi ?
Un guide du Center for Internet Security (CIS) avec 200+ recommandations de sécurité pour Kubernetes. La CKS s'appuie dessus.
Les catégories principales
- Control Plane Configuration (apiserver, scheduler, controller-manager)
- Node Configuration (kubelet, worker nodes)
- Policies (RBAC, network policies, pod security)
- General Security (secrets, compliance, logging)
Outils pour vérifier
kube-bench : scan automatisé du CIS Benchmark
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs -f <pod-id>À faire :
- Installe kube-bench
- Note les 5 failures les plus critiques
- Fix les une par une (prioriser 5.1, 5.2 = RBAC et audit)
🌐 Network Policies
Pourquoi ?
Par défaut, tous les pods peuvent parler à tous les autres pods. Network Policies te permettent de créer des pare-feu au niveau des pods.
Concept clé
Une Network Policy = "par défaut DENY, puis ALLOW les exeptions spécifiques"
Exemple : Frontend peut parler au Backend, Backend peut parler à DB
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
# Tout est bloqué par défaut
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-db
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432À faire :
- Déploie 3 pods : frontend, backend, database
- Applique les Network Policies ci-dessus
- Teste : frontend peut-il accéder à database ? (non!)
- Teste : backend peut-il accéder à database ? (oui!)
📝 Checklist avant CKS
- RBAC : as-user audit, ResourceQuotas, Pod Security Standards
- ETCD : encryption at-rest activée, rotation de clé testée
- Audit logs : policy définie, logs envoyés quelque part (siem?)
- Network Policies : par défaut DENY, exceptions claires
- CIS Benchmark : 90%+ de réussite sur kube-bench
- Secret management : aucun secret en plaintext dans YAML
- API Server : --audit-log-path, --encryption-provider-config, --authorization-mode=RBAC