
Les Pod Security Standards (PSS) définissent 3 niveaux de restrictions de sécurité pour vos pods Kubernetes : Privileged (aucune restriction), Baseline (bloque les escalades évidentes), et Restricted (hardening maximal). Ce guide vous explique quand utiliser chaque niveau et comment les appliquer sans casser vos applications.
Qu’est-ce que Pod Security Standards ?
Section intitulée « Qu’est-ce que Pod Security Standards ? »Pod Security Standards (PSS) est le standard officiel Kubernetes pour définir les niveaux de sécurité des pods. Pensez-y comme à des “profils de sécurité prédéfinis” que vous pouvez appliquer à vos namespaces.
Pourquoi c’est important ?
Section intitulée « Pourquoi c’est important ? »Par défaut, Kubernetes autorise des configurations dangereuses. Sans restriction explicite, un développeur peut déployer un pod qui a un accès complet au nœud hôte — ce qui est exactement ce qu’un attaquant recherche.
Voici ce qui est autorisé si vous ne configurez rien :
| Configuration par défaut | Risque |
|---|---|
Pod en root (UID 0) | Escalade de privilèges si le conteneur est compromis |
privileged: true autorisé | Accès complet à l’hôte |
Montage de / possible | Lecture/écriture du système hôte |
hostNetwork: true autorisé | Écoute sur les ports de l’hôte |
Scénario d’attaque : Un attaquant compromet une application vulnérable dans un pod. Si le pod tourne en root avec privileged: true, l’attaquant peut s’échapper du conteneur, accéder au nœud, puis pivoter vers d’autres nœuds du cluster. Les PSS empêchent ce scénario en bloquant ces configurations dès le déploiement.
Les PSS bloquent ces configurations selon leur niveau de restriction.
Les 3 niveaux PSS
Section intitulée « Les 3 niveaux PSS »Niveau Privileged
Section intitulée « Niveau Privileged »Aucune restriction — Ce niveau autorise tout, y compris les configurations les plus dangereuses.
Quand l’utiliser :
- Namespaces système (
kube-system) - Outils d’infrastructure (monitoring agents, CNI, CSI drivers)
- Jamais pour des applications métier
# Ce pod est autorisé en PrivilegedapiVersion: v1kind: Podmetadata: name: privileged-podspec: containers: - name: debug image: ubuntu securityContext: privileged: true # Accès root complet à l'hôte runAsUser: 0 # Exécution en rootNiveau Baseline
Section intitulée « Niveau Baseline »Restrictions minimales — Bloque les escalades de privilèges les plus dangereuses tout en restant compatible avec la majorité des workloads.
Ce qui est bloqué :
| Configuration | Pourquoi c’est bloqué |
|---|---|
privileged: true | Accès complet à l’hôte |
hostPID: true | Voir les processus de l’hôte |
hostIPC: true | Accès à la mémoire partagée de l’hôte |
hostNetwork: true | Écoute sur les ports de l’hôte |
| Capabilities dangereuses | SYS_ADMIN, NET_RAW, etc. |
Quand l’utiliser :
- Applications legacy ne supportant pas Restricted
- Première étape de migration depuis Privileged
- Environnements de développement
# Ce pod est compatible BaselineapiVersion: v1kind: Podmetadata: name: baseline-podspec: containers: - name: app image: nginx:1.25 securityContext: runAsUser: 1000 # Non-root recommandé allowPrivilegeEscalation: falseNiveau Restricted
Section intitulée « Niveau Restricted »Hardening maximal — Applique les meilleures pratiques de sécurité. C’est le niveau recommandé pour la production.
Ce qui est exigé :
| Exigence | Valeur requise |
|---|---|
runAsNonRoot | true |
allowPrivilegeEscalation | false |
seccompProfile | RuntimeDefault ou Localhost |
capabilities.drop | ALL |
| Volumes autorisés | Seulement configMap, secret, emptyDir, persistentVolumeClaim, projected |
Quand l’utiliser :
- Applications de production
- Workloads manipulant des données sensibles
- Préparation à la certification CKS
# Ce pod est conforme RestrictedapiVersion: v1kind: Podmetadata: name: restricted-podspec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: app image: nginx:1.25-alpine securityContext: runAsUser: 1000 runAsGroup: 1000 allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALLComment appliquer PSS ?
Section intitulée « Comment appliquer PSS ? »Kubernetes applique les Pod Security Standards via Pod Security Admission (PSA), un admission controller intégré depuis la version 1.25.
Les 3 modes d’application
Section intitulée « Les 3 modes d’application »PSA offre trois manières d’appliquer un niveau PSS à un namespace. Ces modes peuvent être combinés pour une migration progressive et sécurisée.
| Mode | Comportement | Usage |
|---|---|---|
enforce | Bloque les pods non conformes | Production |
audit | Enregistre dans les audit logs | Migration |
warn | Affiche un warning à l’utilisateur | Développement |
Stratégie de migration recommandée :
- D’abord
warn+audit: Les développeurs voient les warnings, les violations sont loggées, mais rien n’est bloqué. Cela vous donne le temps de corriger les manifests. - Ensuite
enforce: Une fois tous les pods conformes, activez le blocage. Toute tentative de déploiement non conforme sera refusée.
Cette approche évite de casser la production du jour au lendemain.
Appliquer PSS à un namespace
Section intitulée « Appliquer PSS à un namespace »Méthode 1 : Labels sur le namespace
apiVersion: v1kind: Namespacemetadata: name: production labels: # Applique Restricted en mode enforce pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/enforce-version: latest
# Audit les violations Restricted pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/audit-version: latest
# Avertit pour Restricted pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/warn-version: latestMéthode 2 : kubectl label
# Appliquer Restricted sur un namespace existantkubectl label namespace production \ pod-security.kubernetes.io/enforce=restricted \ pod-security.kubernetes.io/warn=restricted \ pod-security.kubernetes.io/audit=restricted
# Vérifier les labelskubectl get namespace production -o yaml | grep pod-securityMigrer vers Restricted sans casser vos applications
Section intitulée « Migrer vers Restricted sans casser vos applications »-
Audit d’abord : identifiez les violations
Appliquez d’abord en mode
audit+warnpour voir ce qui casserait :Fenêtre de terminal kubectl label namespace monapp \pod-security.kubernetes.io/audit=restricted \pod-security.kubernetes.io/warn=restrictedCréez un pod de test et observez les warnings :
Fenêtre de terminal kubectl run test --image=nginx -n monapp# Warning: would violate "restricted:latest"... -
Corrigez vos Deployments
Pour chaque violation identifiée, mettez à jour le
securityContext:spec:securityContext:runAsNonRoot: trueseccompProfile:type: RuntimeDefaultcontainers:- name: appsecurityContext:allowPrivilegeEscalation: falsereadOnlyRootFilesystem: truerunAsUser: 1000capabilities:drop: ["ALL"] -
Testez en staging
Déployez avec les nouveaux
securityContextet validez que l’application fonctionne. -
Appliquez Restricted en enforce
Une fois tous les pods conformes :
Fenêtre de terminal kubectl label namespace production \pod-security.kubernetes.io/enforce=restricted \--overwrite
Erreurs fréquentes et solutions
Section intitulée « Erreurs fréquentes et solutions »Erreur 1 : “container has runAsNonRoot and image will run as root”
Section intitulée « Erreur 1 : “container has runAsNonRoot and image will run as root” »Cause : L’image utilise root mais vous avez runAsNonRoot: true.
Solution :
securityContext: runAsUser: 1000 # Forcer un UID non-root runAsGroup: 1000 runAsNonRoot: trueErreur 2 : “seccompProfile is required”
Section intitulée « Erreur 2 : “seccompProfile is required” »Cause : Le niveau Restricted exige un profil seccomp.
Solution :
spec: securityContext: seccompProfile: type: RuntimeDefaultErreur 3 : “unrestricted capabilities”
Section intitulée « Erreur 3 : “unrestricted capabilities” »Cause : Vous n’avez pas droppé toutes les capabilities.
Solution :
containers:- name: app securityContext: capabilities: drop: ["ALL"] # Si vraiment nécessaire, ajoutez explicitement : # add: ["NET_BIND_SERVICE"]Comparatif des 3 niveaux
Section intitulée « Comparatif des 3 niveaux »Ce tableau résume ce qui est autorisé ou bloqué à chaque niveau. Utilisez-le comme référence rapide lors de vos audits de sécurité.
| Configuration | Privileged | Baseline | Restricted |
|---|---|---|---|
privileged: true | ✅ | ❌ | ❌ |
hostNetwork/PID/IPC | ✅ | ❌ | ❌ |
hostPath volumes | ✅ | ✅ | ❌ |
| Root (UID 0) | ✅ | ✅ | ❌ |
allowPrivilegeEscalation | ✅ | ✅ | ❌ |
| Capabilities dangereuses | ✅ | ❌ | ❌ |
| Seccomp requis | ❌ | ❌ | ✅ |
Comment lire ce tableau ?
- Baseline bloque les vulnérabilités critiques (
privileged,hostNetwork) mais autorise encore des pratiques risquées (hostPath, root). - Restricted va plus loin : il exige un profil seccomp, interdit root, et limite les volumes montés. C’est la posture “zéro confiance” pour vos workloads.
- Attention à
hostPath: Même en Baseline, un attaquant peut monter/etc/shadows’il contrôle le manifest du pod. C’est pourquoi Restricted est recommandé en production.
À retenir
Section intitulée « À retenir »- 3 niveaux : Privileged (tout autorisé), Baseline (bloque le pire), Restricted (hardening maximal)
- Production = Restricted : C’est le niveau recommandé par la documentation Kubernetes
- Migration progressive : Utilisez
auditetwarnavantenforce - Pod Security Admission : L’admission controller natif qui applique les PSS via des labels
- CKS : Les PSS représentent 20% du domaine “Minimize Microservice Vulnerabilities”