This commit is contained in:
Mosiur Rahman
2026-08-27 11:51:22 +06:00
16 changed files with 425 additions and 75 deletions

View File

@@ -4,7 +4,7 @@ Canonical progress record for CKS preparation. Update this file after every grad
## Dashboard ## Dashboard
Last updated: 2026-08-26 Last updated: 2026-08-27
| Domain | Weight | Hero | Training | Not started | Total | | Domain | Weight | Hero | Training | Not started | Total |
|---|---:|---:|---:|---:|---:| |---|---:|---:|---:|---:|---:|
@@ -38,6 +38,15 @@ A topic becomes Hero only when every item is checked:
Minor syntax corrections during training are expected. A cold retest fails when the solution needs field-by-field coaching, grants excess privilege, breaks required behavior, omits proof, or changes resources outside scope. Minor syntax corrections during training are expected. A cold retest fails when the solution needs field-by-field coaching, grants excess privilege, breaks required behavior, omits proof, or changes resources outside scope.
## Exam-Simulation Rules
- Every graded question is a Linux command-line lab on a designated host or Kubernetes context.
- Prompts specify an end state; the learner changes files, resources, processes, or policies to reach it.
- Deliverables are the resulting state plus short command/output evidence. Essays, prose tables, PowerShell parsing, and multiple-choice answers are not graded tasks.
- Tools are used directly when the syllabus names them. A scanner task requires running the scanner and changing the system, not writing about scanner theory.
- Harder-than-exam means more interacting controls, realistic faults, or a tighter time limit. It does not mean more literature questions.
- When the current computer lacks the required Linux/Kubernetes environment, mark the task environment-blocked and use a Linux lab; do not replace it with a written substitute.
## Resume Protocol ## Resume Protocol
1. Read `MISSION.md`, `NOTES.md`, the newest learning record, and this file. 1. Read `MISSION.md`, `NOTES.md`, the newest learning record, and this file.
@@ -49,7 +58,19 @@ Minor syntax corrections during training are expected. A cold retest fails when
## Next Task ## Next Task
`CS-02.Q1` in progress as Lesson 0036: run a kube-bench-based CIS review and separate automated findings from manual checks across kube-apiserver, etcd, kubelet, and CoreDNS. Finish the one-time local lab installation after Windows restarts, then run `CS-02.Q1` as revised Lesson 0036 on `kind-cks-lab`. Do not use the learner's Kubernetes v1.36 production cluster: kube-bench v0.16.0 has automatic version mappings only through v1.34.
## Local Lab Environment
Status: `WINDOWS RESTART REQUIRED`
- Platform: Ubuntu 24.04 on WSL2, Docker Engine, two-node Kind cluster, and Calico.
- Kubernetes: pinned to v1.34.0; kube-bench: pinned to v0.16.0.
- Cluster and context: `cks-lab` / `kind-cks-lab`.
- Kubeconfig: `/opt/cks-lab/kubeconfig`; it is never merged with a production config.
- Setup and recovery files: `lab-environment/`.
- Resume after restart: run `lab-environment\\02-install-and-build.ps1`, then `lab-environment\\verify-lab.ps1`.
- Lesson scope: use Kind nodes for Kubernetes tasks and the disposable Ubuntu WSL2 VM for host/kernel hardening tasks.
--- ---

View File

@@ -7,3 +7,7 @@
- Review preference: list all detected issues, then correct only one issue per round. - Review preference: list all detected issues, then correct only one issue per round.
- Mastery tracking: use `CKS-MASTERY-CHECKLIST.md` as the canonical cross-session dashboard. Never award Hero from lesson completion alone; require the topic's tool drill, timed capstone, verification evidence, and cold retest. - Mastery tracking: use `CKS-MASTERY-CHECKLIST.md` as the canonical cross-session dashboard. Never award Hero from lesson completion alone; require the topic's tool drill, timed capstone, verification evidence, and cold retest.
- Confidence priority: deliberately rotate through named CKS tools instead of relying mainly on hand-written YAML. - Confidence priority: deliberately rotate through named CKS tools instead of relying mainly on hand-written YAML.
- Exam-simulation rule: graded questions must be Linux command-line performance labs. Do not require PowerShell, essays, explanatory tables, multiple-choice answers, or tool-installation research as task deliverables. Grade the resulting system state and concise command/output evidence.
- Use short CKS-style prompts: designated host/context, exact end state, files/resources in scope, time limit, and verification. Hard mode may combine more controls or tighter time, but must remain a lab rather than a literature exercise.
- Local lab rule: run all future lessons in the disposable `cks-lab` environment under Ubuntu 24.04 WSL2. Use `/opt/cks-lab/kubeconfig` and require context `kind-cks-lab`; never use, copy, or merge a production kubeconfig.
- Lab targeting: use the Kind control-plane and worker containers for Kubernetes component/runtime exercises, and the enclosing Ubuntu WSL2 VM for host OS, IAM, firewall, AppArmor, seccomp, and kernel exercises.

View File

@@ -0,0 +1,28 @@
$ErrorActionPreference = 'Stop'
$principal = New-Object Security.Principal.WindowsPrincipal(
[Security.Principal.WindowsIdentity]::GetCurrent()
)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
$arguments = @(
'-NoProfile',
'-ExecutionPolicy', 'Bypass',
'-File', ('"{0}"' -f $PSCommandPath)
)
Start-Process -FilePath 'powershell.exe' -Verb RunAs -ArgumentList $arguments -Wait
exit $LASTEXITCODE
}
Write-Host 'Enabling Windows Subsystem for Linux...'
& dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
if ($LASTEXITCODE -notin 0, 3010) { throw "DISM failed with exit code $LASTEXITCODE" }
Write-Host 'Enabling Virtual Machine Platform...'
& dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
if ($LASTEXITCODE -notin 0, 3010) { throw "DISM failed with exit code $LASTEXITCODE" }
Write-Host ''
Write-Host 'Windows features are enabled. Restart Windows, then run:'
Write-Host ' .\02-install-and-build.ps1'

View File

@@ -0,0 +1,45 @@
$ErrorActionPreference = 'Stop'
$distribution = 'Ubuntu-24.04'
function Test-Distribution {
$names = @(& wsl.exe --list --quiet 2>$null) | ForEach-Object { $_.Trim("`0 ") }
return $names -contains $distribution
}
if (-not (Test-Distribution)) {
Write-Host "Installing $distribution..."
& wsl.exe --install --web-download --distribution $distribution --no-launch
if ($LASTEXITCODE -ne 0) {
throw 'Ubuntu installation failed. Confirm Windows was restarted after running 01-enable-wsl.ps1.'
}
}
& wsl.exe --set-default-version 2
if ($LASTEXITCODE -ne 0) { throw 'Could not set WSL2 as the default.' }
# Starting as root avoids an interactive Unix-user prompt in this disposable VM.
& wsl.exe --distribution $distribution --user root --exec /bin/true
if ($LASTEXITCODE -ne 0) { throw "$distribution did not initialize correctly." }
$linuxDirectory = (& wsl.exe --distribution $distribution --user root --exec wslpath -a $PSScriptRoot).Trim()
if (-not $linuxDirectory) { throw 'Could not translate the lab path into WSL.' }
Write-Host 'Installing pinned lab tools...'
& wsl.exe --distribution $distribution --user root --exec bash "$linuxDirectory/bootstrap.sh"
if ($LASTEXITCODE -ne 0) { throw 'Linux tool bootstrap failed.' }
# Reload WSL so systemd and Docker use the newly written WSL configuration.
& wsl.exe --shutdown
Start-Sleep -Seconds 3
Write-Host 'Creating the isolated Kubernetes cluster...'
& wsl.exe --distribution $distribution --user root --exec bash "$linuxDirectory/create-lab.sh" "$linuxDirectory/kind-v1.34.yaml"
if ($LASTEXITCODE -ne 0) { throw 'Cluster creation failed.' }
& wsl.exe --distribution $distribution --user root --exec bash "$linuxDirectory/verify-lab.sh"
if ($LASTEXITCODE -ne 0) { throw 'Lab verification failed.' }
Write-Host ''
Write-Host 'CKS lab is ready. Enter it with:'
Write-Host ' .\enter-lab.ps1'

64
lab-environment/README.md Normal file
View File

@@ -0,0 +1,64 @@
# CKS Local Lab
This lab runs entirely inside an Ubuntu 24.04 WSL2 virtual machine. It uses
Docker Engine and Kind to create a two-node Kubernetes cluster.
## Isolation contract
- Cluster name: `cks-lab`
- Kubernetes version: `v1.34.0`
- Lab kubeconfig: `/opt/cks-lab/kubeconfig`
- Lab context: `kind-cks-lab`
- The scripts never read, merge, or modify `$HOME/.kube/config`.
- All destructive commands are limited to the Kind cluster named `cks-lab`.
Kubernetes v1.34 is deliberate: kube-bench v0.16.0 contains a CIS mapping for
v1.34. The production cluster is not a suitable lesson environment.
## Installation
Run these commands from PowerShell in this directory:
```powershell
# Opens one UAC prompt and enables the required Windows features.
.\01-enable-wsl.ps1
```
Restart Windows when requested. Then run:
```powershell
.\02-install-and-build.ps1
```
The first Ubuntu launch can take a few minutes. The script installs Docker,
kubectl, Kind, kube-bench, creates the cluster, and installs Calico.
## Daily use
Open the lab shell:
```powershell
.\enter-lab.ps1
```
The shell sets `KUBECONFIG=/opt/cks-lab/kubeconfig` and refuses to continue if
the active context is not `kind-cks-lab`.
Verify or rebuild the lab:
```powershell
.\verify-lab.ps1
.\reset-lab.ps1
.\02-install-and-build.ps1
```
Run kube-bench against the Kind control-plane node:
```bash
docker exec -it cks-lab-control-plane \
/opt/kube-bench/kube-bench run --benchmark cis-1.12
```
Lesson answers and progress remain in this repository, so they can be carried
to another PC. Cluster state is disposable and should be rebuilt there.

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env bash
set -Eeuo pipefail
KUBECTL_VERSION="v1.34.0"
KIND_VERSION="v0.32.0"
KUBE_BENCH_VERSION="0.16.0"
if [[ "${EUID}" -ne 0 ]]; then
echo "Run this script as root inside the lab WSL distribution." >&2
exit 1
fi
cat >/etc/wsl.conf <<'EOF'
[boot]
systemd=true
[user]
default=root
EOF
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y ca-certificates curl gnupg jq vim git iproute2 iptables conntrack socat
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
. /etc/os-release
cat >/etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: ${UBUNTU_CODENAME:-$VERSION_CODENAME}
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT
curl -fsSLo "$tmp_dir/kubectl" "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl"
curl -fsSLo "$tmp_dir/kubectl.sha256" "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl.sha256"
printf '%s %s\n' "$(cat "$tmp_dir/kubectl.sha256")" "$tmp_dir/kubectl" | sha256sum --check --status
install -m 0755 "$tmp_dir/kubectl" /usr/local/bin/kubectl
curl -fsSLo "$tmp_dir/kind" "https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-linux-amd64"
curl -fsSLo "$tmp_dir/kind.sha256sum" "https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-linux-amd64.sha256sum"
(cd "$tmp_dir" && sha256sum --check --status kind.sha256sum)
install -m 0755 "$tmp_dir/kind" /usr/local/bin/kind
curl -fsSLo "$tmp_dir/kube-bench.tar.gz" \
"https://github.com/aquasecurity/kube-bench/releases/download/v${KUBE_BENCH_VERSION}/kube-bench_${KUBE_BENCH_VERSION}_linux_amd64.tar.gz"
curl -fsSLo "$tmp_dir/checksums.txt" \
"https://github.com/aquasecurity/kube-bench/releases/download/v${KUBE_BENCH_VERSION}/kube-bench_${KUBE_BENCH_VERSION}_checksums.txt"
(cd "$tmp_dir" && grep " kube-bench_${KUBE_BENCH_VERSION}_linux_amd64.tar.gz$" checksums.txt | sha256sum --check --status)
rm -rf /opt/cks-lab/tools/kube-bench
install -d /opt/cks-lab/tools/kube-bench
tar -xzf "$tmp_dir/kube-bench.tar.gz" -C /opt/cks-lab/tools/kube-bench
ln -sfn /opt/cks-lab/tools/kube-bench/kube-bench /usr/local/bin/kube-bench
printf 'Installed kubectl %s, Kind %s, and kube-bench %s.\n' \
"$KUBECTL_VERSION" "$KIND_VERSION" "$KUBE_BENCH_VERSION"

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -Eeuo pipefail
CLUSTER_NAME="cks-lab"
KUBECONFIG_PATH="/opt/cks-lab/kubeconfig"
NODE_IMAGE="kindest/node:v1.34.0@sha256:7416a61b42b1662ca6ca89f02028ac133a309a2a30ba309614e8ec94d976dc5a"
CALICO_VERSION="v3.32.1"
CONFIG_PATH="${1:?Pass the Kind configuration path.}"
if [[ "${EUID}" -ne 0 ]]; then
echo "Run this script as root inside the lab WSL distribution." >&2
exit 1
fi
systemctl start docker 2>/dev/null || service docker start
install -d -m 0700 /opt/cks-lab
if ! kind get clusters | grep -Fxq "$CLUSTER_NAME"; then
kind create cluster \
--name "$CLUSTER_NAME" \
--image "$NODE_IMAGE" \
--config "$CONFIG_PATH" \
--kubeconfig "$KUBECONFIG_PATH"
fi
export KUBECONFIG="$KUBECONFIG_PATH"
chmod 0600 "$KUBECONFIG"
context="$(kubectl config current-context)"
if [[ "$context" != "kind-${CLUSTER_NAME}" ]]; then
echo "Safety check failed: unexpected context $context" >&2
exit 1
fi
kubectl apply -f "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/operator-crds.yaml"
kubectl apply -f "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/tigera-operator.yaml"
kubectl apply -f "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/custom-resources.yaml"
kubectl wait --for=condition=Available deployment/tigera-operator -n tigera-operator --timeout=300s
kubectl wait --for=condition=Ready nodes --all --timeout=600s
for node in "${CLUSTER_NAME}-control-plane" "${CLUSTER_NAME}-worker"; do
docker exec "$node" rm -rf /opt/kube-bench
docker cp /opt/cks-lab/tools/kube-bench "$node":/opt/kube-bench
docker exec "$node" /opt/kube-bench/kube-bench version
done

View File

@@ -0,0 +1,17 @@
$ErrorActionPreference = 'Stop'
$distribution = 'Ubuntu-24.04'
& wsl.exe --distribution $distribution --user root --exec bash -lc @'
export KUBECONFIG=/opt/cks-lab/kubeconfig
context="$(kubectl config current-context 2>/dev/null || true)"
if [[ "$context" != "kind-cks-lab" ]]; then
echo "Safety check failed: expected kind-cks-lab, got ${context:-none}." >&2
exit 1
fi
echo "CKS lab: $(kubectl version --output=json | jq -r .serverVersion.gitVersion)"
echo "Context: $context"
exec bash
'@
if ($LASTEXITCODE -ne 0) { throw 'Could not enter the isolated CKS lab.' }

View File

@@ -0,0 +1,10 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: cks-lab
nodes:
- role: control-plane
- role: worker
networking:
disableDefaultCNI: true
podSubnet: 192.168.0.0/16

View File

@@ -0,0 +1,5 @@
$ErrorActionPreference = 'Stop'
$linuxDirectory = (& wsl.exe --distribution Ubuntu-24.04 --user root --exec wslpath -a $PSScriptRoot).Trim()
& wsl.exe --distribution Ubuntu-24.04 --user root --exec bash "$linuxDirectory/reset-lab.sh"
if ($LASTEXITCODE -ne 0) { throw 'Lab reset failed.' }

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -Eeuo pipefail
CLUSTER_NAME="cks-lab"
export KUBECONFIG="/opt/cks-lab/kubeconfig"
if [[ "$CLUSTER_NAME" != "cks-lab" ]]; then
echo "Refusing to delete an unexpected cluster name." >&2
exit 1
fi
systemctl start docker 2>/dev/null || service docker start
if kind get clusters | grep -Fxq "$CLUSTER_NAME"; then
kind delete cluster --name "$CLUSTER_NAME"
else
echo "The cks-lab cluster does not exist."
fi
rm -f "$KUBECONFIG"

View File

@@ -0,0 +1,5 @@
$ErrorActionPreference = 'Stop'
$linuxDirectory = (& wsl.exe --distribution Ubuntu-24.04 --user root --exec wslpath -a $PSScriptRoot).Trim()
& wsl.exe --distribution Ubuntu-24.04 --user root --exec bash "$linuxDirectory/verify-lab.sh"
if ($LASTEXITCODE -ne 0) { throw 'Lab verification failed.' }

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -Eeuo pipefail
export KUBECONFIG="/opt/cks-lab/kubeconfig"
expected_context="kind-cks-lab"
context="$(kubectl config current-context 2>/dev/null || true)"
if [[ "$context" != "$expected_context" ]]; then
echo "Safety check failed: expected $expected_context, got ${context:-none}." >&2
exit 1
fi
kubectl wait --for=condition=Ready nodes --all --timeout=60s
kubectl get nodes -o wide
kubectl get pods -A
for node in cks-lab-control-plane cks-lab-worker; do
docker inspect "$node" >/dev/null
docker exec "$node" /opt/kube-bench/kube-bench version
done
echo "Verified isolated context: $context"

View File

@@ -0,0 +1,15 @@
# Linux performance labs only
The learner correctly identified that the original Lesson 36 was not CKS-like: it required PowerShell parsing and extensive written analysis. Current Linux Foundation instructions describe CKS as 15–20 performance tasks solved from a Linux command line on designated hosts.
## Permanent teaching rule
All graded CKS questions must be Linux command-line labs. Ask for concrete system changes and concise verification output, not essays, explanatory tables, multiple-choice responses, or PowerShell work. Named tools must be executed directly. If the current computer lacks the required environment, record an environment block and use a Linux Kubernetes lab rather than substituting literature work.
## Difficulty rule
Make labs harder through interacting controls, realistic broken states, strict scope preservation, and tighter time limits. Do not make them harder through extra prose requirements.
## kube-bench environment finding
The learner's production cluster runs Kubernetes v1.36.0. kube-bench v0.16.0 maps Kubernetes versions only through v1.34, where it selects `cis-1.12`. Do not use forced older benchmarks as Hero evidence or modify the v1.36 production control plane for training. Lesson 36 requires a disposable v1.34 kubeadm lab.

View File

@@ -0,0 +1,57 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Lesson 36: kube-bench CIS remediation</title>
<link rel="stylesheet" href="../assets/course.css">
</head>
<body>
<main>
<p class="eyebrow">Lesson 0036 · 25 minutes · Linux performance lab · Cluster Setup</p>
<h1>Remediate kube-bench failures</h1>
<p class="lede">Complete this task on disposable Linux hosts running a kubeadm-style Kubernetes v1.34 cluster with kube-bench v0.16.0. No written explanation is required.</p>
<div class="callout"><strong>Environment required:</strong> a disposable Kubernetes v1.34 lab with one control-plane host, one worker host, root access, kube-bench v0.16.0, and editable component configuration. Do not perform this training remediation on the learner's Kubernetes v1.36 production cluster: kube-bench v0.16.0 maps only through Kubernetes v1.34.</div>
<h2>Task</h2>
<p>Start on host <code>controlplane</code>. Become root. Do not change any setting not named below.</p>
<ol>
<li>Run kube-bench checks <code>1.2.1</code>, <code>1.2.7</code>, <code>2.2</code>, and <code>2.3</code>. Save the output to <code>/root/lesson-36-controlplane-before.txt</code>.</li>
<li>Configure kube-apiserver with anonymous authentication disabled and authorization modes <code>Node,RBAC</code>.</li>
<li>Configure etcd with client-certificate authentication enabled and automatic TLS disabled. Preserve its existing CA, certificate, key, peer, data, and cluster settings.</li>
<li>Wait for kube-apiserver and etcd to become healthy.</li>
<li>Rerun the same four checks and save output to <code>/root/lesson-36-controlplane-after.txt</code>. All four checks must report PASS.</li>
</ol>
<p>Return to the base host, then connect directly to host <code>worker</code>. Become root.</p>
<ol start="6">
<li>Run kube-bench checks <code>4.2.1</code>, <code>4.2.2</code>, and <code>4.2.3</code>. Save output to <code>/root/lesson-36-worker-before.txt</code>.</li>
<li>Configure kubelet so anonymous authentication is disabled, webhook authentication is enabled, and authorization mode is <code>Webhook</code>.</li>
<li>Restart kubelet and verify the node returns to <code>Ready</code>.</li>
<li>Rerun the same three checks and save output to <code>/root/lesson-36-worker-after.txt</code>. All three checks must report PASS.</li>
</ol>
<h2>Completion evidence</h2>
<p>Send only these outputs:</p>
<pre><code># controlplane
grep -E '^\[(PASS|FAIL|WARN)\]' /root/lesson-36-controlplane-after.txt
# worker
grep -E '^\[(PASS|FAIL|WARN)\]' /root/lesson-36-worker-after.txt
systemctl is-active kubelet
kubectl get node worker</code></pre>
<p>Do not submit an essay or remediation table. The result is graded from component state, saved scanner output, and node health.</p>
<h2>Documentation</h2>
<p>Use the installed kube-bench help, component configuration files, and official <a href="https://github.com/aquasecurity/kube-bench">kube-bench documentation</a> as needed.</p>
<h2>What to send me</h2>
<p>Send the four PASS groups, <code>systemctl</code> result, and worker-node status. I will list all detected issues and correct one per round.</p>
<footer>Previous: <a href="0035-apiserver-audit-hard-mode.html">API server and audit hard mode</a> · Tracker: <a href="../CKS-MASTERY-CHECKLIST.md">CKS Mastery Checklist</a></footer>
</main>
</body>
</html>

View File

@@ -1,73 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Lesson 36: kube-bench CIS triage</title>
<link rel="stylesheet" href="../assets/course.css">
</head>
<body>
<main>
<p class="eyebrow">Lesson 0036 · 35 minutes · Tool drill · Cluster Setup</p>
<h1>Triage kube-bench findings without obeying the scanner blindly</h1>
<p class="lede">A scanner accelerates inspection; it does not replace component knowledge. Extract non-passing checks, verify them against configuration, identify uncovered components, and prioritize fixes by impact.</p>
<h2>Environment note</h2>
<p>The current Windows shell has no Docker, WSL, Kubernetes CLI, or Linux node access. Use the provided kube-bench JSON report for this training attempt. Hero remains unavailable until you rerun kube-bench on a Linux control-plane and worker node.</p>
<h2>Task: 25 minutes</h2>
<p>Analyze these files without modifying them:</p>
<ul>
<li><code>lab/lesson-36-kube-bench.json</code></li>
<li><code>lab/lesson-35-kube-apiserver-insecure.yaml</code></li>
<li><code>lab/lesson-36-etcd.yaml</code></li>
<li><code>lab/lesson-28-kubelet-review.yaml</code></li>
<li><code>lab/lesson-36-coredns.yaml</code></li>
</ul>
<p>Create <code>lab/lesson-36-answer.md</code> containing:</p>
<ol>
<li>The exact PowerShell command used to extract every non-PASS result from the JSON.</li>
<li>A table for all seven FAIL results and the one WARN result: check ID, component, status, scanner evidence, configuration evidence, verdict, and precise remediation.</li>
<li>Your first three remediations in operational priority order, with one sentence of justification each.</li>
<li>At least four security findings from the CoreDNS Deployment that kube-bench did not report.</li>
<li>One paragraph explaining why WARN does not mean FAIL, why PASS is not universal proof, and why CoreDNS requires manual review here.</li>
<li>The exact Linux commands you would use to install pinned kube-bench v0.16.0, verify its checksum, run control-plane/etcd/node/policies targets as root, save JSON, and make CI return a nonzero code when checks fail.</li>
</ol>
<div class="callout"><strong>Tool reflex:</strong> kube-bench has PASS, FAIL, WARN, and INFO states. A WARN commonly needs manual attention. A failed check can also reflect an execution or detection problem, so compare <code>actual_value</code> and <code>reason</code> with effective configuration before changing a node.</div>
<h2>PowerShell starting shape</h2>
<pre><code>$report = Get-Content .\lab\lesson-36-kube-bench.json -Raw | ConvertFrom-Json
$report.Controls.tests.results |
Where-Object status -ne 'PASS' |
Select-Object test_number, status, test_desc, actual_value, reason</code></pre>
<h2>Linux Hero rerun shape</h2>
<pre><code># Run on a Linux node with access to component processes and files.
sudo kube-bench run --targets master,etcd,node,policies \
--json --outputfile kube-bench.json --exit-code 42</code></pre>
<p>You must determine and record the complete pinned installation and checksum-verification commands yourself.</p>
<h2>Retrieval check</h2>
<div class="quiz">
<h3>Question</h3>
<p>kube-bench reports WARN for a manual check. What should you do?</p>
<label><input type="radio" name="q" value="verify">Inspect the effective configuration and record a manual verdict.</label>
<label><input type="radio" name="q" value="fail">Treat the warning as a proven configuration failure immediately.</label>
<label><input type="radio" name="q" value="ignore">Ignore the warning because only automated checks matter.</label>
<button onclick="check()">Check answer</button>
<p id="feedback" class="feedback" aria-live="polite"></p>
</div>
<h2>Documentation targets</h2>
<p>Use the official <a href="https://github.com/aquasecurity/kube-bench">kube-bench repository</a>, its <a href="https://github.com/aquasecurity/kube-bench/blob/main/docs/installation.md">installation guide</a>, and the applicable CIS benchmark guidance after your first analysis.</p>
<h2>What to send me</h2>
<p>Save the Markdown answer and say <em>check</em>. I will list every issue and correct one per round. This attempt can advance CS-02 training, but the Hero tool gate requires a later real-node run.</p>
<footer>Previous: <a href="0035-apiserver-audit-hard-mode.html">API server and audit hard mode</a> · Tracker: <a href="../CKS-MASTERY-CHECKLIST.md">CKS Mastery Checklist</a></footer>
</main>
<script>
function check(){const c=document.querySelector('input[name=q]:checked'),f=document.getElementById('feedback');if(!c){f.textContent='Choose an answer.';f.className='feedback bad';return;}if(c.value==='verify'){f.textContent='Correct. WARN requires a manual, evidence-based verdict.';f.className='feedback good';}else{f.textContent='Not quite. The scanner has not proved either compliance or failure.';f.className='feedback bad';}}
</script>
</body>
</html>