Falco on Azure AKS for Runtime Security Monitoring
Falco’s most surprising true capability is its ability to detect threats before they become breaches by analyzing system calls and network activity in real-time, acting as a tripwire for your containerized workloads.
Let’s see Falco in action. Imagine you have a suspicious process trying to execute a shell within a Kubernetes pod.
apiVersion: v1
kind: Pod
metadata:
name: suspicious-pod
spec:
containers:
- name: main-container
image: ubuntu:latest
command: ["/bin/sh", "-c", "sleep infinity"]
When you deploy this pod and then try to exec into it and run an unauthorized command like cat /etc.shadow, Falco, running as a DaemonSet on your AKS cluster, will immediately generate an alert.
Here’s a simplified Falco rule that would trigger on such an event:
- rule: Execute Shell in Container
desc: Detect any shell being executed inside a container.
condition: container and proc.name = "sh"
output: Shell executed in container (user: %user.name, cmd: %proc.cmdline, container: %container.name)
priority: WARNING
When this rule is triggered, Falco will output a message like:
10:30:00.123456789 - Warning - Shell executed in container (user: root, cmd: /bin/sh, container: suspicious-pod)
This alert is generated because Falco is instrumenting the kernel (or a userspace agent) to capture every system call. When the execve system call occurs for a process named sh within a containerized environment, this rule matches. The container condition ensures we only alert on activity within pods, not on the host itself.
To get Falco running on Azure AKS, you’ll typically deploy it as a Helm chart. The installation process involves adding the Falco Helm repository and then installing the chart with specific configurations for your AKS environment.
helm repo add falco https://falcosecurity.github.io/charts
helm repo update
helm install falco falco/falco \
--namespace monitoring \
--create-namespace \
--set falco.jsonOutput=true \
--set falco.logLevel=info \
--set nodeagent.enabled=true \
--set driver.kind=module # or "ebpf" depending on your kernel and preference
The nodeagent.enabled=true flag ensures Falco runs as a DaemonSet, deploying a Falco instance on each AKS node. The driver.kind specifies how Falco interfaces with the kernel; module uses the kernel module, while ebpf uses eBPF, which can be more robust and doesn’t require kernel module compilation. falco.jsonOutput=true is crucial for integrating with systems like Azure Monitor or other SIEMs.
Internally, Falco works by reading a stream of system calls. It then applies a set of rules written in a declarative language. These rules define patterns of system call sequences and properties of the processes generating them. When a pattern matches, Falco triggers an output, which can be a log message, a webhook, or an alert sent to a monitoring system. The power lies in the richness of the data it can access – from process ancestry to file access and network connections.
The Falco rules engine is remarkably efficient. It doesn’t just look at individual system calls; it can track state across multiple calls. For example, a rule might alert if a shell is executed and that shell then attempts to open a file in /etc. This stateful analysis allows for detection of complex attack chains that simpler signature-based tools would miss. The rules are evaluated in a way that minimizes overhead, ensuring minimal impact on your cluster’s performance.
One of the most powerful, yet often overlooked, aspects of Falco is its ability to leverage custom rules. While the default rules cover many common threats, tailoring Falco to your specific application’s behavior can unlock its full potential. For instance, you might want to alert on any unexpected network connections from your database pods, or detect when a specific configuration file is modified by a process other than your deployment controller. This requires understanding your application’s normal operational patterns and translating them into Falco’s rule syntax, which often involves looking at the proc.name, fd.name, and net.addr fields.
The next crucial step after setting up Falco is integrating its alerts into your incident response workflow, likely by forwarding them to Azure Sentinel or another SIEM.