Bonnes pratiques¶
Tuning des regles Falco¶
Gestion des faux positifs¶
Les regles Falco par defaut génèrent des faux positifs dans des environnements reels. Le tuning est un processus continu :
Phase 1 : Observer (1-2 semaines)
- Déployer Falco avec les regles par defaut en mode alerte uniquement
- Collecter toutes les alertes dans Loki
- Identifier les alertes recurrentes et legitimes
Phase 2 : Affiner
# falco_rules.local.yaml — surcharges locales
# Methode 1 : desactiver une regle entiere
- rule: Read sensitive file untrusted
enabled: false
# Methode 2 : ajouter des exceptions a une regle existante
- rule: Terminal shell in container
exceptions:
- name: known_debug_containers
fields: [container.image.repository]
comps: [in]
values:
- [registry.internal.company.io/debug-tools]
- name: ci_runners
fields: [k8s.ns.name]
comps: [in]
values:
- [cicd-runners]
# Methode 3 : creer une macro de filtrage
- macro: allowed_shell_processes
condition: >
(proc.pname in (entrypoint.sh, start.sh, init.sh) or
k8s.ns.name in (cicd-runners, build-system))
- rule: Terminal shell in container
condition: >
spawned_process and container and
proc.name in (bash, sh, zsh, dash) and
not allowed_shell_processes
Phase 3 : Valider
# Tester les regles localement avant deploiement
falco --validate /etc/falco/falco_rules.yaml \
--validate /etc/falco/falco_rules.local.yaml
# Compter les alertes par regle (apres tuning)
# Dans Grafana, comparer avant/apres tuning
Metriques de qualité des regles¶
| Metrique | Cible | Action si hors cible |
|---|---|---|
| Faux positifs / jour | < 10 par regle | Ajouter des exceptions |
| Alertes critiques / jour | < 5 (hors incident) | Vérifier la sévérité des regles |
| Regles desactivees | < 20% du total | Re-évaluer les regles desactivees |
| Temps moyen de triage | < 5 minutes | Améliorer les messages de sortie |
Gestion des exceptions OPA¶
Processus d'exception¶
Parfois, une contrainte OPA doit etre contournee legitimement (déploiement d'urgence, migration, outil spécifique). Le processus de break-glass est formalisé :
| Étape | Responsable | Action |
|---|---|---|
| 1. Demande | Équipe demandeuse | Ticket avec justification, perimetre, duree |
| 2. Approbation | Responsable sécurité | Validation de la justification |
| 3. Implementation | Équipe sécurité | Ajout d'une exception temporaire |
| 4. Suivi | Équipe sécurité | Alerte a l'expiration |
| 5. Revocation | Équipe sécurité | Suppression de l'exception |
Implementation technique des exceptions¶
# Exception temporaire : autoriser un conteneur privilegie pour un outil specifique
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDisallowPrivileged
metadata:
name: no-privileged-containers
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces:
- kube-system
# Exception temporaire — TICKET SEC-2026-042
# Expire le 2026-05-01 — Migration CNI Calico
- calico-migration-temp
Documenter chaque exception
Chaque exception dans une contrainte OPA doit etre accompagnee d'un commentaire avec : le numero de ticket, la raison, la date d'expiration. Automatisez la detection des exceptions expirees.
Dry-run avant enforcement¶
Toujours tester les nouvelles contraintes en mode dry-run avant de les enforcer :
# Phase 1 : dry-run (observe sans bloquer)
spec:
enforcementAction: dryrun
# Phase 2 : warn (avertit sans bloquer)
spec:
enforcementAction: warn
# Phase 3 : deny (bloque)
spec:
enforcementAction: deny
# Verifier les violations en mode audit
kubectl get k8sdisallowprivileged no-privileged-containers \
-o jsonpath='{.status.violations}' | jq '.'
# Compter les violations par contrainte
kubectl get constraints -o json | \
jq '.items[] | {name: .metadata.name, violations: (.status.violations | length)}'
Scanning continu vs scanning a l'admission¶
Stratégie de scanning en couches¶
| Couche | Outil | Quand | Action si echec |
|---|---|---|---|
| CI/CD | Trivy CLI | À chaque build d'image | Pipeline en echec, image non publiee |
| Admission | OPA (contrainte image signee) | A la creation du pod | Pod rejete |
| Runtime continu | Trivy Operator | Periodiquement (toutes les 12h) | Alerte + ticket de remédiation |
Le scanning en CI/CD attrape les vulnerabilites connues au moment du build. Le scanning continu en runtime détecte les nouvelles CVE publiées apres le déploiement.
# Voir les images avec des CVE critiques non corrigees
kubectl get vulnerabilityreports -A -o json | \
jq '.items[] | select(.report.summary.criticalCount > 0) |
{namespace: .metadata.namespace,
image: .report.artifact.repository,
critical: .report.summary.criticalCount,
high: .report.summary.highCount}'
Compliance-as-code¶
CIS Kubernetes Benchmark¶
Le CIS Benchmark définit les bonnes pratiques de sécurité Kubernetes. Trivy peut auditer la conformite :
# Audit CIS avec Trivy
trivy k8s --compliance k8s-cis --report summary cluster
# Rapport detaille
trivy k8s --compliance k8s-cis --report all cluster > cis-report.json
NSA/CISA Kubernetes Hardening Guide¶
Les recommandations NSA/CISA se traduisent en contraintes OPA :
| Recommandation NSA | Contrainte OPA |
|---|---|
| Pas de conteneurs privilegies | K8sDisallowPrivileged |
| Pas de hostNetwork | K8sDisallowHostNetwork |
| Pas de hostPID/hostIPC | K8sDisallowHostNamespaces |
| Resource limits obligatoires | K8sRequireResourceLimits |
| Read-only root filesystem | K8sRequireReadOnlyRootFS |
| runAsNonRoot | K8sRequireRunAsNonRoot |
| Pas de capabilities dangereuses | K8sDisallowCapabilities |
# Exemple : exiger runAsNonRoot
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequirerunasnonroot
spec:
crd:
spec:
names:
kind: K8sRequireRunAsNonRoot
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequirerunasnonroot
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.securityContext.runAsNonRoot
msg := sprintf("runAsNonRoot requis pour : %s", [container.name])
}
Incident response runtime¶
Procedure de réponse¶
Quand Falco détecte une alerte critique :
graph LR
Detection["Detection<br/>(Falco)"] --> Triage["Triage<br/>(SOC/Ops)"] --> Containment["Containment<br/>(isoler)"] --> Forensics["Forensics<br/>(analyser)"] Actions de containment¶
# 1. Isoler le pod : supprimer les labels pour le detacher du Service
kubectl label pod <pod-compromis> app- --overwrite
# 2. Appliquer une NetworkPolicy d'isolation totale
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: isolate-compromised-pod
namespace: <namespace>
spec:
podSelector:
matchLabels:
incident: isolated
policyTypes:
- Ingress
- Egress
# Aucun flux autorise — isolation totale
EOF
kubectl label pod <pod-compromis> incident=isolated
# 3. Capturer l'etat du pod avant suppression (forensics)
kubectl get pod <pod-compromis> -o yaml > forensics/pod-manifest.yaml
kubectl logs <pod-compromis> > forensics/pod-logs.txt
kubectl describe pod <pod-compromis> > forensics/pod-describe.txt
# 4. Si necessaire, supprimer le pod compromis
kubectl delete pod <pod-compromis> --grace-period=0 --force
# 5. Si le namespace entier est compromis, isoler le namespace
kubectl annotate namespace <namespace> incident=active
Ne pas supprimer immédiatement
Avant de supprimer un pod compromis, capturez son état pour l'analyse forensique. La suppression immedite detruit les preuves nécessaires pour comprendre l'attaque et renforcer les defenses.
Troubleshooting¶
Falco — Problèmes courants¶
| Symptome | Cause probable | Résolution |
|---|---|---|
falco_drops_total augmente | Buffer eBPF trop petit ou CPU insuffisant | Augmenter falco.buf_size_preset et les ressources CPU |
| Falco ne demarre pas | Kernel incompatible (eBPF CO-RE) | Vérifier kernel >= 5.8, ou basculer sur le driver kmod |
| Alertes manquantes | Regle desactivee ou exception trop large | Vérifier falco_rules.local.yaml et les exceptions |
| Trop d'alertes | Regles par defaut non tunees | Suivre le processus de tuning (Phase 1-2-3) |
| Falco consomme trop de CPU | Trop d'événements sur le nœud | Filtrer les événements avec des macros evt.type |
# Diagnostiquer les drops
kubectl -n falco-system logs -l app.kubernetes.io/name=falco | grep -i drop
# Verifier les regles chargees
kubectl -n falco-system exec -it <falco-pod> -- falco --list | head -20
# Verifier la version du driver
kubectl -n falco-system exec -it <falco-pod> -- falco --version
OPA/Gatekeeper — Problèmes courants¶
| Symptome | Cause probable | Résolution |
|---|---|---|
| Webhook timeout | Gatekeeper surcharge ou mal dimensionne | Augmenter le timeout webhook et les replicas |
| Ressource rejetee sans raison claire | Contrainte trop stricte | Vérifier le message de violation, passer en dryrun |
| Audit ne détecte pas les violations | auditInterval trop long | Reduire l'intervalle ou forcer un audit |
| ConstraintTemplate en erreur | Erreur de syntaxe Rego | Tester le Rego avec opa eval localement |
| Latence API elevee | Trop de contraintes evaluees | Reduire le nombre de contraintes, optimiser le Rego |
# Verifier le status d'un ConstraintTemplate
kubectl get constrainttemplate <name> -o jsonpath='{.status}'
# Verifier les violations en cours
kubectl get constraints -A -o json | \
jq '.items[] | select(.status.totalViolations > 0) |
{name: .metadata.name, violations: .status.totalViolations}'
# Tester une politique Rego localement
echo '{"review": {"object": ...}}' | opa eval -d policy.rego 'data.main.deny'
Trivy Operator — Problèmes courants¶
| Symptome | Cause probable | Résolution |
|---|---|---|
| Scans ne se terminent pas | Timeout réseau vers les bases de CVE | Configurer un miroir local de la base Trivy |
| Jobs de scan en echec | Ressources insuffisantes pour le Job | Augmenter les limites du Job scanner |
| Rapports obsolètes | Images mises a jour sans re-scan | Reduire le scanJobTTL ou forcer un re-scan |
| Trop de CVE reportees | Sévérité medium incluse | Filtrer sur CRITICAL,HIGH uniquement |
# Voir les jobs de scan en echec
kubectl -n trivy-system get jobs --field-selector status.failed=1
# Forcer un re-scan en supprimant le rapport
kubectl delete vulnerabilityreport <report-name> -n <namespace>
# Verifier la connectivite vers la base de vulnerabilites
kubectl -n trivy-system run trivy-test --rm -it --image=aquasec/trivy:latest -- \
image --download-db-only