
Kubernetes Response Engine, Part 4: Falcosidekick + Tekton
This blog post is part of a series of articles about how to create a
Kubernetes
response engine withFalco
,Falcosidekick
and aFaaS
.See other posts:
- Kubernetes Response Engine, Part 1 : Falcosidekick + Kubeless
- Kubernetes Response Engine, Part 2 : Falcosidekick + OpenFaas
- Kubernetes Response Engine, Part 3 : Falcosidekick + Knative
- Kubernetes Response Engine, Part 5 : Falcosidekick + Argo
- Kubernetes Response Engine, Part 6 : Falcosidekick + Cloud Run
- Kubernetes Response Engine, Part 7: Falcosidekick + Cloud Functions
Falcosidekick + Tekton
Earler in this series we have seen how to use Kubeless, OpenFaas and Knative to trigger a pod after getting input from falcosidekick to delete a compromised pod.
In this part I will showcase how we can use Tekton and not have to add any extra complexity to your cluster by adding a serverless runtime.
I won't go through how Tekton works in depth but, you can find a good overview in the official docs. But here is the crash course:
- Tekton is built to be reusable.
- The smallest part of tekton is a step, a step can be something like this:
- Run unit tests
- Run linting
- In a task you can have multiple steps.
- A pipeline consist of one or multiple tasks.
- To trigger a pipeline to actually run you need a pipelinerun or a trigger-template.
Tekton also supports eventlisteners that is used to listen for webhooks. Normally these webhooks listen for incoming changes to a git repo, for example a PR. But we will use it to listen for Falco events.
You can find all the yaml and code in my repo.
Prerequisites
As always within Kubernetes we need a few tools, I have used the following versions of Helm, Minikube and kubectl in my setup.
- Minikube v1.19.0
- Helm v3.4.2
- kubectl v1.20.5
Provision local Kubernetes Cluster
I'm sure you can use a kind cluster as well to follow along, but falco complained a bit when I tried and I was too lazy to check out what extra flags I need so I went with minikube.
Install Tekton
Install Tekton pipelines and triggers. When doing this in production I recommend the Tekton operator but for now let us use some pure yaml.
Within a few seconds you should be able to see a few pods in the tekton-pipelines namespace.
If you want a deeper understanding how Tekton triggers work check out the getting-started guide.
Install Falco + Falcosidekick
Create the falco namespace and add the helm repo:
For simplicity and long term usability let us create a custom values file and start falco.
Note the customRules and the webhook address.
We haven't setup this webhook address nor is there currently any reason for us to have customRules for eventlistenersink or poddeleter, but it will come. Both the Tekton event listener and my poddeleter does a few kubernetes API calls and we don't want falco generate alarms for our own infrastructure.
You should be able to see falco and falcosidekick pods in the falco namespace:
Protect me Falco
My current setup is rather harsh and will delete any pods that breaks any falco rule. In the future I plan to make both the go code and the tekton setup better and more flexible, hopefully this is something that we can do in the community.
During this demo I will use the Terminal Shell in container since it's very easy to reproduce.
So how does all this work?
- We start a random pod and perform a simple exec.
- Falco will notice that a pod have broken the rule
- Sends an event to Falcosidekick
- Sends a webhook to tekton event-listener
- Tekton triggers a new pipeline
- A task is started with a small go program that deletes the pod
So let us look at some yaml.
The go code
I have adapted the code that Batuhan Apaydın wrote in Falcosidekick + OpenFaas = a Kubernetes Response Engine, Part 2 to listen for json in an environment variable instead of a http request.
Below you can see the code, in short it does the following:
- Check for environment variable BODY.
- Unmarshal the data according to the Alert struct.
- Setups a kubernetes client, by calling setupKubeClient function.
- Calls the deletePod with a kubernetes client, the falcoEvent we gotten and a hash map of critical Namespaces.
- Check in the event that we got from falcosidekick and see if the pod that triggered the event is in our critical namespaces hash map.
- If it is return to the main and shutdown the application.
- Else deletes the pod in the namespace specified in the falcosidekick event.
If you rather see it in github.
Now that you know what I will make run in your cluster let us take a look at the Tekton yaml.
Tekton pipeline
Create the falcoresponse namespace to do our tests in.
Task
So let us start with the smallest part, the task.
- The task needs a input variable falco-event.
- The step called pod-delete uses the poddeleter image.
- Step pod-delete sets the environment BODY from the input parameter called falco-event.
Pipeline
Here you can see the reusability of tekton. This pipeline can easily add more tasks and other pipelines can use the exact same task as this one.
Just like the task this pipeline expects a parameter called falco-event which it sends in to the pod-delete task.
RBAC
We will be using two separate serviceAccounts, one for the event-listener and one for the poddeleter it self.
So let us create these serviceAccounts and give them some access.
Below you can find the event listener RBAC config.
And here is the poddeleter serviceAccount:
Event listener
Finally time to configure the tekton webhook receiver. Just like rest of Tekton the event listener builds on multiple parts.
It is possible to expose a event listener using a ingress, this is a rather normal use case if you want github to trigger a pipeline for example.
I cannot stress this enough DO NOT MAKE THE EVENT LISTENER PUBLIC TO THE INTERNET. We haven't added any protection and this task have the power to kill pods in your cluster. Don't give a potential hacker this power!
The event listener is rather complex and can do allot. For example one way to improve this tekton pipeline could be to check for a specific Priority from Falco. This could be done with a cel interceptor and filter on body.Priority.
But for now let us just trigger on everything.
The triggerBinding let us you define what data should be gathered from the incoming webhook. In this case I take the entire request body.
We use the TriggerTemplate to call on the pipeline that we defined earlier using the parameter that the TriggerBinding gives us.
Notice the annotations, without it the pipeline will never get triggered.
We define the serviceAccount to use in our pipeline/task, point to the pipeline that we should use. And what parameter to send down to the pipeline, notice the tt in front of parma. This is special syntax for TriggerBindings.
The triggerTemplate was the final piece needed and you should see a pod spinning up in the falcoresponse namespace.
Trigger job
Finally it's time to test our setup.
I would recommend that you start a second terminal for this part.
Terminal 1 follow the falco logs:
Terminal 2 let us trigger the Terminal Shell in container falco rule
In Terminal 1 you should see something like this:
In Terminal 2 you should see a pod starting and hopefully Complete without any errors and the alpine pod getting killed.
Hurray our "hacked" pod have been killed
If you look in the logs of the task
Conclusion
This was a rather simple example on how we can use the power of tekton together with Falco to protect us from bad actors that is trying to take over pods in our cluster.
As noted during this post there are a lot of potential improvements before this is production ready:
- The criticalNamespaces in our go code is currently hard-coded and needs to be input variable of some kind.
- We need to be able to delete pods depending on priority level, rule or something similar.
- To be able to debug pods we might need to shell in to them, we need a way to ignore pods temporary without the pod getting restarted. Probably a annotation to look for in the pod before deleting it.
- And probably many other needs that you can come up with.
If you have any ideas/issues come and share them in the falco slack https://kubernetes.slack.com #falco.
Tekton
If you would like to find out more about Tekton:
- Get started in tekton.dev.
- Check out the Tekton Project in GitHub.
- Meet the maintainers on the TektonCD Slack.
- Follow @tektoncd on Twitter.
Falco
If you would like to find out more about Falco:
- Get started in Falco.org.
- Check out the Falco project in GitHub.
- Get involved in the Falco community.
- Meet the maintainers on the Falco Slack.
- Follow @falco_org on Twitter.