Falco - Container Native Runtime Security
)
In der modernen Welt von Kubernetes, bei der Entwickler immer mehr Rechte über komplette Systeme (Container) bekommen, ist es wichtig, auch ein entsprechendes System zur Überprüfung der Aktivitäten auf einem Cluster zu implementieren. Falco ist hierbei ein idealer Kandidat. Doch was genau kann ich mit Falco alles überwachen?
Features
Falco hängt sich direkt an den Kernel und kann so auf alle Ereignisse reagieren, die einen Linux Sys-Call ausgelöst haben. Somit ist Falco nicht von einer eigenen Implementierung abhängig, sondern funktioniert auch mit bestehenden Anwendungen. Als Beispiele seien hier folgende Events aufgeführt:
Eine Shell wird in einem Container ausgeführt
Ein Server Prozess startet einen Child Prozess mit einem unerwarteten Typ
Eine sensitive Datei, z.B. /etc/shadow wird gelesen / geschrieben
Eine "non-device" Datei wird unter /dev geschrieben
Eine Standart Systemkomponente (z.B. ls) startet eine ausgehende Netzwerkverbindung
Zusätzlich kann Falco so Konfiguriert werden, dass es die Kubernetes Audit-Logs bekommt und so einen noch tieferen Einblick in das System bekommt.
Installation
Die Installation gestaltet sich denkbar einfach. Im Kern ist Falco ein Daemonset, welches somit auf jeder Node in deinem Cluster läuft. Die genaue Installationsanleitung ist in der Dokumentation zu finden.
Grundlegend sind folgende Schritte Notwendig:
Clone des Repositories / Wechsel in das entsprechende Verzeichnis:
git clone https://github.com/falcosecurity/falco/ && cd falco/integrations/k8s-using-daemonset
Falco Serviceaccount:
kubectl apply -f k8s-with-rbac/falco-account.yaml
Falco Service:
kubectl apply -f k8s-with-rbac/falco-service.yaml
Erforderliche Konfigurationen in ein neues Verzeichnis kopieren:
mkdir -p k8s-with-rbac/falco-config cp ../../falco.yaml k8s-with-rbac/falco-config/ cp ../../rules/falco_rules.* k8s-with-rbac/falco-config/ cp ../../rules/k8s_audit_rules.yaml k8s-with-rbac/falco-config/
ConfigMap erzeugen:
kubectl create configmap falco-config --from-file=k8s-with-rbac/falco-config
Falco DaemonSet:
kubectl apply -f k8s-with-rbac/falco-daemonset-configmap.yaml
Anschließend sollte Falco starten, die Nodes entsprechend so anpassen, dass die Kernel Events ausgelesen werden können und anschließend alle Events loggen können. Somit haben wir den ersten Part der Installation abgeschlossen.
Integration der Kubernetes Audit Logs
Die Audit Logs müssen nun in einem weiteren Step konfiguriert werden. Dazu nutzt Falco die in Kubernetes implementierte dynamische AuditSink Konfiguration. Da der Kubernetes API Server NICHT mit Kubernetes internen Services sprechen kann, muss das Logging an eine statische IP Adresse gesendet werden. Diese Konfiguration wird anhand eines Templates unter /examples/k8s_audit_config/ wie folgt erstellt:
FALCO_SERVICE_CLUSTERIP=$(kubectl get service falco-service -o=jsonpath={.spec.clusterIP}) envsubst < webhook-config.yaml.in > webhook-config.yaml
Um die Konfiguration zu aktivieren, wird ein kleines Hilfsscript verwendet:
bash ./enable-k8s-audit.sh <variant> dynamic
Hierbei wird für <variant>
je nach Installationsart kops oder minikube eingesetzt. Für andere Installationen müssen die Änderungen händisch vorgenommen werden. Für kops muss zusätzlich der API-Server Host angegeben werden: APISERVER_HOST=api.my-kops-cluster.com.
Verwendung von Falco
Alle Events von Falco landen standardmäßig in den Logs der Container. Erweitert werden kann das ganze über z.B. Webhooks oder andere Backends. Um sich für alle Nodes die Logs anschauen zu können, nutzen wir bei kubectl logs die Möglichkeit, anhand eines Labels zu loggen. Somit erhalten wir die Logs von allen laufenden Containern:
kubectl logs -l app=falco
In den Logs seht ihr anhand der Example Kubernetes Konfiguration, welche von Falco mitgeliefert wird, nun z.B. folgende Ausgaben in den Container Logs. Auf diese könnte man in weiteren Schritten entsprechend reagieren.
11:15:41.410620639: Notice A shell was spawned in a container with an attached terminal (user=root k8s.ns=cloudpirate k8s.pod=cloudpirate-deployment-88dc64d88-frf62 container=01da62e24137 shell=bash parent=docker-runc cmdline=bash terminal=34816 container_id=01da62e24137 image=hdcms/client) k8s.ns=cloudpirate k8s.pod=cloudpirate-deployment-88dc64d88-frf62 container=01da62e24137
11:15:41.171320064: Notice Attach/Exec to pod (user=kubecfg pod=cloudpirate-deployment-88dc64d88-frf62 ns=cloudpirate action=exec command=bash)
Critical File Edit
11:17:14.817387894: Error File created below /dev by untrusted program (user=root command=touch unexpected-file file=/dev/unexpected-file container_id=01da62e24137 image=hdcms/client) k8s.ns=cloudpirate k8s.pod=cloudpirate-deployment-88dc64d88-frf62 container=01da62e24137 k8s.ns=cloudpirate k8s.pod=cloudpirate-deployment-88dc64d88-frf62 container=01da62e24137
Ich hoffe dieser kleine Einstieg zeigt das Potenzial von Falco, seine Anwendungen und Cluster zu überwachen. Besonders interessant dabei finde ich, dass ohne Änderungen an den laufenden Pods eine Überwachung möglich ist. Somit kann dieses System sehr einfach in bestehende Kubernetes Cluster eingesetzt werden.