Principes Fondamentaux de la Sécurité
La sécurisation d'un cluster Kubernetes repose sur une approche multicouche. Chaque couche doit être configurée pour minimiser les risques, du réseau jusqu'aux conteneurs.
| Couche | Mesure de Protection | Solution |
|---|---|---|
| Cluster | Contrôle d'accès (RBAC) | Principe du moindre privilège |
| Réseau | Politiques réseau | Modèle zéro confiance |
| Conteneur | Analyse d'images | Détection de vulnérabilités |
| Runtime | Normes de sécurité Pod | Restreindre les conteneurs privilégiés |
| Données | Gestion des secrets | Intégration avec HashiCorp Vault |
Configuration Pratique
Gestion des Droits avec RBAC
Un exemple de configuration RBAC pour limiter l'accès en lecture aux pods dans un namespace spécifique :
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">rbac.authorization.k8s.io/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Role</span>
<span class="hljs-attr">metadata:</span>
<span class="hljs-attr">namespace:</span> <span class="hljs-string">production</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">pod-viewer</span>
<span class="hljs-attr">rules:</span>
- <span class="hljs-attr">apiGroups:</span> [<span class="hljs-string">""</span>]
<span class="hljs-attr">resources:</span> [<span class="hljs-string">"pods"</span>]
<span class="hljs-attr">verbs:</span> [<span class="hljs-string">"get"</span>, <span class="hljs-string">"watch"</span>, <span class="hljs-string">"list"</span>]
---
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">rbac.authorization.k8s.io/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">RoleBinding</span>
<span class="hljs-attr">metadata:</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">grant-pod-view</span>
<span class="hljs-attr">namespace:</span> <span class="hljs-string">production</span>
<span class="hljs-attr">subjects:</span>
- <span class="hljs-attr">kind:</span> <span class="hljs-string">User</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">dev-user</span>
<span class="hljs-attr">apiGroup:</span> <span class="hljs-string">rbac.authorization.k8s.io</span>
<span class="hljs-attr">roleRef:</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Role</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">pod-viewer</span>
<span class="hljs-attr">apiGroup:</span> <span class="hljs-string">rbac.authorization.k8s.io</span>
Politiques Réseau
Pour implémenter une isolation réseau stricte, on combine une politique de refus total avec une règle d'autorisation spécifique :
<span class="hljs-comment"># Politique par défaut : tout bloquer</span>
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
<span class="hljs-comment"># Autoriser le trafic entrant uniquement depuis les pods frontend</span>
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: <span class="hljs-number">8080</span>
Normes de Sécurité des Pods
Une PodSecurityPolicy (PSP) restreint les capacités des contenerus. Voici un exemple restreignant l'élévation de privilèges :
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: strict-policy
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: <span class="hljs-string">'runtime/default'</span>
apparmor.security.beta.kubernetes.io/allowedProfileNames: <span class="hljs-string">'runtime/default'</span>
spec:
privileged: <span class="hljs-literal">false</span>
allowPrivilegeEscalation: <span class="hljs-literal">false</span>
requiredDropCapabilities:
- <span class="hljs-keyword">ALL</span>
runAsUser:
rule: <span class="hljs-string">'MustRunAsNonRoot'</span>
seLinux:
rule: <span class="hljs-string">'RunAsAny'</span>
fsGroup:
rule: <span class="hljs-string">'MustRunAs'</span>
ranges:
- min: <span class="hljs-number">1</span>
max: <span class="hljs-number">65535</span>
volumes:
- <span class="hljs-string">'configMap'</span>
- <span class="hljs-string">'emptyDir'</span>
- <span class="hljs-string">'projected'</span>
- <span class="hljs-string">'secret'</span>
- <span class="hljs-string">'downwardAPI'</span>
Sécurité des Images
L'analyse des images est cruciale. Nous utilisons Trivy dans un pipeline GitLab CI pour détecter les vulnérabilités critiques :
<span class="hljs-comment"># Installation de Trivy</span>
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.49.1
<span class="hljs-comment"># Analyse rapide</span>
trivy image nginx:alpine
<span class="hljs-comment"># Configuration CI</span>
cat > .gitlab-ci.yml << <span class="hljs-string">'EOF'</span>
<span class="hljs-string">image_scan:</span>
<span class="hljs-string"> stage: test</span>
<span class="hljs-string"> script:</span>
<span class="hljs-string"> - trivy image --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA</span>
<span class="hljs-string"> allow_failure: true</span>
<span class="hljs-string">EOF</span>
Gestion des Secrets avec Vault
L'intégration avec Vault permet de centraliser et de rafraîchir automatiquement les secrets :
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: app-credentials
namespace: production
spec:
type: kv-v2
mount: kv
path: apps/production
refreshAfter: 30m
destination:
name: app-secrets
create: true
rolloutRestartTargets:
- kind: Deployment
name: backend-service
Surveillance et Détection des Menaces
Journal d'Audit
Configuration de l'audit pour capturer chaque requête sur des ressources sensibles :
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
resources:
- group: <span class="hljs-string">""</span>
resources: [<span class="hljs-string">"secrets"</span>, <span class="hljs-string">"configmaps"</span>]
- level: Metadata
resources:
- group: <span class="hljs-string">""</span>
resources: [<span class="hljs-string">"pods"</span>, <span class="hljs-string">"services"</span>]
Détection Réseau avec Falco
Falco surveille les appels système et génère des alertes en cas d'activité suspecte :
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: falco-agent
namespace: security
spec:
selector:
matchLabels:
app: falco
template:
metadata:
labels:
app: falco
spec:
containers:
- name: falco
image: falcosecurity/falco:latest
securityContext:
privileged: true
volumeMounts:
- name: config
mountPath: /etc/falco
volumes:
- name: config
configMap:
name: falco-rules
Liste de Contrôle
- Cluster : Activer RBAC, configurer les politiques réseau, appliquer la norme Pod Security, activer la journalisation d'audit.
- Conteneurs : Utiliser des images minimales, analyser les vulnérabilités, restreindre les privilèges (pas de
privileged: true), définir des limites de ressources. - Réseau : Appliquer des NetworkPolicies, configurer un Ingress Controller, activer TLS pour tout le trafic externe, limiter les accès sortants.
- Données : Stocker les secrets dans Kubernetes Secrets ou un gestionnaire externe, intégrer Vault, chiffrer les volumes persistants.
Problèmes Courants et Solutions
- Conteneurs privilégiés : Éviter
privileged: true. UtilisersecurityContextpour limiter les capacités. - Images vulnérables : Mettre en place une analyse systématique (Trivy, Clair) et n'utiliser que des images officeilles ou vérifiées.
- Exposition réseau : Appliquer des politiques réseau restrictives par défaut (deny all) et n'autoriser que le trafic nécesssaire.
- Fuites de secrets : Ne jamais coder en dur. Utiliser Secrets, Vault ou des solutions équivalentes.
La sécurisation d'un cluster Kubernetes est un processus continu. En suivant ces pratiques, vous réduirez considérablement la surface d'attaque.