Installation et configuration¶
Pre-requis¶
| Composant | Version minimum | Note |
|---|---|---|
| Kubernetes | 1.25+ | Pour les PodSecurity admission |
| Kernel Linux | 5.8+ | Pour eBPF CO-RE (Falco) |
| Helm | 3.12+ | Gestionnaire de charts |
| kubectl | 1.25+ | Correspond a la version du cluster |
# Verifier la version du kernel sur les noeuds
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.kernelVersion}{"\n"}{end}'
# Verifier que eBPF est supporte
kubectl debug node/<node-name> -it --image=busybox -- ls /sys/kernel/btf/vmlinux
Déploiement de Falco¶
Ajout du dépôt Helm¶
Valeurs de configuration¶
# falco-values.yaml
falco:
# Utiliser eBPF moderne (pas le module kernel)
driver:
kind: modern_ebpf
# Format de sortie JSON pour integration avec Loki
json_output: true
json_include_output_property: true
json_include_tags_property: true
# Canaux de sortie
stdout_output:
enabled: true
http_output:
enabled: false
grpc_output:
enabled: false
# Regles personnalisees (en plus des regles par defaut)
rules_files:
- /etc/falco/falco_rules.yaml
- /etc/falco/falco_rules.local.yaml
- /etc/falco/rules.d
# Regles personnalisees
customRules:
custom-rules.yaml: |-
# Detecter la lecture de tokens ServiceAccount
- rule: Read ServiceAccount Token
desc: Detect reading of ServiceAccount token in a container
condition: >
open_read and container and
fd.name startswith /var/run/secrets/kubernetes.io/serviceaccount and
not proc.name in (coredns, kube-proxy, calico-node)
output: >
Lecture du token ServiceAccount
(user=%user.name container=%container.name
file=%fd.name image=%container.image.repository)
priority: WARNING
tags: [kubernetes, mitre_credential_access]
# Ressources
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 512Mi
# Tolerations pour s'executer sur tous les noeuds
tolerations:
- effect: NoSchedule
operator: Exists
Installation¶
# Creer le namespace dedie
kubectl create namespace falco-system
# Installer Falco
helm install falco falcosecurity/falco \
--namespace falco-system \
--values falco-values.yaml \
--wait
# Verifier le deploiement
kubectl -n falco-system get pods -l app.kubernetes.io/name=falco
kubectl -n falco-system logs -l app.kubernetes.io/name=falco --tail=20
Vérification¶
# Declencher une alerte de test : shell dans un conteneur
kubectl run test-falco --image=busybox --restart=Never -- sleep 300
kubectl exec test-falco -- sh -c "cat /etc/shadow"
# Verifier que Falco a detecte l'evenement
kubectl -n falco-system logs -l app.kubernetes.io/name=falco | grep "test-falco" | tail -5
# Nettoyage
kubectl delete pod test-falco
Déploiement de OPA/Gatekeeper¶
Ajout du dépôt Helm¶
Valeurs de configuration¶
# gatekeeper-values.yaml
replicas: 2
# Activer le mode audit
audit:
# Frequence d'audit des ressources existantes
auditInterval: 300 # 5 minutes
# Nombre max de violations stockees par contrainte
constraintViolationsLimit: 20
# Webhook
webhook:
# Timeout du webhook (eviter les blocages)
timeoutSeconds: 10
# Metriques Prometheus
metricsBackends: ["prometheus"]
# Exempter les namespaces systeme
exemptNamespaces:
- kube-system
- gatekeeper-system
- falco-system
- monitoring
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
Installation¶
# Installer Gatekeeper
helm install gatekeeper gatekeeper/gatekeeper \
--namespace gatekeeper-system \
--create-namespace \
--values gatekeeper-values.yaml \
--wait
# Verifier
kubectl -n gatekeeper-system get pods
Déployer les contraintes essentielles¶
Contrainte : interdire les conteneurs privilegies¶
# template-privileged-container.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sdisallowprivileged
spec:
crd:
spec:
names:
kind: K8sDisallowPrivileged
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sdisallowprivileged
violation[{"msg": msg}] {
containers := array.concat(
object.get(input.review.object.spec, "containers", []),
object.get(input.review.object.spec, "initContainers", []))
container := containers[_]
container.securityContext.privileged == true
msg := sprintf("Conteneur privilegie interdit : %s", [container.name])
}
# constraint-no-privileged.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDisallowPrivileged
metadata:
name: no-privileged-containers
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces:
- kube-system
Autres contraintes recommandees¶
Suivez le même pattern (ConstraintTemplate + Constraint) pour ces cas courants :
| Contrainte | Objectif |
|---|---|
K8sAllowedRepos | Limiter les registres d'images autorises |
K8sRequireRunAsNonRoot | Exiger runAsNonRoot sur tous les conteneurs |
K8sDisallowHostNetwork | Interdire hostNetwork: true |
K8sRequireResourceLimits | Exiger des resources.limits sur chaque conteneur |
La Gatekeeper Library fournit des templates pre-écrits pour ces cas.
# Deployer les contraintes
kubectl apply -f template-privileged-container.yaml
kubectl apply -f constraint-no-privileged.yaml
# Verifier le status
kubectl get constrainttemplates
kubectl get constraints
Déploiement de Trivy Operator¶
Ajout du dépôt Helm¶
Valeurs de configuration¶
# trivy-operator-values.yaml
operator:
targetNamespaces: "" # vide = tous les namespaces
excludeNamespaces: "kube-system,gatekeeper-system,falco-system"
scanJobTTL: 300s
concurrentScanJobsLimit: 3
trivy:
mode: Standalone
severity: "CRITICAL,HIGH,MEDIUM"
ignoreUnfixed: false
vulnerabilityReportsPlugin: "Trivy"
configAuditReportsPlugin: "Trivy"
exposedSecretsScannerEnabled: true
serviceMonitor:
enabled: true
Installation¶
# Installer Trivy Operator
helm install trivy-operator aqua/trivy-operator \
--namespace trivy-system \
--create-namespace \
--values trivy-operator-values.yaml \
--wait
# Verifier
kubectl -n trivy-system get pods
Vérification¶
# Attendre que les premiers scans se terminent (quelques minutes)
kubectl get vulnerabilityreports -A --no-headers | head -10
# Voir le detail d'un rapport
kubectl get vulnerabilityreport -n default -o yaml | head -40
# Compter les CVE critiques
kubectl get vulnerabilityreports -A -o json | \
jq '[.items[].report.summary.criticalCount] | add'
Routage des alertes vers Loki/Grafana¶
Collecte des alertes Falco avec Alloy¶
Configurez Alloy pour collecter les logs Falco (stdout JSON) et les pousser vers Loki avec un tenant dedie security :
# Extrait de la configuration Alloy
discovery.kubernetes "falco_pods" {
role = "pod"
namespaces { names = ["falco-system"] }
selectors {
role = "pod"
label = "app.kubernetes.io/name=falco"
}
}
loki.source.kubernetes "falco_logs" {
targets = discovery.kubernetes.falco_pods.targets
forward_to = [loki.write.default.receiver]
}
loki.write "default" {
endpoint {
url = "http://loki-gateway.monitoring.svc:3100/loki/api/v1/push"
tenant_id = "security"
}
}
Dashboard pre-construit
Falco fournit un dashboard Grafana officiel (ID 11914). Importez-le depuis grafana.com/dashboards. Pour les dashboards et requêtes LogQL détaillés, voir le chapitre Integration.