How to Use Kube-bench to Audit Kubernetes Security Against CIS Benchmarks

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Your Kubernetes Cluster Runs Smoothly, but Is It Truly Secure?

Once a Kubernetes cluster is up, pods are running smoothly, and Ingress routes traffic properly, most engineers breathe a sigh of relief. I used to be the same way. But after a test server got hit by an automated SSH brute-force attack via an exposed port at 2 AM, I learned a crucial lesson: a working system is never guaranteed to be a secure system.

By default, Kubernetes prioritizes ease of use during initial setup. Configuration files for kube-apiserver, kubelet, or etcd often come with overly permissive file permissions (such as 644 or 777). If a web pod suffers an RCE vulnerability, an attacker could read service account tokens, exploit exposed API ports, and take full control of the entire cluster. To remediate these configuration vulnerabilities, we need an automated and reliable auditing tool.

What Are CIS Kubernetes Benchmark and Kube-bench?

To audit effectively, you first need to understand these two foundational resources:

  • CIS Kubernetes Benchmark: A 200+ page guide published by the Center for Internet Security. It defines comprehensive security best practices and configuration standards for the Control Plane, etcd, Worker Nodes, and authentication mechanisms.
  • Kube-bench: An open-source Go tool developed by Aqua Security. Kube-bench checks node configurations, file permissions, and process parameters against CIS standards, generating a detailed report in just 10–15 seconds.

Hands-on: Auditing Kubernetes Security with Kube-bench

Depending on your cluster architecture (self-managed with kubeadm or managed services like EKS and GKE), you can choose one of the two methods below.

Method 1: Running Kube-bench as a Kubernetes Job (Recommended)

This method allows you to quickly scan your cluster directly via kubectl without needing SSH access to each node.

Create the manifest file job-kube-bench.yaml:

cat <<EOF > job-kube-bench.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: kube-bench
spec:
  template:
    spec:
      hostPID: true
      nodeSelector:
        node-role.kubernetes.io/control-plane: ""
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
      containers:
        - name: kube-bench
          image: aquasec/kube-bench:latest
          command: ["kube-bench"]
          volumeMounts:
            - name: var-lib-etcd
              mountPath: /var/lib/etcd
              readOnly: true
            - name: var-lib-kubelet
              mountPath: /var/lib/kubelet
              readOnly: true
            - name: etc-systemd
              mountPath: /etc/systemd
              readOnly: true
            - name: etc-kubernetes
              mountPath: /etc/kubernetes
              readOnly: true
            - name: usr-bin
              mountPath: /usr/local/mount-from-host/bin
              readOnly: true
      restartPolicy: Never
      volumes:
        - name: var-lib-etcd
          hostPath:
            path: /var/lib/etcd
        - name: var-lib-kubelet
          hostPath:
            path: /var/lib/kubelet
        - name: etc-systemd
          hostPath:
            path: /etc/systemd
        - name: etc-kubernetes
          hostPath:
            path: /etc/kubernetes
        - name: usr-bin
          hostPath:
            path: /usr/bin
EOF

Deploy the Job and view the logs:

# Create the scan Job
kubectl apply -f job-kube-bench.yaml

# Wait for the Pod to complete
kubectl wait --for=condition=complete job/kube-bench --timeout=60s

# View the scan report
kubectl logs job/kube-bench

Method 2: Running the Binary Directly on Master / Worker Nodes

For bare-metal servers or self-managed VMs, running the standalone binary is the most straightforward way to audit each node individually.

# Download the latest release
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.8.0/kube-bench_0.8.0_linux_amd64.tar.gz -o kube-bench.tar.gz
tar -xvf kube-bench.tar.gz

# Audit the Control Plane node
sudo ./kube-bench run --targets master

# Audit the Worker node
sudo ./kube-bench run --targets node

Understanding Results and Remediating FAIL Warnings

Kube-bench categorizes scan results into four statuses:

  • [PASS]: Complies with CIS benchmarks.
  • [FAIL]: Critical security issue that requires immediate attention.
  • [WARN]: Warning that should be reviewed based on your specific use case.
  • [INFO]: Informational item for reference.

Beneath every FAIL item, Kube-bench provides a == Remediation == block with specific remediation steps. Here are two of the most common issues I frequently encounter on newly deployed K8s clusters:

1. Incorrect API Server Configuration File Permissions (Section 1.1.1)

By default, manifest files containing initialization secrets and tokens may be readable by standard OS users. Restrict permissions to 600:

sudo chown root:root /etc/kubernetes/manifests/kube-apiserver.yaml
sudo chmod 600 /etc/kubernetes/manifests/kube-apiserver.yaml

2. Kubelet Anonymous Authentication Enabled (Section 4.2.1)

If anonymous-auth is enabled, anyone with access to the node’s internal network can send requests directly to Kubelet on port 10250. Edit /var/lib/kubelet/config.yaml:

authentication:
  anonymous:
    enabled: false
  webhook:
    enabled: true

Restart the service to apply changes:

sudo systemctl restart kubelet

Real-World Tips for Auditing Kubernetes Clusters

After using Kube-bench extensively across staging and production environments, here are a few key takeaways:

  1. Don’t blindly aim for 100% PASS: Some rules recommending disabling anonymous requests or blocking hostPath might break your CNI (like Calico, Cilium) or Storage CSI plugins. Always test thoroughly in staging before applying fixes in production.
  2. Set up automated CronJobs and alerts: Schedule a weekly CronJob scan (e.g., Sunday at 3 AM). Forward error logs directly to your DevOps team’s Slack or Telegram channel so you are instantly notified if file permissions are accidentally altered.
  3. Use the matching benchmark version: Always verify your current K8s version and pass the appropriate flag, such as --benchmark cis-1.8. Running mismatched versions will produce inaccurate results.

Infrastructure security is an ongoing process. Integrating Kube-bench into your regular pipeline alongside tools like Trivy Operator and Kyverno policy automation will give you peace of mind knowing your Kubernetes cluster isn’t exposed to basic misconfigurations.

Share: