Boost Kubernetes Security with KubeSec: Best Practices and Implementation
Updated: Nov 5
Kubesec is an open-source Kubernetes security scanner and analysis tool. It scans your Kubernetes
cluster for common exploitable risks such as privileged capabilities and provides a severity score for each
found vulnerability.
Security risk analysis for Kubernetes resources.
• Take in a single YAML file as input.
• One YAML can connect multiple Kubernetes resources.
Kubesec is available as:
• Docker container image at docker.io/kubesec/kubesec:v2
• Linux/MacOS/Win binary (get the latest release)
• Kubernetes Admission Controller
• Kubectl plugin
Keep your cluster secure and follow me on a brief demo!
First things first, we are going to define a bash script which is going to perform the scans on our yaml file
by calling the KubeSec API.
1) Execute touch kubesec-scan.sh
2) Create our risky deployment! execute another touch command as follows:
touch insecure-deployment.yaml
Then, paste the following content (make sure you are using your image, it also can be a testing one.
e.g public.ecr.aws/docker/library/node:slim):
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: devsecops
name: devsecops
spec:
replicas: 2
selector:
matchLabels:
app: devsecops
strategy: {}
template:
metadata:
labels:
app: devsecops
spec:
volumes:
- name: vol
emptyDir: {}
containers:
- image: replace
name: devsecops-container
volumeMounts:
- mountPath: /tmp
name: vol
3) Back to our bash script, define some variables for a later usage, here we are going to make use of the KubeSec API.
Open the newly created file with your preferred text editor and paste the following:
#!/bin/bash
# KubeSec v2 api
scan_result=$(curl -sSX POST --data-binary @"insecure-deployment.yaml" https://v2.kubesec.io/scan) scan_message=$(curl -sSX POST --data-binary @"insecure-deployment.yaml" https://v2.kubesec.io/scan | jq .[0 scan_score=$(curl -sSX POST --data-binary @"insecure-deployment.yaml" https://v2.kubesec.io/scan | jq .[0].
# Kubesec scan result processing
# echo "Scan Score : $scan_result"
3) Alright! in the previous step we made some interesting calls to the KubeSec API, the first variable output is a big JSON object (we can see it if we uncomment the echo at the end of the script).
Then, on the next two variables (since it's a json object) we are using jq CLI, a powerful and lightweight command-line JSON processor. Making use of it, we extract the scanning message and score.
4) We continue with the script edition, now it's time to log some exciting stuff!
Add the following to our bash script:
if [[ "${scan_score}" -ge 5 ]]; then
echo "Score is $scan_score"
echo "Kubesec Scan $scan_message"
else
echo "Score is $scan_score, which is less than or equal to 5."
echo "Scanning Kubernetes Resource has Failed"
exit 1;
fi;
This last section of the script is a basic bash conditional were we are checking the scan_score variable. If its greater or equal than 5 then is going to “pass” our requirements. Otherwise is going to fail.
Note: Choose some relevant score numbers based on your application requirements. This example is just for demo purposes and not meant to run on production environments.
The final script will look like this:
#!/bin/bash
# KubeSec v2 api
scan_result=$(curl -sSX POST --data-binary @"insecure-deployment.yaml" https://v2.kubesec.io/scan) scan_message=$(curl -sSX POST --data-binary @"insecure-deployment.yaml" https://v2.kubesec.io/scan | jq .[0].me scan_score=$(curl -sSX POST --data-binary @"insecure-deployment.yaml" https://v2.kubesec.io/scan | jq .[0].scor
# Kubesec scan result processing
# echo "Scan Score : $scan_result"
if [[ "${scan_score}" -ge 5 ]]; then
echo "Score is $scan_score"
echo "Kubesec Scan $scan_message"
else
echo "Score is $scan_score, which is less than or equal to 5."
echo "Scanning Kubernetes Resource has Failed"
exit 1;
fi;
Alternatively run it with docker as follows:
#!/bin/bash
scan_result=$(docker run -i kubesec/kubesec:512c5e0 scan /dev/stdin < insecure-deployment.yaml) scan_message=$(docker run -i kubesec/kubesec:512c5e0 scan /dev/stdin < insecure-deployment.yaml | jq .[].messag scan_score=$(docker run -i kubesec/kubesec:512c5e0 scan /dev/stdin < insecure-deployment.yaml | jq .[].score)
5) Time to see the power of the KubeSec scans! Execute the script.
The output shows
Which means… there are some security improvement opportunities.
At this point, we begin to see the potentially integrations within our DevSecOps pipeline (see the extras section for a Jenkins example).
6) KubeSec made a good job by scanning our deployment. But… How do we leverage the security opportunities?
If we go a few steps back, and we uncomment this line # echo "Scan Score : $scan_result"
We are going to be able to see (under the scoring, advice section) an array of security items, their value in points and reason, among others. This is going to be a key component of our scans.
Now we can take action. See the screenshot below.
7) Lets make some updates to our insecure deployment, under containers add the following:
securityContext:
runAsNonRoot: true
runAsUser: 100
readOnlyRootFilesystem: true
And under the spec section:
serviceAccountName: default
Finally, run the script once again and verify the new score.
You should see something like this
Awesome! with just a few steps we improve our kubernetes deployment security!
Extra: Try integrating the solution on your DevSecOps pipeline!
Below is an example on a Jenkinsfile
pipeline {
agent any
stages {
stage('Vulnerability Scan - Kubernetes') {
steps {
sh "bash kubesec-scan.sh"
}
}
}
}
To read more about security best practices for Kubernetes deployments: https://kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/
References:
https://kubesec.io/
https://www.jenkins.io/doc/book/pipeline/
Tomás Torales
Cloud Engineer
Teracloud
If you want to know more about Security, we suggest checking Streamlining Security with Amazon Security Hub