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 NetworkPolicy par 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://database

Le 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

Graphe des flux autorisés entre microservices Graphe des flux autorisés entre microservices 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://database

Rendu 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-deny seul, tous les flux inter-pods échouent.
  • Avec les politiques ciblées, seule la matrice attendue (frontend→backend, backend→database) fonctionne.