Admission Control sorgt dafür, dass ein Pod gar nicht erst startet, wenn er gegen eine Policy verstößt. Damit endet die Kontrolle aber genau dort, wo der Container losläuft. Was ein Prozess zur Laufzeit tut, welche Dateien er öffnet oder ob jemand eine Shell im Container aufmacht, sieht ein Admission Controller nicht. Genau diese Lücke schließt Runtime Security, und Falco ist dafür das verbreitetste Open-Source-Werkzeug.
Was Falco eigentlich beobachtet
Falco liest Systemaufrufe mit. Jedes Mal, wenn ein Prozess eine Datei öffnet, eine Netzwerkverbindung aufbaut oder ein neues Programm ausführt, geht das über den Kernel. Falco hängt sich per eBPF an diesen Strom und wertet ihn gegen Regeln aus. Der Vorteil: Es braucht keine Änderung an den Anwendungen und keine Sidecars. Der Kernel liefert die Wahrheit, egal was im Container läuft.
Installation im Cluster
Falco läuft als DaemonSet, also ein Pod pro Node. Der schnellste Weg ist Helm.
helm repo add falcosecurity https://falcosecurity.github.io/chartshelm repo updatehelm install falco falcosecurity/falco \ --namespace falco --create-namespace \ --set driver.kind=modern_ebpf
modern_ebpf nutzt CO-RE, damit funktioniert der Treiber ohne Kernel-Header auf dem Node. Nach dem Rollout prüft man die Pods:
kubectl get pods -n falco -o wide
Wie eine Regel aussieht
Falco-Regeln sind YAML. Eine Regel besteht aus einer Bedingung, einer Ausgabe, einer Priorität und optional Tags. Eine der bekanntesten mitgelieferten Regeln schlägt an, wenn in einem Container eine Shell gestartet wird:
- rule: Terminal shell in container desc: A shell was spawned in a container with an attached terminal. condition: > spawned_process and container and shell_procs and proc.tty != 0 and container_entrypoint output: > Shell spawned in container (user=%user.name container=%container.name shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline) priority: NOTICE tags: [container, shell, mitre_execution]
Die Makros wie shell_procs und container_entrypoint kommen aus dem mitgelieferten Regelsatz. Man kombiniert sie, statt jedes Detail selbst auszuformulieren.
Eine eigene Regel schreiben
Angenommen, kein Pod im Namespace payments darf jemals eine Verbindung nach außen ins Internet aufbauen. Das lässt sich direkt als Regel formulieren:
- rule: Unexpected outbound connection from payments desc: A pod in the payments namespace opened an outbound connection. condition: > outbound and container and k8s.ns.name = "payments" and not fd.sip in (allowed_egress_ips) output: > Outbound connection from payments pod (pod=%k8s.pod.name dest=%fd.sip:%fd.sport image=%container.image.repository) priority: WARNING tags: [network, payments]- list: allowed_egress_ips items: ["10.0.0.0/8"]
Die Liste allowed_egress_ips trennt Konfiguration von Logik. Neue erlaubte Ziele pflegt man in die Liste, die Regel selbst bleibt unangetastet.
Alerts dahin bringen, wo sie gelesen werden
Falco allein schreibt nach stdout. Damit daraus eine Reaktion wird, braucht es Falcosidekick. Der nimmt die Events entgegen und leitet sie an Ziele wie Slack, Loki oder einen Webhook weiter.
helm upgrade falco falcosecurity/falco \ --namespace falco --reuse-values \ --set falcosidekick.enabled=true \ --set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/services/XXX"
Wichtig ist, von Anfang an zu filtern. Wer jede NOTICE-Regel nach Slack schickt, hat nach einem Tag einen Kanal, den niemand mehr liest. Sinnvoll ist, nur WARNING und höher zu routen und den Rest in ein durchsuchbares Backend zu schreiben.
Wo Falco aufhört
Falco erkennt Verhalten, es verhindert es nicht. Standardmäßig ist es ein Detektiv, kein Türsteher. Es gibt Ansätze, auf ein Event hin einen Pod zu killen, etwa über Falco Talon, aber das gehört bewusst getestet, sonst legt eine False-Positive-Regel im Zweifel die Produktion lahm. Der zweite Punkt: Regeln pflegen ist Arbeit. Der Standardsatz ist ein guter Start, produziert ohne Anpassung an die eigene Umgebung aber Rauschen. Ein Tag investierte Tuning-Arbeit entscheidet, ob das Team die Alerts ernst nimmt oder wegklickt.
Runtime Detection ist die logische Ergänzung zu Admission Control: das eine hält bekannte Fehlkonfigurationen vom Cluster fern, das andere meldet, wenn zur Laufzeit etwas Ungewöhnliches passiert. Wie sich beide Bausteine in eine durchgehende Supply-Chain- und Cluster-Absicherung einordnen, beschreibe ich ausführlicher auf digital-business.blog.
Hinterlasse einen Kommentar