Kubernetes static code analysis with Checkov

blank

Over the past few years, Kubernetes has emerged as the go-to for container orchestration, and yet Kubernetes security remains a challenge. We talk to teams every day that have clusters in production with no processes or tools for Kubernetes security—and we don’t blame them.

There are so many layers to Kubernetes security.

You have to analyze the security of your cloud or hosting environment, your host OS instances, the container images you’re placing into your cluster, the configuration of the resources you deploy, and finally, the security of your application code. That’s no small feat for even the most seasoned DevOps teams. We’re excited to help those teams tackle this problem so they can focus on building and shipping code.

Checkov, our open-source infrastructure-as-code analysis tool, now scans Kubernetes manifests and identifies security and configuration issues in Kubernetes workloads.

 

How it works

Checkov already covers infrastructure-as-code security scanning of Terraform and CloudFormation for AWS, Azure, and GCP, enabling you to catch infrastructure misconfigurations such as publicly exposed resources as well as helping maintain cloud security best practices.

With the addition of Kubernetes manifest scanning, you can now maintain security best practices for Kubernetes resources and catch issues such as over-privileged containers, bad image lifecycle practices, QoS and health check misconfiguration, and many more. Finding and preventing these issues as part of every build minimizes the risk of your workloads being compromised and saves time remediating issues in production.

In this post, we’ll walk you through using Checkov to scan sample Kubernetes manifests, but you can easily get started on your own project.

 

Installing Checkov

#install via pip:
pip install checkov

#install via homebrew:
brew tap bridgecrewio/checkov https://github.com/bridgecrewio/checkov
brew update
brew install checkov

Scanning for Kubernetes misconfigurations

Once installed, you can see the checks we run with:

checkov -l --framework kubernetes

Now point Checkov at some Kubernetes manifests and scan.

git clone https://github.com/kubernetes/examples

checkov -d examples/

View the results:

       _               _              
   ___| |__   ___  ___| | _______   __
  / __| '_ \ / _ \/ __| |/ / _ \ \ / /
 | (__| | | |  __/ (__|   < (_) \ V / 
  \___|_| |_|\___|\___|_|\_\___/ \_/  

by bridgecrew.io | version: 1.0.369

kubernetes scan results:

Passed checks: 1650, Failed checks: 2502, Skipped checks: 0

Check: CKV_K8S_27: "Do not expose the docker daemon socket to containers"
        PASSED for resource: Deployment.selenium-hub.default
        File: /staging/selenium/selenium-hub-deployment.yaml:1-37

Check: CKV_K8S_19: "Containers should not share the host network namespace"
        PASSED for resource: Deployment.selenium-hub.default
        File: /staging/selenium/selenium-hub-deployment.yaml:1-37

Check: CKV_K8S_8: "Liveness Probe Should be Configured"
        FAILED for resource: Pod.mongo.default (container 0)
        File: /staging/meteor/mongo-pod.json:22-36

                22 |       {
                23 |         "name": "mongo",
                24 |         "image": "mongo:latest",
                25 |         "ports": [
                26 |           {
                27 |             "name": "mongo",
                28 |             "containerPort": 27017
                29 |           }
                30 |         ],
                31 |         "volumeMounts": [
                32 |           {
                33 |             "name": "mongo-disk",
                34 |             "mountPath": "/data/db"
                35 |           }
                36 |         ]

Check: CKV_K8S_12: "Memory requests should be set"
        FAILED for resource: Pod.mongo.default (container 0)
        File: /staging/meteor/mongo-pod.json:22-36

                22 |       {
                23 |         "name": "mongo",
                24 |         "image": "mongo:latest",
                25 |         "ports": [
                26 |           {
                27 |             "name": "mongo",
                28 |             "containerPort": 27017
                29 |           }
                30 |         ],
                31 |         "volumeMounts": [
                32 |           {
                33 |             "name": "mongo-disk",
                34 |             "mountPath": "/data/db"
                35 |           }
                36 |         ]

Checkov identifies all passing and failing resources, including the file and lines in question for any issues. This allows you to address issues upfront before committing manifests to your source code repository or deploying in your cluster. Alternatively, you can run Checkov with GitHub Actions or in a CI/CD pipeline to block security issues from being deployed.

Suppressing checks

If a failed check doesn’t apply to your workload, you can suppress it for future scans. For example, the memory requests check above is not applicable if you wanted to run MongoDB with a QoS class of BestEffort.

To do that, use annotations with the check name and a suppression reason. Below is an example of using an annotation to suppress a check in examples/staging/meteor/mongo-pod.json:

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "mongo",
    "labels": {
      "name": "mongo",
      "role": "mongo"
    },
    "annotations": {
      "checkov.io/skip1": "CKV_K8S_12=QoS of BestEffort Desired"
    }
  },

This example is JSON, but the same approach applies to YAML. Retest the file using a single check to confirm it has been skipped:

checkov -f examples/staging/meteor/mongo-pod.json -c CKV_K8S_12
       _               _              
   ___| |__   ___  ___| | _______   __
  / __| '_ \ / _ \/ __| |/ / _ \ \ / /
 | (__| | | |  __/ (__|   < (_) \ V / 
  \___|_| |_|\___|\___|_|\_\___/ \_/  

by bridgecrew.io | version: 1.0.369

kubernetes scan results:

Passed checks: 0, Failed checks: 0, Skipped checks: 1

Check: CKV_K8S_12: "Memory requests should be set"
        SKIPPED for resource: Pod.mongo.default (container 0)
        Suppress comment: QoS of BestEffort Desired

File: examples/staging/meteor/mongo-pod.json:25-39

Kubernetes Cluster Resource Scanning

While we originally built Checkov for build-time static analysis, its application for Kubernetes is more extensive and unique. Because all Kubernetes resources deployed in a cluster can be described in code, you can also use Checkov in run-time for analyzing deployed Kubernetes resources. There are several ways to deploy Checkov in a Kubernetes environment. Here’s an example using a job:

kubectl apply -f https://raw.githubusercontent.com/bridgecrewio/checkov/master/kubernetes/checkov-job.yaml

Depending on the size of your cluster this may take 30+ seconds to execute.  You can check progress with the following:

kubectl get jobs -n checkov

Once completed, you can review the logs:

kubectl logs job/checkov -n checkov

And clean them up with:

kubectl delete -f https://raw.githubusercontent.com/bridgecrewio/checkov/master/kubernetes/checkov-job.yaml

Unifying Kubernetes build-time scan results with run-time scanning

We built and open-sourced Checkov to make infrastructure-as-code scanning straightforward and accessible to all. To take that to the next level, the Bridgecrew platform (which is free to use up to 100 cloud resources) automates remediation in code.

By unifying run-time and build-time scanning, Bridgecrew enables you to fix cloud misconfigurations at the source to keep them from resurfacing down the road.

Next Steps

In the coming weeks, we’ll be adding more Kubernetes checks as well as adding support for other templating tools such as Helm and Kustomize.

Check out our docs for a complete guide to getting started with Checkov. We hope you give it a try and that it helps you gain visibility into the security of your Kubernetes workloads. Feel free to reach out to us on Slack with any Checkov feedback—and don’t forget to give it a ⭐️  on GitHub!