Falco on Kind with Prometheus and Grafana

March 19, 2020  —  Leonardo Grasso

Kind is a tool for running local Kubernetes clusters using Docker container “nodes”, that may be used for local development or CI. It also offers a convenient and easy way to install Falco in a Kubernetes cluster and play with it locally. We will use Kind to show how to export Falco metrics to Prometheus and Grafana.

Create a Kind cluster

Running Falco in a Kind cluster is easy, as explained in the documentation.

If you want to use the kernel module, basically, you only have to mount /dev.

Note that it’s not mandatory to mount the entire /dev path. Falco just needs access to some devices created by the kernel module:

$ ls -l /dev/falco*
cr-------- 1 root root 238, 0 Mar 12 16:04 /dev/falco0
cr-------- 1 root root 238, 1 Mar 12 16:04 /dev/falco1
cr-------- 1 root root 238, 2 Mar 12 16:04 /dev/falco2
cr-------- 1 root root 238, 3 Mar 12 16:04 /dev/falco3
cr-------- 1 root root 238, 4 Mar 12 16:04 /dev/falco4
cr-------- 1 root root 238, 5 Mar 12 16:04 /dev/falco5
cr-------- 1 root root 238, 6 Mar 12 16:04 /dev/falco6
cr-------- 1 root root 238, 7 Mar 12 16:04 /dev/falco7

As you can see, the kernel module is creating one device per CPU (8 in my case). These paths are all Falco needs.

Certificates

To export metrics to Prometheus, we will use falco-expoter which connects to the Falco gRPC output. The Falco gRPC server works only with mutual TLS by design. Therefore, you also need valid certificate files to configure Falco and falco-exporter properly.

You can quickly generate cert materials using falcoctl:

FALCOCTL_NAME=falco-grpc.default.svc.cluster.local FALCOCTL_PATH=/tmp/certs falcoctl install tls 

Otherwise you can manually generate them as explained here.

Note that in both cases, you have to make sure to set the correct CommonName. In this example, we are using the default hostname used by the Helm chart.

Install Falco

The official Falco Helm Chart is a straightforward way to deploy Falco. The chart adds Falco to all nodes in your cluster using a DaemonSet.

Be sure to include TLS cert material and enable the gRPC output:

helm install falco stable/falco \
    --set-file certs.server.key=/tmp/certs/server.key,certs.server.crt=/tmp/certs/server.crt,certs.ca.crt=/tmp/certs/ca.crt \
    --set falco.grpc.enabled=true,falco.grpcOutput.enabled=true

Install falco-exporter

falco-exporter is the Prometheus metrics exporter for Falco output events. Again here, using the provided Helm chart is the easiest way to deploy it.

So you only have to clone the falco-exporter repo and run helm install command:

$ git clone https://github.com/falcosecurity/falco-exporter.git
Cloning into 'falco-exporter'...
remote: Enumerating objects: 178, done.
remote: Counting objects: 100% (178/178), done.
remote: Compressing objects: 100% (103/103), done.
remote: Total 178 (delta 64), reused 129 (delta 38), pack-reused 0
Receiving objects: 100% (178/178), 693.25 KiB | 1.92 MiB/s, done.
Resolving deltas: 100% (64/64), done.

$ cd falco-exporter

$ helm install falco-exporter \
    --set-file certs.ca.crt=/tmp/certs/ca.crt,certs.client.key=/tmp/certs/client.key,certs.client.crt=/tmp/certs/client.crt \
    ./deploy/helm/falco-exporter

Install Prometheus

Once Falco and the exporter are up and running, we can proceed by installing Prometheus:

helm install prom stable/prometheus

Then we have to wait for Prometheus to set up and run:

export POD_NAME=$(kubectl get pods --namespace default -l "app=prometheus,component=server" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace default port-forward $POD_NAME 9090

So we can open http://localhost:9090/targets and check that falco-exporter has been discovered by Prometheus.

Install Grafana and the Falco dashboard

To deploy Grafana, just run:

helm install grafana stable/grafana

Then get your ‘admin’ user password by running:

kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

When Grafana is up and running, port forward the Grafana service:

kubectl port-forward service/grafana 3000:80

To log in to Grafana, open http://127.0.0.1:3000/login and use the ‘admin’ user password you got above.

Now you can add the Prometheus endpoint (http://prom-prometheus-server.default.svc.cluster.local) to the Grafana data sources and finally go to http://127.0.0.1:3000/dashboard/import and import the Falco dashboard by copy-paste the following dashboard URL:

https://grafana.com/grafana/dashboards/11914

Otherwise, you can use the provided dashboard.json.

Falco dashboard

Now we can generate events to see the system in action!

Generate events

There are many ways to demonstrate a Falco rule has been violated, and if you have loaded the default Falco ruleset here are some fun things to try.

A simple one line example is to create an alert is to touch a file in a well known executable directory. Also, you can cat or touch files in other potentially vulnerable directories as well.

Common one-liners

touch /usr/local/bin/example-violation
touch /usr/bin/example-violation
cat /etc/shadow
touch /etc/example-violation

You can find the default ruleset here.

Fun with privileged mode

You can see the demo that Kris Nóva gave at FOSDEM and find the function shell() that she used defined below.

function shell () {
  kubectl run shell --restart=Never -it --image krisnova/hack:latest \
  --rm --attach \
  --overrides \
        '{
          "spec":{
            "hostPID": true,
            "containers":[{
              "name":"scary",
              "image": "krisnova/hack:latest",
	      "imagePullPolicy": "Always",
              "stdin": true,
              "tty": true,
              "command":["/bin/bash"],
	      "nodeSelector":{
		"dedicated":"master" 
	      },
              "securityContext":{
                "privileged":true
              }
            }]
          }
        }'
}

You can paste this into a new file shell.sh and source the file.

source shell.sh

Then you can type the following to demonstrate a privilege escalation in Kubernetes.

[user@user]$ shell
If you don't see a command prompt, try pressing enter.
root@shell:/# nsenter -t 1 -m -u -i -n bash
root@ip-1-2-3-4:/# 

Doing this takes advantage of a well known security exploit in Kubernetes, and you can find the Falco alerts rendered in Prometheus/Grafana.

Falco events generator

You can find more information on generating sample events in the official documentation

For a quick example, you can run the following command to begin generating events

docker run -it --rm falcosecurity/falco-event-generator event_generator