Garden of KnowledgeApplied Sciences › Computer Science › Software › DevSecOps › Kubernetes
May 4, 2025

Sécurité Kubernetes

La sécurité Kubernetes se structure selon le modèle des 4C : Cloud, Cluster, Container, Code. Chaque couche doit être sécurisée indépendamment — une vulnérabilité au niveau Code peut être atténuée par les couches supérieures, mais une mauvaise configuration Cluster expose toutes les applications.

Modèle des 4C§

Cloud (fournisseur, réseau physique, IAM cloud)
└── Cluster (API server, etcd, nœuds, RBAC)
    └── Container (image, runtime, isolation)
        └── Code (application, dépendances, secrets)

RBAC (Role-Based Access Control)§

RBAC contrôle qui peut faire quoi sur quelles ressources dans le cluster.

Concepts§

ObjetPortéeDescription
RoleNamespacePermissions sur des ressources dans un namespace
ClusterRoleClusterPermissions sur des ressources cluster-wide (Nodes, PV…)
RoleBindingNamespaceAttache un Role à un sujet (User, Group, ServiceAccount)
ClusterRoleBindingClusterAttache un ClusterRole à un sujet globalement
# Role : autoriser la lecture des pods dans le namespace "prod"
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: prod
  name: lecteur-pods
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]

# RoleBinding : attacher ce Role à un ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: prod
  name: lecteur-pods-binding
subjects:
  - kind: ServiceAccount
    name: monitoring-sa
    namespace: prod
roleRef:
  kind: Role
  name: lecteur-pods
  apiGroup: rbac.authorization.k8s.io

Principe du moindre privilège§

# Mauvaise pratique : droits wildcard
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]

# Bonne pratique : permissions minimales et explicites
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list"]

Vérifier les permissions d’un sujet :

kubectl auth can-i list pods --namespace prod --as system:serviceaccount:prod:monitoring-sa
kubectl auth can-i --list --namespace prod

Network Policies§

Par défaut, tous les pods peuvent communiquer entre eux. Les Network Policies définissent des règles de pare-feu au niveau des pods.

# Politique : par défaut, bloquer tout le trafic entrant dans le namespace "prod"
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: prod
spec:
  podSelector: {}    # s'applique à tous les pods du namespace
  policyTypes:
    - Ingress

# Autoriser uniquement le trafic venant du namespace "frontend" vers les pods backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: prod
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: frontend
          podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

Les Network Policies nécessitent un CNI qui les supporte (Calico, Cilium, Weave — mais pas Flannel en configuration basique).

Pod Security et SecurityContext§

SecurityContext au niveau Pod et Container§

apiVersion: v1
kind: Pod
metadata:
  name: pod-securise
spec:
  securityContext:
    runAsNonRoot: true         # le container ne peut pas tourner en root
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 2000              # groupe propriétaire des volumes montés
    seccompProfile:
      type: RuntimeDefault     # profil seccomp par défaut du runtime
  containers:
    - name: app
      image: monapp:1.0
      securityContext:
        allowPrivilegeEscalation: false   # impossible de devenir root (sudo, setUID)
        readOnlyRootFilesystem: true       # filesystem en lecture seule
        capabilities:
          drop: ["ALL"]                    # supprimer toutes les capabilities Linux
          add: ["NET_BIND_SERVICE"]        # n'ajouter que ce qui est strictement nécessaire
      volumeMounts:
        - name: tmp
          mountPath: /tmp                  # monter /tmp en écriture si readOnlyRootFilesystem
  volumes:
    - name: tmp
      emptyDir: {}

Pod Security Admission (PSA) — remplacement de PodSecurityPolicy§

PSA définit trois niveaux de sécurité appliqués par namespace :

NiveauDescription
privilegedAucune restriction
baselineEmpêche les configurations les plus dangereuses
restrictedConformité maximale (non-root, capabilities droppées, seccomp)
# Appliquer le niveau "restricted" au namespace "prod"
kubectl label namespace prod pod-security.kubernetes.io/enforce=restricted
kubectl label namespace prod pod-security.kubernetes.io/audit=restricted
kubectl label namespace prod pod-security.kubernetes.io/warn=restricted

Gestion des secrets§

Problèmes avec les Secrets Kubernetes natifs§

Les Secret Kubernetes sont encodés en base64 (pas chiffrés) et stockés en clair dans etcd par défaut.

# Un Secret est trivial à décoder
kubectl get secret mon-secret -o jsonpath='{.data.password}' | base64 -d

Chiffrement at-rest de etcd§

# EncryptionConfiguration à passer à l'API server (--encryption-provider-config)
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <clé base64 de 32 octets>
      - identity: {}   # fallback pour la lecture des secrets non chiffrés

Alternatives recommandées§

OutilApproche
HashiCorp VaultServeur de secrets externe, rotation automatique
External Secrets OperatorSync depuis Vault/AWS SM/Azure KV vers des Secrets K8s
Sealed Secrets (Bitnami)Chiffrement asymétrique — le Secret chiffré peut être versionné dans git
AWS Secrets Manager + IRSAIntégration native AWS pour les pods EKS

Sécurité des images§

# Scanner une image avec Trivy (Aqua Security)
trivy image nginx:1.25
trivy image --severity CRITICAL,HIGH monapp:latest

# Intégration dans un pipeline CI
trivy image --exit-code 1 --severity CRITICAL monapp:$TAG
# exit-code 1 fait échouer le pipeline si des CVE critiques sont trouvées

# Vérifier la signature d'une image (Cosign)
cosign verify --certificate-identity [email protected] \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/org/image@sha256:...

Bonnes pratiques pour les images :

Audit Logs§

Les audit logs de l’API server tracent toutes les requêtes.

# Politique d'audit basique
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: None
    resources:
      - group: ""
        resources: ["events"]    # ne pas logger les events (trop verbeux)

  - level: Metadata
    resources:
      - group: ""
        resources: ["secrets", "configmaps"]

  - level: RequestResponse
    verbs: ["create", "update", "patch", "delete"]
    resources:
      - group: "rbac.authorization.k8s.io"
        resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]

  - level: Request
    omitStages: ["RequestReceived"]

Niveaux d’audit : None (rien) < Metadata (qui, quoi, quand) < Request (+ corps requête) < RequestResponse (+ corps réponse).

Kubescape§

Kubescape (ARMO) scanne un cluster ou des manifestes contre les benchmarks NSA/CISA et CIS.

# Installer
curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash

# Scanner le cluster courant
kubescape scan

# Scanner contre un framework spécifique
kubescape scan framework nsa
kubescape scan framework cis-aks-t1.2.0

# Scanner des manifestes avant déploiement
kubescape scan *.yaml

# Rapport HTML
kubescape scan --format html --output rapport.html

Bonnes pratiques — récapitulatif§

DomainePratique
RBACMoindre privilège, éviter les ClusterAdmin, auditer régulièrement
RéseauNetwork Policies default-deny, segmenter par namespace
PodsNon-root, readOnlyRootFilesystem, capabilities DROP ALL
SecretsChiffrement etcd at-rest + solution externe (Vault, ESO)
ImagesScanner les CVE, distroless, digest SHA256
API serverAudit logs activés, désactiver l’accès anonyme
etcdChiffrement at-rest, TLS mutuel, accès réseau restreint
NœudsCIS Benchmark, mises à jour régulières du kubelet
—The Gardener