Signed-off-by: Louis Labeyrie <labeyrielouis@gmail.com>
This commit is contained in:
2026-04-27 16:21:21 +02:00
parent 1e24ec3243
commit 1580a13fb6
10 changed files with 760 additions and 40 deletions

View File

@@ -39,7 +39,7 @@ kubectl wait --for=condition=ready pod \
echo " ✓ Kyverno opérationnel"
echo ""
echo "Application des 8 ClusterPolicies de sécurité..."
echo "Application des 14 ClusterPolicies de sécurité..."
# Policy 1 : Interdire les containers privileged
# POURQUOI: Un container privileged a accès complet au kernel de l'hôte (comme root sur l'hôte).
@@ -306,7 +306,222 @@ spec:
- Egress
EOF
echo " ✓ 8 ClusterPolicies appliquées"
# Policy 9 : Forcer le drop de toutes les capabilities (sauf NET_BIND_SERVICE)
# POURQUOI: Par défaut, un container hérite de capabilities (CAP_CHOWN, CAP_DAC_OVERRIDE,
# CAP_NET_RAW, etc.) qui permettent à root dans le container de bypass certains
# contrôles. Drop ALL + add seulement NET_BIND_SERVICE = principe du moindre privilège.
kubectl apply -f - <<'EOF'
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-drop-all-capabilities
annotations:
policies.kyverno.io/description: "Force le drop de toutes les capabilities Linux."
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-drop-all
match:
any:
- resources:
kinds: [Pod]
exclude:
any:
- resources:
namespaces: [kube-system, kyverno, kubearmor]
validate:
message: "Les containers doivent drop ALL capabilities (securityContext.capabilities.drop)."
foreach:
- list: "request.object.spec.containers"
deny:
conditions:
all:
- key: "ALL"
operator: AnyNotIn
value: "{{ element.securityContext.capabilities.drop[] || `[]` }}"
EOF
# Policy 10 : Interdire allowPrivilegeEscalation
# POURQUOI: Sans cette restriction, un binaire setuid (ou un appel à execve avec
# transmission des privilèges) peut élever le processus au-delà de ce qu'il
# devrait avoir. Avec false, le bit no_new_privs est posé sur le process tree.
kubectl apply -f - <<'EOF'
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privilege-escalation
annotations:
policies.kyverno.io/description: "Interdit allowPrivilegeEscalation: true."
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-privesc
match:
any:
- resources:
kinds: [Pod]
exclude:
any:
- resources:
namespaces: [kube-system, kyverno, kubearmor]
validate:
message: "allowPrivilegeEscalation doit être false."
pattern:
spec:
containers:
- securityContext:
allowPrivilegeEscalation: false
EOF
# Policy 11 : Restreindre les registries d'images autorisés
# POURQUOI: Empêche qu'un attaquant pull une image arbitraire (cryptominer, backdoor).
# Whitelist des registries publics réputés + l'éventuel registry interne de l'école.
# AJUSTER les valeurs pour le Kube Battle (ajouter votre registry si besoin).
kubectl apply -f - <<'EOF'
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
annotations:
policies.kyverno.io/description: "Limite les registries autorisés pour les images de container."
spec:
validationFailureAction: Enforce
background: false
rules:
- name: validate-registries
match:
any:
- resources:
kinds: [Pod]
exclude:
any:
- resources:
namespaces: [kube-system, kyverno, kubearmor]
validate:
message: "Image refusée : registry non autorisé. Autorisés : docker.io, registry.k8s.io, quay.io, ghcr.io."
pattern:
spec:
containers:
- image: "docker.io/* | registry.k8s.io/* | quay.io/* | ghcr.io/* | nginx:* | busybox:*"
EOF
# Policy 12 : Bloquer les services NodePort et LoadBalancer
# POURQUOI: NodePort expose un service sur un port de chaque nœud (accessible depuis
# l'extérieur du cluster). Permet à l'équipe externe d'exposer publiquement
# un service malveillant (C2, exfiltration HTTP). LoadBalancer fait pareil.
# L'équipe externe doit utiliser ClusterIP + Ingress contrôlé.
kubectl apply -f - <<'EOF'
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-nodeport-loadbalancer
annotations:
policies.kyverno.io/description: "Interdit les services type NodePort et LoadBalancer."
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-nodeport
match:
any:
- resources:
kinds: [Service]
exclude:
any:
- resources:
namespaces: [kube-system, kyverno, kubearmor]
validate:
message: "Les services NodePort et LoadBalancer sont interdits. Utiliser ClusterIP + Ingress."
pattern:
spec:
=(type): "!NodePort & !LoadBalancer"
EOF
# Policy 13 : Bloquer les RBAC avec wildcards (verbe ou ressource = *)
# POURQUOI: Un Role avec verbs=["*"] ou resources=["*"] = équivalent cluster-admin
# dans son scope. Si l'équipe externe arrive (par bug RBAC) à créer un Role,
# elle ne pourra au moins pas se donner tous les pouvoirs.
kubectl apply -f - <<'EOF'
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: block-rbac-wildcards
annotations:
policies.kyverno.io/description: "Interdit les Roles/ClusterRoles avec verbe ou ressource '*'."
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-wildcard-verbs
match:
any:
- resources:
kinds: [Role, ClusterRole]
exclude:
any:
- clusterRoles: ["cluster-admin"]
- subjects:
- kind: User
name: "system:admin"
validate:
message: "Les Roles/ClusterRoles avec verbe '*' ou ressource '*' sont interdits."
deny:
conditions:
any:
- key: "{{ request.object.rules[].verbs[] | contains(@, '*') }}"
operator: Equals
value: true
- key: "{{ request.object.rules[].resources[] | contains(@, '*') }}"
operator: Equals
value: true
- key: "{{ request.object.rules[].verbs[] | contains(@, 'escalate') }}"
operator: Equals
value: true
- key: "{{ request.object.rules[].verbs[] | contains(@, 'bind') }}"
operator: Equals
value: true
- key: "{{ request.object.rules[].verbs[] | contains(@, 'impersonate') }}"
operator: Equals
value: true
EOF
# Policy 14 : Interdire hostPort dans les containers
# POURQUOI: hostPort bind un port de l'hôte directement (bypass du Service K8s).
# Permet à un attaquant d'écouter sur un port haut de l'hôte (par ex 31337)
# pour un C2 ou un reverse shell, contournant les Services et NetworkPolicies.
kubectl apply -f - <<'EOF'
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-ports
annotations:
policies.kyverno.io/description: "Interdit les hostPort dans les containers."
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-host-port
match:
any:
- resources:
kinds: [Pod]
exclude:
any:
- resources:
namespaces: [kube-system, kyverno, kubearmor]
validate:
message: "Les hostPort sont interdits."
deny:
conditions:
any:
- key: "{{ request.object.spec.containers[].ports[].hostPort | length(@) }}"
operator: GreaterThan
value: 0
EOF
echo " ✓ 14 ClusterPolicies appliquées"
# --- Vérifications ---
echo ""