TP 18 : Micro-segmentation et Sécurité des Réseaux Kubernetes
Module : 5 – NetSecDevOps et Sécurité Automatisée
Durée indicative : 2h
Prérequis : un cluster Kubernetes local avec CNI supportant les NetworkPolicy (voir fichier d’environnement), kubectl, Python 3, pip install kubernetes
Objectifs
- Déployer des microservices de test dans des espaces de noms dédiés.
- Appliquer une politique default deny puis des autorisations ciblées.
- Générer des
NetworkPolicypar programmation avec le client Python Kubernetes.
Contexte
Vous sécurisez une petite architecture de microservices (frontend, backend, database) en n’autorisant que les flux strictement nécessaires entre eux.
Étape 1 – Déploiement des microservices de test
kubectl create namespace demo-app
kubectl -n demo-app run frontend --image=nginx --labels="app=frontend"
kubectl -n demo-app run backend --image=nginx --labels="app=backend"
kubectl -n demo-app run database --image=nginx --labels="app=database"
kubectl -n demo-app expose pod frontend --port=80
kubectl -n demo-app expose pod backend --port=80
kubectl -n demo-app expose pod database --port=80Étape 2 – Vérification de l’absence de restriction
kubectl -n demo-app exec frontend -- curl -s -o /dev/null -w "%{http_code}\n" http://databaseÀ ce stade, tous les pods se joignent librement (200 attendu partout).
Étape 3 – Politique default deny
# default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: demo-app
spec:
podSelector: {}
policyTypes: [Ingress, Egress]kubectl apply -f default-deny.yaml
kubectl -n demo-app exec frontend -- curl -s -o /dev/null -w "%{http_code}\n" http://databaseLe second appel doit désormais échouer (timeout).
Étape 4 – Autorisations ciblées
# allow-frontend-to-backend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: demo-app
spec:
podSelector:
matchLabels: {app: backend}
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels: {app: frontend}Créez de la même façon allow-backend-to-database.yaml (seul backend peut joindre database).
Étape 5 – Génération programmatique avec le client Python
from kubernetes import client, config
config.load_kube_config()
net_v1 = client.NetworkingV1Api()
policy = client.V1NetworkPolicy(
metadata=client.V1ObjectMeta(name="allow-backend-to-database", namespace="demo-app"),
spec=client.V1NetworkPolicySpec(
pod_selector=client.V1LabelSelector(match_labels={"app": "database"}),
policy_types=["Ingress"],
ingress=[client.V1NetworkPolicyIngressRule(
_from=[client.V1NetworkPolicyPeer(
pod_selector=client.V1LabelSelector(match_labels={"app": "backend"})
)]
)]
)
)
net_v1.create_namespaced_network_policy(namespace="demo-app", body=policy)Étape 6 – Validation complète
Seuls frontend→backend et backend→database sont autorisés ; database n’initie aucune connexion.
Vérifiez la matrice de flux attendue :
| Source \ Destination | frontend | backend | database |
|---|---|---|---|
| frontend | - | ✅ | ❌ |
| backend | ❌ | - | ✅ |
| database | ❌ | ❌ | - |
kubectl -n demo-app exec frontend -- curl -s -o /dev/null -w "%{http_code}\n" http://backend
kubectl -n demo-app exec frontend -- curl -s -o /dev/null -w "%{http_code}\n" http://database
kubectl -n demo-app exec backend -- curl -s -o /dev/null -w "%{http_code}\n" http://databaseRendu attendu
- Les manifestes YAML (
default-deny.yaml,allow-*.yaml) et le script Python, versionnés. - Une capture de la matrice de flux testée (étape 6) confirmant le résultat attendu.
- Une courte explication du rôle du CNI dans l’application effective de ces politiques.
Points de vérification
- Sans aucune politique, tous les flux passent (référence de départ).
- Avec
default-denyseul, tous les flux inter-pods échouent. - Avec les politiques ciblées, seule la matrice attendue (frontend→backend, backend→database) fonctionne.