Aller au contenu

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)

  1. Déployer Falco avec les regles par defaut en mode alerte uniquement
  2. Collecter toutes les alertes dans Loki
  3. 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