← Back to Guide
Compliance & Auditing L1 · INTRO ~45 min

Run kube-bench and Generate a Compliance Report

Execute the CIS Kubernetes Benchmark against a cluster using kube-bench, export the results as JSON, parse failures by CIS section, compute a compliance score, and identify the highest-priority remediations.

Objective

The CIS Kubernetes Benchmark defines security configuration standards for control plane, etcd, kubelet, and policies. kube-bench automates these checks and produces a structured report. This exercise runs kube-bench as a Kubernetes Job, parses the JSON output, and produces a categorised report with a compliance score — the foundation of a recurring security posture measurement workflow.

Prerequisites

Steps

01

Run kube-bench as a Kubernetes Job

The cleanest approach is running kube-bench as a Job on each node type (master/worker). The official Kubernetes Job manifests handle node targeting via tolerations and host path mounts.

# Run against worker nodes (node benchmark)
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml

# Watch the job complete
kubectl wait --for=condition=complete job/kube-bench --timeout=120s

# Retrieve output
kubectl logs job/kube-bench

## [INFO] 4 Worker Node Security Configuration
## [INFO] 4.1 Worker Node Configuration Files
## [PASS] 4.1.1 Ensure that the kubelet service file permissions are set to 600 ...
## [FAIL] 4.1.5 Ensure that the --kubeconfig kubelet.conf file permissions are set to 600 ...
## ...
## == Summary ==
## 38 checks PASS
## 12 checks FAIL
## 4 checks WARN
## 0 checks INFO

kubectl delete job kube-bench
On managed Kubernetes (AKS/EKS/GKE), control plane checks (Section 1) are not applicable — the cloud provider manages the control plane. Focus on Sections 3 (worker nodes) and 5 (policies).
02

Export results as JSON

# Use the JSON output job variant
kubectl apply -f - <<EOF
apiVersion: batch/v1
kind: Job
metadata:
  name: kube-bench-json
spec:
  template:
    spec:
      hostPID: true
      containers:
        - name: kube-bench
          image: aquasec/kube-bench:latest
          command: ["kube-bench", "--json", "--outputfile", "/tmp/results.json"]
          volumeMounts:
            - name: tmp
              mountPath: /tmp
      restartPolicy: Never
      volumes:
        - name: tmp
          emptyDir: {}
EOF

kubectl wait --for=condition=complete job/kube-bench-json --timeout=120s

# Copy the JSON out of the pod
POD=$(kubectl get pods -l job-name=kube-bench-json -o jsonpath='{.items[0].metadata.name}')
kubectl cp ${POD}:/tmp/results.json kube-bench-results.json

# Preview structure with jq
jq '.Controls[0] | {version, text, node_type}' kube-bench-results.json
## { "version": "1.8", "text": "Kubernetes Worker Node Security", "node_type": ["node"] }

kubectl delete job kube-bench-json
03

Parse and categorise failures with Python

parse_kube_bench.py
import json, sys
from collections import defaultdict

with open("kube-bench-results.json") as f:
    data = json.load(f)

totals = defaultdict(int)
failures_by_section = defaultdict(list)

for control in data.get("Controls", []):
    section_name = control.get("text", "Unknown")
    for group in control.get("tests", []):
        for result in group.get("results", []):
            status = result.get("status", "UNKNOWN")
            totals[status] += 1
            if status == "FAIL":
                failures_by_section[section_name].append({
                    "id":     result.get("test_number"),
                    "desc":   result.get("test_desc"),
                    "scored": result.get("scored", True),
                    "remediation": result.get("remediation", "").strip()[:120],
                })

total_checks = sum(totals.values())
passed = totals.get("PASS", 0)
score = (passed / total_checks * 100) if total_checks > 0 else 0

print(f"\n=== CIS Kubernetes Benchmark Report ===\n")
print(f"Compliance Score : {score:.1f}%  ({passed}/{total_checks} checks passing)")
print(f"PASS: {totals['PASS']}  FAIL: {totals['FAIL']}  WARN: {totals['WARN']}\n")

for section, failures in sorted(failures_by_section.items()):
    print(f"── {section} ({len(failures)} failures)")
    for f in failures:
        scored_tag = "[SCORED]" if f["scored"] else "[NOT SCORED]"
        print(f"   {f['id']} {scored_tag} {f['desc']}")
        if f["remediation"]:
            print(f"   Remediation: {f['remediation']}...")
    print()
python3 parse_kube_bench.py

## === CIS Kubernetes Benchmark Report ===
##
## Compliance Score : 76.0%  (38/50 checks passing)
## PASS: 38  FAIL: 12  WARN: 4
##
## ── Kubernetes Worker Node Security (8 failures)
##    4.1.5 [SCORED] Ensure kubelet.conf permissions are 600 ...
##    Remediation: Run: chmod 600 /etc/kubernetes/kubelet.conf...
##    4.2.1 [SCORED] Ensure anonymous-auth is false ...
##    Remediation: Edit kubelet config: set authentication.anonymous.enabled: false...
04

Identify the top 5 highest-priority remediations

Prioritise scored failures that are exploitable at the network level. These five are the most common and highest-impact on a default cluster:

# 1. Anonymous authentication on kubelet (4.2.1)
# Edit kubelet config: /var/lib/kubelet/config.yaml
# authentication:
#   anonymous:
#     enabled: false

# 2. Kubelet read-only port (4.2.4)
# readOnlyPort: 0  # disable the unauthenticated port 10255

# 3. Audit logging not enabled (1.2.22 — if kubeadm)
# Add to kube-apiserver: --audit-policy-file=/etc/kubernetes/audit-policy.yaml

# 4. Etcd not encrypted at rest (1.2.33)
# Add to kube-apiserver: --encryption-provider-config=/etc/kubernetes/enc.yaml

# 5. AlwaysPullImages admission controller not enabled (1.2.11)
# Add to kube-apiserver: --enable-admission-plugins=...,AlwaysPullImages

# Restart kubelet after config changes
sudo systemctl daemon-reload && sudo systemctl restart kubelet

# Re-run kube-bench to measure improvement
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl wait --for=condition=complete job/kube-bench --timeout=120s
kubectl logs job/kube-bench | tail -10

Success Criteria

Further Reading