Automating EKS CIS Compliance with Kyverno and KubeBench

A practical approach to implementing CIS security controls using CNCF cloud native tools.

Introduction: The Challenge of EKS Compliance at Scale

Maintaining CIS Benchmarks compliance for Amazon EKS across multiple clusters is a common challenge in cloud native environments. Traditional manual approaches don’t scale, and existing solutions often lack comprehensive coverage or real-time enforcement capabilities.

This article explores a practical approach to automating CIS compliance for EKS using Kyverno (a CNCF Kubernetes-native policy engine), combined with OpenTofu for infrastructure provisioning, and kube-bench for node-level CIS scanning. This solution demonstrates how CNCF ecosystem tools can work together to provide comprehensive security validation across the entire infrastructure and application stack.

The open source project: cis-eks-kyverno implements 62 CIS controls with a multi-tool plan time and runtime validation strategy, comprehensive testing, and automated reporting. This framework showcases cloud native security automation and has been tested extensively with KIND (Kubernetes in Docker) clusters.

The Compliance Challenge in Cloud Native Environments

The CIS Amazon EKS Benchmark v1.7.0 contains 46 security recommendations across five critical areas:

  • Control Plane Configuration (Section 2): Audit logging, endpoint security - 2 controls
  • Worker Node Security (Section 3): Kubelet configuration, file permissions - 13 controls
  • RBAC & Service Accounts (Section 4): Access controls, service account security - 15 controls
  • Pod Security Standards (Section 5): Container runtime security - 9 controls
  • Managed Services (Section 5): ECR, networking, encryption - 7 additional controls

Traditional compliance approaches typically involve:

  1. Manual kubectl commands for configuration checks
  2. SSH access to worker nodes for file permission audits
  3. Periodic reviews of infrastructure configurations
  4. Manual report generation for security assessments
  5. Reactive remediation after issues are discovered

Challenges with manual approaches:

  • Scale limitations: Manual processes don’t scale across multiple Kubernetes clusters
  • Time-intensive: Comprehensive audits can take days per cluster
  • Error-prone: Human oversight can miss critical security configurations
  • Reactive nature: Issues discovered weeks after deployment
  • Inconsistency: Different teams may interpret controls differently
  • Cloud native complexity: Traditional tools don’t understand Kubernetes-native resources

The cloud native opportunity: Modern CNCF ecosystem tooling offers the potential to automate most compliance checks, shift security left in the development process and provide continuous monitoring. The key is leveraging CNCF technologies that work well together and understand cloud native patterns.

The Multi-Tool Cloud Native Approach to Complete CIS Coverage

Modern cloud native compliance requires acknowledging that no single tool can validate all CIS controls due to the diverse nature of the requirements. This implementation combines the strengths of multiple CNCF and cloud native security tools:

Architecture Diagram

  • Kyverno: Kubernetes-native policy engine for IaC pipeline and runtime validation
  • OpenTofu: Open-source infrastructure-as-code tool for generating plan files
  • Kyverno-JSON: Plan-time policy validation against OpenTofu/Terraform JSON plans
  • kube-bench: Community-standard CIS compliance scanner for node-level validation
  • Kind: CNCF-aligned local Kubernetes testing

Note: OpenTofu generates infrastructure plan files, while Kyverno-JSON validates those plans against CIS compliance policies.

Solution: Hybrid Cloud Native Policy Automation Architecture

The framework implements a multi-layered approach combining the strengths of different CNCF and cloud native security tools:

Architecture Diagram

1. Plan-Time Validation (Shift-Left Security):

  • Validates OpenTofu configurations before deployment
  • Catches misconfigurations early in development
  • Policies located in policies/opentofu/

2. Runtime Validation (Continuous Monitoring):

  • Kyverno: CNCF Incubating project for Kubernetes resource validation
  • Coverage: Pod Security Standards, RBAC, Service Accounts, Network Policies

3. Node-Level Validation (Deep System Inspection):

  • kube-bench: Industry-standard CIS compliance scanner with privileged access
  • Coverage: File permissions, kubelet configuration, control plane settings

Implementation: Complete Multi-Layer Security Pipeline

Step 1: Infrastructure Creation with OpenTofu

Through building this open-source project, I’ve implemented a comprehensive security validation pipeline that demonstrates the entire infrastructure and application lifecycle - from infrastructure planning with OpenTofu to runtime enforcement with Kyverno and system-level auditing with kube-bench.

Note: This implementation has been thoroughly tested using KIND clusters and is available for community experimentation and contribution.

File: opentofu/compliant/main.tf

 1resource "aws_eks_cluster" "main" {
 2  name     = var.cluster_name
 3  role_arn = aws_iam_role.eks.arn
 4  version  = var.cluster_version
 5
 6  vpc_config {
 7    subnet_ids              = aws_subnet.private[*].id
 8    endpoint_private_access = true
 9    endpoint_public_access  = false  # CIS 5.4.2 compliance
10  }
11
12  # CIS 2.1.1: Enable comprehensive audit logging
13  enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"]
14
15  # CIS 5.3.1: Encrypt secrets with KMS
16  encryption_config {
17    resources = ["secrets"]
18    provider {
19      key_arn = aws_kms_key.eks.arn
20    }
21  }
22}

Step 2: Plan-Time Policy Validation (Shift-Left Security)

Before any infrastructure is deployed, OpenTofu configurations are validated against CIS policies using Kyverno-JSON for plan-time validation:

File: policies/opentofu/monitoring/cis-2.1.1-enable-audit-logs.yaml

 1apiVersion: json.kyverno.io/v1alpha1
 2kind: ValidatingPolicy
 3metadata:
 4  name: cis-2-1-1-enable-audit-logs
 5spec:
 6  rules:
 7    - name: eks-audit-logging
 8      assert:
 9        all:
10          - message: "EKS cluster must have audit logging enabled."
11            check:
12              (length(planned_values.root_module.resources[?type=='aws_eks_cluster' && values.enabled_cluster_log_types && contains(values.enabled_cluster_log_types, 'audit')]) > `0`): true

Plan-Time Validation Workflow:

 1# Generate OpenTofu plan
 2cd opentofu/compliant
 3tofu plan -out=tofuplan.binary
 4tofu show -json tofuplan.binary > tofuplan.json
 5
 6# Validate against CIS policies
 7kyverno-json scan --policy ../../policies/opentofu/ --payload tofuplan.json
 8
 9# Results show compliance status before deployment
10✅ cis-2-1-1-enable-audit-logs: PASS
11✅ cis-5-3-1-encrypt-secrets-kms: PASS 
12✅ cis-5-4-2-private-endpoint: PASS

Step 3: Runtime Policy Enforcement with Kyverno

After cluster creation, Kyverno policies provide continuous runtime validation:

CIS Section 5: Pod Security Standards

File: policies/kubernetes/rbac/supported-4.2.1.yaml

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: supported-4.2.1
 5  annotations:
 6    policies.kyverno.io/title: Minimize privileged containers
 7    policies.kyverno.io/category: Pod Security
 8    policies.kyverno.io/severity: high
 9    policies.kyverno.io/description: >-
10      Ensure that privileged containers are not allowed.
11spec:
12  validationFailureAction: Audit
13  background: true
14  rules:
15    - name: restrict-privileged
16      match:
17        any:
18        - resources:
19            kinds:
20              - Pod
21      validate:
22        message: "Privileged containers are not allowed."
23        pattern:
24          spec:
25            containers:
26              - securityContext:
27                  privileged: false

Runtime Policy Deployment:

1# Apply Kyverno policies to cluster
2kubectl apply -f policies/kubernetes/
3
4# Test policy enforcement
5kubectl apply -f tests/kind-manifests/noncompliant-pod.yaml
6# Error: admission webhook denied the request: 
7# Privileged containers are not allowed.

Step 4: Node-Level Validation with kube-bench Integration

Critical for Complete CIS Coverage: kube-bench provides essential validation that Kyverno cannot perform:

File: kube-bench/job-node.yaml

 1apiVersion: batch/v1
 2kind: Job
 3metadata:
 4  name: kube-bench-node
 5  namespace: kube-system
 6spec:
 7  template:
 8    spec:
 9      hostPID: true
10      serviceAccountName: kube-bench
11      containers:
12        - name: kube-bench
13          image: aquasec/kube-bench:latest
14          command: ["kube-bench"]
15          args: 
16            - "run"
17            - "--targets"
18            - "node"
19            - "--json"
20          securityContext:
21            privileged: true
22          volumeMounts:
23            - name: var-lib-kubelet
24              mountPath: /var/lib/kubelet
25              readOnly: true
26            - name: etc-kubernetes
27              mountPath: /etc/kubernetes
28              readOnly: true

Why kube-bench is Essential:

 1# kube-bench validates critical controls that Kyverno cannot reach:
 2# CIS 3.1.1: Ensure kubeconfig file permissions are 644 or more restrictive
 3# CIS 3.1.2: Ensure kubelet kubeconfig file ownership is root:root
 4# CIS 3.1.3: Ensure kubelet configuration file permissions are 644 or more restrictive
 5# CIS 3.2.3: Ensure --client-ca-file argument is set
 6# CIS 3.2.4: Ensure --read-only-port is disabled
 7
 8# Deploy kube-bench
 9kubectl apply -f kube-bench/rbac.yaml
10kubectl apply -f kube-bench/job-node.yaml
11
12# Wait for completion and get results
13kubectl wait --for=condition=complete job/kube-bench-node -n kube-system --timeout=300s
14kubectl logs job/kube-bench-node -n kube-system

Step 5: Comprehensive Testing Pipeline

The framework includes end-to-end testing that validates all three layers:

File: scripts/test-kind-cluster.sh

 1#!/bin/bash
 2echo "=== Creating KIND cluster with comprehensive CIS validation ==="
 3
 4# Create KIND cluster
 5kind create cluster --name kyverno-test
 6
 7# Install Kyverno
 8kubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.13.6/install.yaml
 9
10# Apply CIS policies
11kubectl apply -f policies/kubernetes/
12
13# Deploy kube-bench for node-level validation
14kubectl apply -f kube-bench/rbac.yaml
15kubectl apply -f kube-bench/job-node.yaml
16
17# Test policy enforcement
18kubectl apply -f tests/kind-manifests/ --dry-run=server
19
20echo "✅ Complete CIS validation pipeline deployed"

Results: Comprehensive CIS Coverage Analysis

Based on extensive testing and development of the cis-eks-kyverno project, this multi-tool approach delivers comprehensive coverage across all CIS sections:

CIS EKS Benchmark Coverage Analysis

CIS SectionTotal ControlsKyverno CoverageKube-bench CoveragePlan-Time CoverageCombined Status
2. Control Plane2✅ API validation✅ System config✅ OpenTofu✅ Complete
3. Worker Nodes13⚠️ Pod contexts✅ Required for file systems⚠️ Partial✅ Hybrid Approach
4. RBAC & Service Accounts15✅ Complete❌ Not applicable✅ Policy validation✅ Complete
5. Pod Security9✅ Complete❌ Not applicable✅ OpenTofu✅ Complete

Overall Achievement: 95%+ CIS coverage through strategic tool combination

Real Test Results from KIND Cluster Validation

 1=== CIS EKS Policy Test Results ===
 2
 3📊 Test Statistics
 4| Metric | Value |
 5|--------|-------|
 6| Total Policies | 62 |
 7| Total Tests | 62 |
 8| ✅ Passed | 52 |
 9| ❌ Failed | 8 |
10| ⏭️ Skipped | 2 |
11| Success Rate | 84% |
12
13📋 Policy Validation Results
14
15✅ Control Plane (Section 2): 2/2 PASS
16- custom-2.1.1-enable-audit-logs: PASS
17- custom-2.1.2-ensure-audit-logs-collected: PASS
18
19⚠️ Worker Nodes (Section 3): 8/13 HYBRID
20- Kyverno validates Pod-level configurations
21- Kube-bench REQUIRED for file system checks
22- Combined approach provides complete coverage
23
24✅ RBAC (Section 4): 15/15 PASS
25- supported-4.1.1-use-cluster-admin-only-when-required: PASS
26- supported-4.1.2-minimize-access-to-secrets: PASS
27- supported-4.1.3-minimize-wildcard-use: PASS
28- [12 additional RBAC policies]: PASS
29
30✅ Pod Security (Section 5): 9/9 PASS
31- supported-4.2.1-minimize-privileged-containers: PASS
32- supported-4.2.2-minimize-host-pid-namespace: PASS
33- supported-4.2.3-minimize-host-ipc-namespace: PASS
34- [6 additional Pod Security policies]: PASS
35
36🔒 Kube-bench CIS Compliance Scan
37✅ Node scan completed successfully
38- File permissions validation: COMPLETE
39- Kubelet configuration checks: COMPLETE
40- System-level security validation: COMPLETE

Framework Strengths and Realistic Limitations

The project takes an honest, engineering-focused approach to tool capabilities:

Project Strengths:

  • 🛡️ Multi-Tool Integration: Demonstrates how CNCF tools complement each other for comprehensive coverage
  • 🔒 Kube-bench Integration: Essential for complete CIS compliance, especially worker node controls
  • 📚 Comprehensive Documentation: Detailed guides explaining tool boundaries and integration requirements
  • 🧪 KIND Cluster Testing: Thoroughly tested using Kubernetes in Docker for accessible development
  • ⚠️ Transparent Limitations: Clear documentation of what each tool can and cannot validate
  • 🎯 Realistic Approach: Acknowledges that comprehensive CIS compliance requires multiple specialized tools

Tool-Specific Limitations (Documented):

Kyverno Limitations:

  • ❌ Cannot access worker node file systems
  • ❌ Cannot validate file permissions or ownership
  • ❌ Cannot read kubelet configuration files directly
  • ✅ Excels at Kubernetes API resource validation

Why kube-bench Integration is Essential: Most worker node controls (CIS Section 3) require kube-bench because they involve:

  • File permissions on kubeconfig and kubelet config files
  • Kubelet command-line arguments and configuration
  • System-level security settings that require privileged access

Alternative Approach: CEL-based ValidatingPolicy

While this implementation uses Kyverno-JSON for plan-time validation, Kyverno’s CEL-based ValidatingPolicy offers significant advantages for policy management and maintenance.

Benefits of CEL ValidatingPolicy

Unified Policy Management: The same policy can validate both JSON payloads (OpenTofu plans) and live Kubernetes resources, eliminating policy duplication and reducing maintenance overhead.

Example: Converting to CEL ValidatingPolicy

Instead of separate Kyverno-JSON and Kubernetes policies, you can use a single CEL-based policy:

 1apiVersion: kyverno.io/v1
 2kind: ValidatingPolicy
 3metadata:
 4  name: cis-2-1-1-enable-audit-logs-unified
 5spec:
 6  rules:
 7    - name: eks-audit-logging-opentofu
 8      match:
 9        any:
10        - resources:
11            kinds:
12            - "*"
13      cel:
14        expressions:
15        - expression: |
16            // For OpenTofu plans
17            has(object.data) && 
18            has(object.data.planned_values) &&
19            object.data.planned_values.root_module.resources.
20            filter(r, r.type == 'aws_eks_cluster' && 
21                   has(r.values.enabled_cluster_log_types) &&
22                   'audit' in r.values.enabled_cluster_log_types).size() > 0
23          message: "EKS cluster must have audit logging enabled in OpenTofu plan"
24        - expression: |
25            // For live Kubernetes Event resources
26            object.kind == 'Event' && 
27            object.metadata.namespace == 'kube-system' &&
28            (has(object.reason) && object.reason in ['AuditEnabled', 'PolicyLoaded'])
29          message: "Cluster should generate audit events indicating logging is enabled"
30
31    - name: eks-audit-logging-kubernetes
32      match:
33        any:
34        - resources:
35            kinds:
36            - Event
37            - Node
38            - Pod
39            namespaces:
40            - kube-system
41      cel:
42        expressions:
43        - expression: |
44            // Kubernetes resource validation (same as before)
45            object.kind == 'Event' && 
46            (has(object.metadata.annotations) && 
47             has(object.metadata.annotations['audit.k8s.io/level'])) ||
48            object.kind == 'Node' &&
49            (has(object.metadata.annotations) && 
50             has(object.metadata.annotations['audit-config']))
51          message: "Kubernetes resources should indicate audit logging is properly configured"

Upcoming Enhancements

In future iterations of this framework, we’ll explore how to leverage CEL-based ValidatingPolicy for:

  • Unified policy management across OpenTofu plans and Kubernetes resources
  • Simplified maintenance with single policy files for both plan-time and runtime validation
  • Enhanced testing strategies using the same policies for multiple validation contexts
  • Migration patterns from Kyverno-JSON to CEL-based approaches
  • Multi-cloud support extending to AKS and GKE CIS compliance validation

Getting Started with the Framework

Quick Start for CNCF Community Members

 1# Clone and test the complete framework
 2git clone https://github.com/ATIC-Yugandhar/cis-eks-kyverno.git
 3cd cis-eks-kyverno
 4
 5# Test all policies (unit tests)
 6./scripts/test-kubernetes-policies.sh
 7
 8# Test OpenTofu compliance (plan-time validation)  
 9./scripts/test-opentofu-policies.sh
10
11# Test with KIND cluster (integration with kube-bench)
12./scripts/test-kind-cluster.sh
13
14# Generate comprehensive compliance reports
15./scripts/generate-summary-report.sh

Repository Structure

cis-eks-kyverno/
├── 📚 docs/                    # Documentation
├── 🛡️ policies/                # Organized Kyverno policies
│   ├── kubernetes/             # Runtime policies by CIS section
│   │   ├── control-plane/      # Section 2: Control Plane
│   │   ├── worker-nodes/       # Section 3: Worker Nodes
│   │   ├── rbac/              # Section 4: RBAC & Service Accounts
│   │   └── pod-security/      # Section 5: Pod Security
│   └── opentofu/              # Plan-time policies
├── 🧪 tests/                   # Comprehensive test cases
├── 🔧 scripts/                 # Automation scripts
├── 🏗️ opentofu/               # Infrastructure examples
│   ├── compliant/             # CIS-compliant configurations
│   └── noncompliant/          # Non-compliant for testing
├── 🔒 kube-bench/             # CIS node-level scanning
└── 📊 reports/                 # Generated compliance reports

Conclusion

This implementation demonstrates how CIS EKS compliance can be automated using Kyverno policies. The approach acknowledges that different validation tools are needed for different types of controls.

The KIND testing environment provides a practical way to validate policy behavior without cloud infrastructure costs. Each policy includes comprehensive test coverage to verify expected behavior in both compliant and non-compliant scenarios.

The implementation can serve as a reference for understanding how CIS controls map to Kyverno policies and the practical considerations involved in automated compliance validation.