@@ -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 ""
|
||||
|
||||
Reference in New Issue
Block a user