Wir haben euch bereits in einem früheren TechUp Cilium vorgestellt. Es handelt sich dabei um ein eBPF-basiertes Networking, Observability und Security Tool, welches in allen cloud-native Umgebungen wie beispielsweise Kubernetes eingesetzt werden kann. 🐝
Heute möchte ich einen Teil von Cilium etwas genauer betrachten, nämlich Tetragon.
Bei Tetragon handelt es sich um einen Agent, welcher in jeder Linux-Umgebung laufen kann. Dabei spielt es keine Rolle, ob es sich um eine Kubernetes Umgebung handelt oder nicht. Tetragon nutzt dabei eBPF, um Daten auszulesen und diese in verschiedensten Formaten zur Verfügung zu stellen. Um welche Daten es sich dabei handelt, werden wir später noch im Detail sehen. Tetragon ist ein Cilium-Projekt, was aber nicht bedeutet, dass es Cilium unbedingt braucht. Wir können Tetragon ohne Probleme auch als “Standalone” installieren und werden dies in diesem TechUp auch tun. Vorerst will ich euch aber ein paar Fakten zu Tetragon geben. Der erste Commit im Github wurde erst am 11. Mai 2022 gemacht. Dies spiegelt aber nicht das wirkliche Alter des Projekts wider. Tetragon ist schon seit Jahren in Cilium Enterprise enthalten. Nun wurden aber Teile des Projekts open-source der Community zur Verfügung gestellt. Tetragon ist in C und Golang geschrieben und zählt Stand heute 35 Mitwirkende.
So funktioniert Tetragon im Hintergrund
Tetragon ist, wie oben bereits erwähnt, ein eBPF-basiertes Tool welches sich um Security Observability und Runtime Enforcement kümmert. Security Observability bedeutet dabei, dass bösartige Aktivitäten in Echtzeit erkannt werden und das Reporting stattfindet, sobald dieses Event passiert. Es geht sogar soweit, dass diese bösartigen Events verhindert werden, bevor sie Schaden anrichten können. Aber wie genau soll das funktionieren? Dazu nehmen wir uns das offizielle Schaubild von Tetragon zur Hilfe.
Figure: Quelle: https://isovalent.com/blog/post/2022-05-16-tetragon (aufgerufen am 07.10.2022)
Wie wir sehen können werden verschiedene Aktivitäten wie beispielsweise Prozessausführungen, Syscall-Aktivitäten, Dateizugriffe, Namespace-Escapes, Netzwerkaktivitäten und vieles weitere von Tetragon mittels eBPF überwacht und protokolliert. Das hört sich erstmal nach jeder Menge Overhead an, nicht wahr? Tetragon macht sich hier den sogenannten SmartCollector zu nutze. Dieser filter und aggregiert bereits im Kernel die notwendigen Informationen und sendet diese erst dann an den Tetragon Agent, welcher im Userspace läuft. All diese gesammelten Daten sind aber erst nützlich, wenn man sie auch verwenden kann. Der Tetragon Agent stellt dafür beispielsweise Integrationen zu Prometheus, Grafana, fluentd und anderen Systemen zur Verfügung. Ausserdem kann man sich die Daten per JSON exportieren, um diese zu verarbeiten. Tetragon kann aber nicht nur low-level Kernel Aktivitäten beobachten, sonder auch Function Calls, Code Executions oder den Einsatz vulnerabler Bibliotheken in der Applikation überwachen. Um diese Überwachung zu starten, sind keine Änderungen im Code notwendig, da alle Daten direkt im Kernel gesammelt werden.
Wenn Tetragon in einer Kubernetes-Umgebung verwendet wird, ist es Kubernetes-aware, was bedeutet, dass es alle Kubernetes Ressourcen wie Namespaces, Pods und so weiter versteht. Die Eventerkennung kann also im Hinblick auf individuelle Workloads granular konfiguriert werden.
Wer mehr über Kernel und Userspace erfahren möchte, dem lege ich Tom’s Techup über Cilium ans Herz. Er erklärt hier sehr genau die Unterschiede.
Schauen wir uns nun ein paar Beispiele dazu an!
Real-Time Runtime Enforcement
Schauen wir uns als nächstes an, wie wir Events nicht nur erkennen und reporten können, sondern diese mittels Tetragon direkt verhindern können. Dafür bietet uns Tetragon das bereits erwähnte Runtime Enforcement. Auch hier wollen wir uns wieder ein Schaubild zur Hilfe nehmen
Figure: Quelle: https://isovalent.com/blog/post/2022-05-16-tetragon (aufgerufen am 07.10.2022)
Wie wir sehen können, gibt es im Kernel eine Rule Engine, in der wir Richtlinien hinterlegen können, auf welche Datei beispielsweise die Schreibrechte eingeschränkt werden sollen. Die eBPF Kernel Runtime stellt dann sicher, dass diese Richtlinien eingehalten werden. Wenn eine Applikation gegen diese Richtlinie verstösst, so kann die Aktion direkt gestoppt oder die Applikation beendet werden.
Hier sehen wir, wie so eine Regel aussehen könnte, welche verhindert dass ein Container mit Root-Rechten ausgeführt wird.
|
|
Anwendung einer Richtlinie
Der Tetragon Agent bietet uns hier verschiedene Wege an, diese Sicherheitsrichtlinen einzuspielen. Im obigen Beispiel sehen wir eine Kubernetes CRD Richtlinie. Weiterhin wären beispielsweise auch JSON Richtlinien oder Richtlinien, die von Open Policy Agent (OPA) erstellt wurden als Input möglich. Was genau passiert aber nun, wenn wir so eine Regel anlegen?
Am besten sehen wir uns das anhand von einem kleinen Beispiel an. Dazu installieren wir uns erstmal Tetragon. Eine Anleitung hierzu ist auf der Github-Seite zu finden. Auf meinem Macbook mit M1 Max ARM64-Prozessor habe ich den Container mittels kind leider nicht zum Laufen gebracht. Ich musste daher auf die GCP-Variante ausweichen.
Sobald Tetragon läuft, installieren wir uns die Demo-Applikation von Cilium.
kubectl create -f https://raw.githubusercontent.com/cilium/cilium/v1.11/examples/minikube/http-sw-app.yaml
Diese installiert uns die folgenden 4 Pods:
|
|
Mit Tetragon Logs überprüfen
Schauen wir uns doch mal an, wie ein solches Event jetzt aussieht. Dazu öffnen wir ein Terminal-Fenster und überwachen dort die Logs von Tetragon.
kubectl logs -n kube-system -l app.kubernetes.io/name=tetragon -c export-stdout -f
In einem zweiten Fenster öffnen wir eine Shell in einem Pod und fragen dort einfach den aktuellen Benutzer mittels whoami
ab.
|
|
Wie wir sehen können erhalten wir als Event ein JSON-Objekt, welches verschiedenste Daten beinhaltet. Die Tetragon-CLI bietet ein Tool (observe
), mit welchem wir die wesentlichen Details herauslesen könnten.
Das JSON bezüglich der Bash sieht also folgendermassen aus:
|
|
Die wichtigsten Informationen, die auch observe
ausspucken würde, sind:
|
|
Wir sehen also, dass ein Prozess /bin/bash
im Namespace default
im Pod xwing
gestartet wurde. Über diese Bash wollen wir nun testen, ob es möglich ist, eine Datei zu bearbeiten.
|
|
Ich erstelle einen neuen Benutzer “test” und speichere die Datei ab. Nun wollen wir testen, ob die Änderungen tatsächlich übernommen wurden.
|
|
Natürlich wollen wir eine Änderung durch einen fremden Benutzer auf unserem System auf jeden Fall verhindern. Schauen wir uns nun also an, wie wir das mit Tetragon machen können.
Erstellen einer Tracing Policy
Wir erstellen uns hierfür eine Policy mit dem folgenden Inhalt. Mit dieser Policy wollen wir verhindern, dass jemand eine Datei im Ordner /tmp/forbidden
anlegen kann.
|
|
Im Wesentlichen passiert hier folgendes. Sobald ein Syscall __x64_sys_write
ausgeführt wird, wird geschaut, ob es sich dabei um ein “write” auf eine Datei im Ordner /tmp/forbidden
handelt. Ist dies der Fall, so soll das Sigkill
-Event ausgeführt werden, was in unserem Fall bedeutet, dass der Schreibprozess sofort beendet wird.
Testen der Tracing Policy
Um zu beweisen das unsere Policy auch funktioniert, legen wir uns als Erstes eine Datei an, welche wir später editieren.
|
|
Nun versuchen wir, die Datei zu editieren, aber erstmal ohne die angegebene Policy. Wir schreiben einfach “File changed” in die Datei und speichern und schliessen die Datei.
|
|
Wir können die Datei editieren und sehen unsere Änderungen, wenn wir diese wieder öffnen. Probieren wir das gleiche nun mit der oben gezeigten Policy. Wir führen dafür den folgenden Befehl auf unserem Host-System aus.
|
|
Anschliessend eröffnen wir wieder eine Bash-Shell im Container und versuchen, die Datei im /tmp
-Ordner zu editieren. Wir schreiben unter “File changed” einfach irgendwas drunter und versuchen, die Datei wieder zu speichern und zu schliessen.
|
|
Wie wir sehen können, wird der Schreibprozess sofort beendet. Unsere Policy erfüllt also wie gewünscht ihren Zweck. So sieht das ganze schön zusammengefasst und übersichtlich in der Tetragon-CLI aus:
|
|
Fazit
Mit Tetragon haben wir ein sehr mächtiges Mittel, um unsere Systeme direkt im Kernel abzusichern. Natürlich ist es für die Anwendung in Kombination mit Cilium nicht notwendig, Policies auf dieser Ebene zu definieren, aber es ist auf jeden Fall gut zu wissen, wie es funktioniert.
Wir bei b-nova werden uns auf jeden Fall in naher Zukunft weitere Projekte im Zusammenhang mit eBPF anschauen, also bleibe gespannt und folge unseren Social-Media Kanälen. Stay tuned! 🔥