206
partie-01-installation/07-verify-cluster.sh
Executable file
206
partie-01-installation/07-verify-cluster.sh
Executable file
@@ -0,0 +1,206 @@
|
||||
#!/bin/bash
|
||||
# Partie 1 - Vérification complète du cluster sécurisé
|
||||
# À exécuter sur le nœud MASTER
|
||||
|
||||
set -e
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
|
||||
# Nettoyer les ressources de test même en cas d'échec
|
||||
CLEANUP_RESOURCES=()
|
||||
cleanup() {
|
||||
if [[ ${#CLEANUP_RESOURCES[@]} -gt 0 ]]; then
|
||||
echo ""
|
||||
echo "--- Nettoyage des ressources de test ---"
|
||||
for res in "${CLEANUP_RESOURCES[@]}"; do
|
||||
kubectl delete $res --ignore-not-found=true 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
check_ok() { echo " ✓ $1"; ((PASS++)); }
|
||||
check_fail() { echo " ✗ $1"; ((FAIL++)); }
|
||||
|
||||
echo "=== Vérification du cluster Kubernetes sécurisé ==="
|
||||
echo ""
|
||||
|
||||
# --- 1. Nœuds ---
|
||||
echo "1. Nœuds du cluster:"
|
||||
kubectl get nodes -o wide
|
||||
echo ""
|
||||
|
||||
# --- 2. Composants control plane ---
|
||||
echo "2. Composants control plane:"
|
||||
kubectl get pods -n kube-system
|
||||
echo ""
|
||||
|
||||
# --- 3. Cilium ---
|
||||
echo "3. Cilium:"
|
||||
if cilium status 2>/dev/null | grep -q "OK"; then
|
||||
check_ok "Cilium opérationnel"
|
||||
else
|
||||
check_fail "Cilium non opérationnel"
|
||||
fi
|
||||
|
||||
if kubectl get pods -n kube-system -l app.kubernetes.io/name=cilium 2>/dev/null | grep -q "Running"; then
|
||||
check_ok "Pods Cilium en état Running"
|
||||
else
|
||||
check_fail "Pods Cilium non Running"
|
||||
fi
|
||||
|
||||
if kubectl get pods -n kube-system -l app.kubernetes.io/name=hubble-relay 2>/dev/null | grep -q "Running"; then
|
||||
check_ok "Hubble relay opérationnel"
|
||||
else
|
||||
check_fail "Hubble relay non opérationnel"
|
||||
fi
|
||||
|
||||
if kubectl get pods -n kube-system -l app.kubernetes.io/name=tetragon 2>/dev/null | grep -q "Running"; then
|
||||
check_ok "Tetragon opérationnel"
|
||||
else
|
||||
check_fail "Tetragon non opérationnel"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- 4. KubeArmor ---
|
||||
echo "4. KubeArmor:"
|
||||
if kubectl get pods -n kubearmor 2>/dev/null | grep -q "Running"; then
|
||||
check_ok "Pods KubeArmor en état Running"
|
||||
else
|
||||
check_fail "Pods KubeArmor non Running"
|
||||
fi
|
||||
|
||||
KUBEARMOR_POLICIES=$(kubectl get clusterkubearmorpholicies 2>/dev/null | grep -c "block\|audit" || echo "0")
|
||||
if [[ "$KUBEARMOR_POLICIES" -ge 4 ]]; then
|
||||
check_ok "ClusterKubeArmorPolicies actives: ${KUBEARMOR_POLICIES}"
|
||||
else
|
||||
check_fail "ClusterKubeArmorPolicies insuffisantes (trouvées: ${KUBEARMOR_POLICIES}, attendues: 4)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- 5. Kyverno ---
|
||||
echo "5. Kyverno:"
|
||||
if kubectl get pods -n kyverno 2>/dev/null | grep -q "Running"; then
|
||||
check_ok "Pods Kyverno en état Running"
|
||||
else
|
||||
check_fail "Pods Kyverno non Running"
|
||||
fi
|
||||
|
||||
KYVERNO_POLICIES=$(kubectl get clusterpolicies 2>/dev/null | grep -c "pass\|fail" || \
|
||||
kubectl get clusterpolicies 2>/dev/null | tail -n +2 | wc -l || echo "0")
|
||||
if [[ "$KYVERNO_POLICIES" -ge 8 ]]; then
|
||||
check_ok "ClusterPolicies Kyverno actives: ${KYVERNO_POLICIES}"
|
||||
else
|
||||
check_fail "ClusterPolicies Kyverno insuffisantes (trouvées: ${KYVERNO_POLICIES}, attendues: 8)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- 6. Audit logs ---
|
||||
echo "6. Audit logging:"
|
||||
AUDIT_LOG="/var/log/kubernetes/audit/audit.log"
|
||||
if sudo test -f "$AUDIT_LOG" 2>/dev/null; then
|
||||
AUDIT_LINES=$(sudo wc -l < "$AUDIT_LOG" 2>/dev/null || echo "0")
|
||||
check_ok "Audit log actif ($AUDIT_LINES entrées): $AUDIT_LOG"
|
||||
else
|
||||
check_fail "Audit log non trouvé: $AUDIT_LOG"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- 7. Chiffrement etcd at-rest ---
|
||||
echo "7. Chiffrement etcd at-rest:"
|
||||
# Créer un secret test et vérifier qu'il est chiffré dans etcd
|
||||
kubectl create secret generic etcd-encryption-check \
|
||||
--from-literal=key=valeur-test-chiffrement \
|
||||
-n default \
|
||||
--dry-run=client -o yaml | kubectl apply -f - > /dev/null 2>&1
|
||||
CLEANUP_RESOURCES+=("secret/etcd-encryption-check -n default")
|
||||
|
||||
ETCD_DATA=$(sudo ETCDCTL_API=3 etcdctl \
|
||||
--endpoints=https://127.0.0.1:2379 \
|
||||
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
|
||||
--cert=/etc/kubernetes/pki/etcd/server.crt \
|
||||
--key=/etc/kubernetes/pki/etcd/server.key \
|
||||
get /registry/secrets/default/etcd-encryption-check 2>/dev/null || echo "")
|
||||
|
||||
if echo "$ETCD_DATA" | grep -q "k8s:enc:aescbc"; then
|
||||
check_ok "Secrets chiffrés AES-CBC dans etcd"
|
||||
elif [[ -z "$ETCD_DATA" ]]; then
|
||||
check_fail "Impossible de lire etcd (vérifier les certificats)"
|
||||
else
|
||||
check_fail "Secrets NON chiffrés dans etcd (données en clair détectées)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- 8. Test NetworkPolicy deny-all ---
|
||||
echo "8. NetworkPolicy deny-all:"
|
||||
kubectl run netpol-test-sender \
|
||||
--image=busybox:1.36 \
|
||||
--restart=Never \
|
||||
-- sleep 3600 2>/dev/null || true
|
||||
CLEANUP_RESOURCES+=("pod/netpol-test-sender -n default")
|
||||
|
||||
kubectl run netpol-test-receiver \
|
||||
--image=busybox:1.36 \
|
||||
--restart=Never \
|
||||
-- sleep 3600 2>/dev/null || true
|
||||
CLEANUP_RESOURCES+=("pod/netpol-test-receiver -n default")
|
||||
|
||||
kubectl wait --for=condition=ready pod/netpol-test-sender pod/netpol-test-receiver \
|
||||
--timeout=60s 2>/dev/null || true
|
||||
|
||||
RECEIVER_IP=$(kubectl get pod netpol-test-receiver -o jsonpath='{.status.podIP}' 2>/dev/null || echo "")
|
||||
if [[ -n "$RECEIVER_IP" ]]; then
|
||||
if kubectl exec netpol-test-sender -- \
|
||||
wget -qO- --timeout=3 "http://${RECEIVER_IP}" 2>/dev/null; then
|
||||
check_fail "NetworkPolicy deny-all NON effective (communication inter-pods possible)"
|
||||
else
|
||||
check_ok "NetworkPolicy deny-all effective (communication inter-pods bloquée)"
|
||||
fi
|
||||
else
|
||||
check_fail "Impossible de récupérer l'IP du pod receiver"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- 9. Test Kyverno : pod privileged refusé ---
|
||||
echo "9. Kyverno - rejet pod privileged:"
|
||||
KYVERNO_REJECT_OUTPUT=$(kubectl run kyverno-priv-test \
|
||||
--image=nginx:1.25 \
|
||||
--restart=Never \
|
||||
--overrides='{"spec":{"containers":[{"name":"kyverno-priv-test","image":"nginx:1.25","securityContext":{"privileged":true}}]}}' \
|
||||
--dry-run=server 2>&1 || true)
|
||||
|
||||
if echo "$KYVERNO_REJECT_OUTPUT" | grep -qiE "disallow-privileged|admission webhook|denied"; then
|
||||
check_ok "Pod privileged correctement refusé par Kyverno"
|
||||
else
|
||||
check_fail "Pod privileged NON refusé — vérifier la ClusterPolicy disallow-privileged-containers"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- 10. Test de déploiement légitime ---
|
||||
echo "10. Test déploiement légitime (sans restrictions):"
|
||||
kubectl create deployment cluster-verify-test \
|
||||
--image=nginx:1.25 \
|
||||
--replicas=2 2>/dev/null || true
|
||||
CLEANUP_RESOURCES+=("deployment/cluster-verify-test -n default")
|
||||
|
||||
kubectl wait --for=condition=available deployment/cluster-verify-test \
|
||||
--timeout=60s 2>/dev/null && \
|
||||
check_ok "Déploiement légitime nginx:1.25 fonctionnel" || \
|
||||
check_fail "Déploiement légitime échoué (vérifier les policies)"
|
||||
echo ""
|
||||
|
||||
# --- Résumé ---
|
||||
echo "============================================="
|
||||
echo " RÉSUMÉ DES VÉRIFICATIONS"
|
||||
echo "============================================="
|
||||
echo " Succès : $PASS"
|
||||
echo " Échecs : $FAIL"
|
||||
echo "============================================="
|
||||
echo ""
|
||||
if [[ $FAIL -eq 0 ]]; then
|
||||
echo "✓ Cluster sécurisé opérationnel — toutes les vérifications passées!"
|
||||
else
|
||||
echo "⚠ $FAIL vérification(s) échouée(s) — voir les détails ci-dessus."
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user