Compare commits
4 Commits
a89b4ed4c2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac6292db20 | ||
|
|
d74b79cfc6 | ||
|
|
03db3343c1 | ||
|
|
93c7781891 |
3
CKS-DASHBOARD.html
Normal file
3
CKS-DASHBOARD.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>CKS mastery dashboard</title><link rel="stylesheet" href="assets/course.css"><style>
|
||||
body{background:linear-gradient(135deg,#e8effd,#f7f9fc 50%,#e8f8f1);font-family:Arial,sans-serif}main{max-width:1050px!important;padding:0!important;overflow:hidden;border-radius:20px}.hero{padding:45px 52px;color:#fff;background:radial-gradient(circle at 90% 15%,#315da9,#0b1736 65%)}.hero h1{color:#fff;font-size:2.5rem}.hero .lede{color:#dce7ff}.hero .eyebrow{color:#75e0bd}.content{padding:34px 52px}.grid{display:grid;grid-template-columns:220px 1fr;gap:32px;align-items:center}.ring{width:190px;height:190px;position:relative;display:grid;place-items:center}.ring svg{width:190px;transform:rotate(-90deg)}circle{fill:none;stroke-width:14}.track{stroke:#edf0f5}.progress{stroke:#75e0bd;stroke-linecap:round;stroke-dasharray:503;stroke-dashoffset:75}.ring div{position:absolute;text-align:center}.ring b{display:block;font-size:2.2rem}.ring span,.muted{color:#667085;font-size:.8rem}.stats,.checks,.domains{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.card,.check{padding:15px;border:1px solid #e6ebf2;border-radius:12px;background:#f8fafc}.card b{font-size:1.65rem;color:#0b1736}.card span{display:block;color:#667085;font-size:.7rem;text-transform:uppercase;margin-top:5px}h2{border:0!important;padding:0!important;margin:0;color:#0b1736}.title{display:flex;justify-content:space-between;align-items:baseline;border-bottom:1px solid #e6ebf2;margin:38px 0 14px;padding-bottom:9px}.domains{grid-template-columns:1fr 1fr}.domain{display:grid;grid-template-columns:135px 1fr 32px;gap:8px;align-items:center;font-size:.8rem;font-weight:bold}.bar{height:9px;background:#e8edf4;border-radius:9px;overflow:hidden}.bar i{display:block;height:100%;background:linear-gradient(90deg,#4c8df0,#75e0bd)}.check{padding-left:42px;position:relative;font-size:.84rem}.check:before{position:absolute;left:14px;top:14px;width:18px;height:18px;border-radius:50%;display:grid;place-items:center}.done:before{content:"✓";background:#75e0bd}.todo:before{content:"";border:2px solid #aeb8c9}.check small{display:block;color:#667085;margin-top:5px}.next{margin-top:38px;padding:25px 28px;border-radius:16px;background:linear-gradient(105deg,#f1f7ff,#f1fcf7);display:grid;grid-template-columns:1fr auto;gap:20px;align-items:center}.next a{padding:12px 16px;border-radius:8px;background:#0b1736;color:#fff;text-decoration:none;font-weight:bold;font-size:.85rem}@media(max-width:700px){main{margin:0!important;border-radius:0!important}.hero,.content{padding-left:24px;padding-right:24px}.grid,.stats,.checks,.domains,.next{grid-template-columns:1fr}.next a{text-align:center}}
|
||||
</style></head><body><main><header class="hero"><p class="eyebrow">CKS mastery dashboard · updated 27 August 2026</p><h1>Build confidence into evidence.</h1><p class="lede">Lab ready · Kubernetes v1.34 · Linux tools installed · 2 CIS labs passed today</p></header><section class="content"><div class="grid"><div class="ring"><svg viewBox="0 0 190 190"><circle class="track" cx="95" cy="95" r="80"/><circle class="progress" cx="95" cy="95" r="80"/></svg><div><b>85%</b><span>topic coverage</span></div></div><div><h2>22 of 26 topics have practical training evidence.</h2><p class="muted">Hero is deliberately strict: tool drill, capstone, evidence, scope review, and cold retest.</p><div class="stats"><div class="card"><b>22</b><span>training</span></div><div class="card"><b>4</b><span>not started</span></div><div class="card"><b>0</b><span>heroes—yet</span></div></div></div></div><div class="title"><h2>Coverage by domain</h2><span class="muted">training / total</span></div><div class="domains"><div class="domain">Cluster Setup <div class="bar"><i style="width:100%"></i></div>5/5</div><div class="domain">Cluster Hardening <div class="bar"><i style="width:75%"></i></div>3/4</div><div class="domain">System Hardening <div class="bar"><i style="width:50%"></i></div>2/4</div><div class="domain">Microservices <div class="bar"><i style="width:100%"></i></div>4/4</div><div class="domain">Supply Chain <div class="bar"><i style="width:75%"></i></div>3/4</div><div class="domain">Monitoring & Runtime <div class="bar"><i style="width:100%"></i></div>5/5</div></div><div class="title"><h2>CS-02 Hero checklist</h2><span class="muted">CIS components</span></div><div class="checks"><div class="check done"><b>Tool drills</b><small>kube-bench, etcd, and kubelet practised</small></div><div class="check todo"><b>Timed capstone</b><small>multi-component remediation</small></div><div class="check todo"><b>Evidence & cold retest</b><small>saved PASS groups, then repeat later</small></div></div><section class="next"><div><p class="eyebrow">Next win</p><h2>CS-02.Q4 — secure CoreDNS component review</h2><p class="muted">Deployment, ServiceAccount, RBAC, ConfigMap, image, and security context.</p></div><a href="CKS-MASTERY-CHECKLIST.md">Open checklist</a></section><footer>Latest pass: Lesson 38 — five kubelet controls verified. · <a href="CKS-MASTERY-CHECKLIST.md">Canonical checklist</a></footer></section></main></body></html>
|
||||
1
CKS-Lessons
Submodule
1
CKS-Lessons
Submodule
Submodule CKS-Lessons added at a89b4ed4c2
@@ -58,18 +58,18 @@ Minor syntax corrections during training are expected. A cold retest fails when
|
||||
|
||||
## Next Task
|
||||
|
||||
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.
|
||||
Run `CS-02.Q4`: review CoreDNS deployment, ServiceAccount, RBAC, ConfigMap, image, and security context; distinguish CIS-relevant component configuration from workload hardening. Do not use the learner's Kubernetes v1.36 production cluster.
|
||||
|
||||
## Local Lab Environment
|
||||
|
||||
Status: `WINDOWS RESTART REQUIRED`
|
||||
Status: `READY`
|
||||
|
||||
- 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`.
|
||||
- Enter the ready lab with `lab-environment\\enter-lab.ps1`; verify or rebuild it with `lab-environment\\verify-lab.ps1` and `lab-environment\\02-install-and-build.ps1`.
|
||||
- Lesson scope: use Kind nodes for Kubernetes tasks and the disposable Ubuntu WSL2 VM for host/kernel hardening tasks.
|
||||
|
||||
---
|
||||
@@ -603,6 +603,9 @@ Append one row after every graded attempt.
|
||||
|
||||
| Date | Task | Topic | Time | Result | Critical errors | Evidence | Next action |
|
||||
|---|---|---|---:|---|---:|---|---|
|
||||
| 2026-08-27 | Lesson 0038 | CS-02 | Not recorded | Training pass | 0 after verifier correction | `lab/lesson-38-verify.sh /tmp/lesson-38-kubelet.yaml`: all PASS | Continue CS-02.Q4 |
|
||||
| 2026-08-27 | Lesson 0037 | CS-02 | Not recorded | Training pass | 0 after one correction | `lab/lesson-37-verify.sh /tmp/lesson-37-etcd.yaml`: all PASS | Continue CS-02.Q3 |
|
||||
| 2026-08-27 | Lesson 0036 | CS-02 | 90 minutes | Partial training evidence | etcd and worker checks not captured | `lab/lesson-36-controlplane-after.txt` shows 1.2.1 and 1.2.7 PASS | Run focused CS-02.Q2, then require PASS evidence |
|
||||
| 2026-08-26 | Lesson 0035 | CH-03 / MR-05 | Not recorded | Training pass | 0 after review | `lab/lesson-35-kube-apiserver-answer.yaml`, `lab/lesson-35-audit-policy.yaml` | Cold retest later |
|
||||
| 2026-08-26 | Lesson 0034 | CS-01 / MM-01 | Not recorded | Training pass | 0 after review | `lab/lesson-34-answer.yaml` | Cold retest later |
|
||||
| 2026-08-25 | Lesson 0032 | MR-03 | Not recorded | Training; evidence incomplete | 0 substantive; command omitted | `lab/lesson-32-answer.md` | Require structured query next time |
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# CKS training workspace
|
||||
|
||||
Start with the [CKS Mastery Dashboard](CKS-DASHBOARD.html). The [Mastery Checklist](CKS-MASTERY-CHECKLIST.md) is the canonical record of evidence, Hero gates, and the next task.
|
||||
|
||||
@@ -20,7 +20,15 @@ EOF
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install -y ca-certificates curl gnupg jq vim git iproute2 iptables conntrack socat
|
||||
apt-get install -y \
|
||||
bash-completion ca-certificates conntrack curl dnsutils git gnupg iproute2 \
|
||||
iptables iputils-ping jq less lsof man-db nano netcat-openbsd procps psmisc \
|
||||
socat strace tcpdump tree vim wget yq
|
||||
|
||||
cat >/etc/profile.d/cks-lab.sh <<'EOF'
|
||||
alias k=kubectl
|
||||
complete -o default -F __start_kubectl k 2>/dev/null || true
|
||||
EOF
|
||||
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||
@@ -45,20 +53,20 @@ curl -fsSLo "$tmp_dir/kubectl.sha256" "https://dl.k8s.io/release/${KUBECTL_VERSI
|
||||
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-linux-amd64" "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
|
||||
install -m 0755 "$tmp_dir/kind-linux-amd64" /usr/local/bin/kind
|
||||
|
||||
curl -fsSLo "$tmp_dir/kube-bench.tar.gz" \
|
||||
curl -fsSLo "$tmp_dir/kube-bench_${KUBE_BENCH_VERSION}_linux_amd64.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
|
||||
tar -xzf "$tmp_dir/kube-bench_${KUBE_BENCH_VERSION}_linux_amd64.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' \
|
||||
printf 'Installed CKS command-line tools plus kubectl %s, Kind %s, and kube-bench %s.\n' \
|
||||
"$KUBECTL_VERSION" "$KIND_VERSION" "$KUBE_BENCH_VERSION"
|
||||
|
||||
@@ -31,9 +31,9 @@ if [[ "$context" != "kind-${CLUSTER_NAME}" ]]; then
|
||||
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 apply --server-side --validate=false -f "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/operator-crds.yaml"
|
||||
kubectl apply --server-side --validate=false -f "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/tigera-operator.yaml"
|
||||
kubectl apply --server-side --validate=false -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
|
||||
@@ -43,4 +43,3 @@ for node in "${CLUSTER_NAME}-control-plane" "${CLUSTER_NAME}-worker"; do
|
||||
docker cp /opt/cks-lab/tools/kube-bench "$node":/opt/kube-bench
|
||||
docker exec "$node" /opt/kube-bench/kube-bench version
|
||||
done
|
||||
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$distribution = 'Ubuntu-24.04'
|
||||
$linuxScript = (& wsl.exe --distribution $distribution --user root --exec wslpath -a "$PSScriptRoot/enter-lab.sh").Trim()
|
||||
if (-not $linuxScript) { throw 'Could not locate the Linux lab entry script.' }
|
||||
|
||||
& 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
|
||||
'@
|
||||
& wsl.exe --distribution $distribution --user root --exec bash $linuxScript
|
||||
|
||||
if ($LASTEXITCODE -ne 0) { throw 'Could not enter the isolated CKS lab.' }
|
||||
|
||||
|
||||
25
lab-environment/enter-lab.sh
Normal file
25
lab-environment/enter-lab.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/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
|
||||
|
||||
echo "CKS lab: $(kubectl version --output=json | jq -r .serverVersion.gitVersion)"
|
||||
echo "Context: $context"
|
||||
required_tools=(kubectl kube-bench nano vim curl wget jq yq dig nc ss ps less)
|
||||
missing_tools=()
|
||||
for tool in "${required_tools[@]}"; do
|
||||
command -v "$tool" >/dev/null 2>&1 || missing_tools+=("$tool")
|
||||
done
|
||||
if (( ${#missing_tools[@]} )); then
|
||||
echo "Lab setup incomplete; missing: ${missing_tools[*]}. Run ./02-install-and-build.ps1." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Tools: ready (nano, curl, wget, jq, yq, dig, nc, tcpdump, ss); alias k=kubectl"
|
||||
exec bash
|
||||
17
lab/lesson-36-controlplane-after.txt
Normal file
17
lab/lesson-36-controlplane-after.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
root@cks-lab-control-plane:/opt/kube-bench# ./kube-bench --benchmark cis-1.12 --config-dir cfg run --targets master --check 1.2.1,1.2.7,2.2,2.3
|
||||
[INFO] 1 Control Plane Security Configuration
|
||||
[INFO] 1.2 API Server
|
||||
[PASS] 1.2.1 Ensure that the --anonymous-auth argument is set to false (Manual)
|
||||
[PASS] 1.2.7 Ensure that the --authorization-mode argument includes Node (Automated)
|
||||
|
||||
== Summary master ==
|
||||
2 checks PASS
|
||||
0 checks FAIL
|
||||
0 checks WARN
|
||||
0 checks INFO
|
||||
|
||||
== Summary total ==
|
||||
2 checks PASS
|
||||
0 checks FAIL
|
||||
0 checks WARN
|
||||
0 checks INFO
|
||||
22
lab/lesson-36-controlplane-before.txt
Normal file
22
lab/lesson-36-controlplane-before.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
[INFO] 1 Control Plane Security Configuration
|
||||
[INFO] 1.2 API Server
|
||||
[WARN] 1.2.1 Ensure that the --anonymous-auth argument is set to false (Manual)
|
||||
[PASS] 1.2.7 Ensure that the --authorization-mode argument includes Node (Automated)
|
||||
|
||||
== Remediations master ==
|
||||
1.2.1 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the control plane node and set the below parameter.
|
||||
--anonymous-auth=false
|
||||
|
||||
|
||||
== Summary master ==
|
||||
1 checks PASS
|
||||
0 checks FAIL
|
||||
1 checks WARN
|
||||
0 checks INFO
|
||||
|
||||
== Summary total ==
|
||||
1 checks PASS
|
||||
0 checks FAIL
|
||||
1 checks WARN
|
||||
0 checks INFO
|
||||
15
lab/lesson-36-worker-before.txt
Normal file
15
lab/lesson-36-worker-before.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
root@cks-lab-worker:/opt/kube-bench# ./kube-bench --benchmark cis-1.12 --config-dir cfg run --targets master --check 4.2.1,4.2.2,4.2.3
|
||||
Warning: Kubernetes version was not auto-detected because kubectl could not connect to the Kubernetes server. This may be because the kubeconfig information is missing or has credentials that do not match the server. Assuming default version 1.18
|
||||
[INFO] 1 Control Plane Security Configuration
|
||||
|
||||
== Summary master ==
|
||||
0 checks PASS
|
||||
0 checks FAIL
|
||||
0 checks WARN
|
||||
0 checks INFO
|
||||
|
||||
== Summary total ==
|
||||
0 checks PASS
|
||||
0 checks FAIL
|
||||
0 checks WARN
|
||||
0 checks INFO
|
||||
47
lab/lesson-37-etcd-insecure.yaml
Normal file
47
lab/lesson-37-etcd-insecure.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: etcd
|
||||
namespace: kube-system
|
||||
labels:
|
||||
component: etcd
|
||||
spec:
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: etcd
|
||||
image: registry.k8s.io/etcd:3.6.4-0
|
||||
command:
|
||||
- etcd
|
||||
- --name=controlplane
|
||||
- --data-dir=/var/lib/etcd
|
||||
- --listen-client-urls=http://127.0.0.1:2379,https://10.0.0.10:2379
|
||||
- --advertise-client-urls=https://10.0.0.10:2379
|
||||
- --initial-advertise-peer-urls=https://10.0.0.10:2380
|
||||
- --listen-peer-urls=https://10.0.0.10:2380
|
||||
- --initial-cluster=controlplane=https://10.0.0.10:2380
|
||||
- --client-cert-auth=false
|
||||
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
|
||||
- --cert-file=/etc/kubernetes/pki/etcd/server.crt
|
||||
- --key-file=/etc/kubernetes/pki/etcd/server.key
|
||||
- --auto-tls=true
|
||||
- --peer-client-cert-auth=false
|
||||
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
|
||||
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
|
||||
- --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
|
||||
- --peer-auto-tls=true
|
||||
- --listen-metrics-urls=http://0.0.0.0:2381
|
||||
volumeMounts:
|
||||
- name: etcd-data
|
||||
mountPath: /var/lib/etcd
|
||||
- name: etcd-certs
|
||||
mountPath: /etc/kubernetes/pki/etcd
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: etcd-data
|
||||
hostPath:
|
||||
path: /var/lib/etcd
|
||||
type: DirectoryOrCreate
|
||||
- name: etcd-certs
|
||||
hostPath:
|
||||
path: /etc/kubernetes/pki/etcd
|
||||
type: DirectoryOrCreate
|
||||
28
lab/lesson-37-verify.sh
Normal file
28
lab/lesson-37-verify.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
manifest=${1:?Usage: lesson-37-verify.sh PATH_TO_MANIFEST}
|
||||
[[ -f "$manifest" ]] || { echo "FAIL manifest not found"; exit 1; }
|
||||
|
||||
required=(
|
||||
'--client-cert-auth=true'
|
||||
'--auto-tls=false'
|
||||
'--peer-client-cert-auth=true'
|
||||
'--peer-auto-tls=false'
|
||||
'--trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt'
|
||||
'--peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt'
|
||||
'--listen-metrics-urls=http://127.0.0.1:2381'
|
||||
)
|
||||
for flag in "${required[@]}"; do
|
||||
if grep -Fqx " - $flag" "$manifest"; then
|
||||
echo "PASS $flag"
|
||||
else
|
||||
echo "FAIL $flag"
|
||||
fi
|
||||
done
|
||||
|
||||
if grep -Eq 'http://0\.0\.0\.0:2381|http://127\.0\.0\.1:2379' "$manifest"; then
|
||||
echo 'FAIL insecure etcd listener remains'
|
||||
else
|
||||
echo 'PASS no insecure etcd listener'
|
||||
fi
|
||||
1
lab/lesson-38-effective-args.txt
Normal file
1
lab/lesson-38-effective-args.txt
Normal file
@@ -0,0 +1 @@
|
||||
/usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/tmp/lesson-38-kubelet.yaml --anonymous-auth=false --authentication-token-webhook=true --authorization-mode=Webhook --read-only-port=0 --rotate-certificates=true
|
||||
11
lab/lesson-38-kubelet-config.yaml
Normal file
11
lab/lesson-38-kubelet-config.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
kind: KubeletConfiguration
|
||||
authentication:
|
||||
anonymous:
|
||||
enabled: true
|
||||
webhook:
|
||||
enabled: false
|
||||
authorization:
|
||||
mode: AlwaysAllow
|
||||
readOnlyPort: 10255
|
||||
rotateCertificates: false
|
||||
17
lab/lesson-38-verify.sh
Normal file
17
lab/lesson-38-verify.sh
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
config=${1:?Usage: lesson-38-verify.sh PATH_TO_CONFIG}
|
||||
[[ -f "$config" ]] || { echo "FAIL configuration not found"; exit 1; }
|
||||
|
||||
check() {
|
||||
local label=$1 expected=$2 query=$3 actual
|
||||
actual="$(yq -r "$query" "$config")"
|
||||
if [[ "$actual" == "$expected" ]]; then echo "PASS $label"; else echo "FAIL $label (got: $actual)"; fi
|
||||
}
|
||||
|
||||
check 'anonymous authentication disabled' false '.authentication.anonymous.enabled'
|
||||
check 'webhook authentication enabled' true '.authentication.webhook.enabled'
|
||||
check 'webhook authorization selected' Webhook '.authorization.mode'
|
||||
check 'read-only port disabled' 0 '.readOnlyPort'
|
||||
check 'certificate rotation enabled' true '.rotateCertificates'
|
||||
@@ -0,0 +1,7 @@
|
||||
# etcd transport and metrics hardening
|
||||
|
||||
The learner independently remediated an etcd static manifest to require client and peer certificates, disable automatic TLS, eliminate HTTP client exposure, and bind metrics to loopback while preserving the existing CA and certificate paths. This establishes a reliable baseline for the next CIS drill: reconciling kubelet configuration with its effective process.
|
||||
|
||||
## Evidence
|
||||
|
||||
`lab/lesson-37-verify.sh /tmp/lesson-37-etcd.yaml` reported every required control as PASS on 2026-08-27.
|
||||
7
learning-records/0012-kubelet-effective-configuration.md
Normal file
7
learning-records/0012-kubelet-effective-configuration.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Kubelet configuration and effective flags
|
||||
|
||||
The learner reconciled an insecure KubeletConfiguration with approved effective flags, independently setting anonymous authentication off, webhook authentication and authorization on, the read-only port to zero, and certificate rotation on. Future CIS practice can now combine configuration-file review with process-argument verification.
|
||||
|
||||
## Evidence
|
||||
|
||||
`lab/lesson-38-verify.sh /tmp/lesson-38-kubelet.yaml` reported all five controls as PASS on 2026-08-27.
|
||||
4
lessons/0037-etcd-static-manifest-hardening.html
Normal file
4
lessons/0037-etcd-static-manifest-hardening.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Lesson 37: etcd static-manifest hardening</title><link rel="stylesheet" href="../assets/course.css"></head><body><main><p class="eyebrow">Lesson 0037 · 15 minutes · Linux performance lab · Cluster Setup</p><h1>Harden etcd without breaking membership</h1><p class="lede">This is a focused CIS remediation drill. It deliberately removes the cluster-entry and package-installation friction from the previous attempt.</p><div class="callout"><strong>Scope discipline:</strong> change only the insecure transport, authentication, and metrics flags. Preserve identity, data, listen/advertise peer addresses, initial cluster membership, certificates, mounts, and image.</div><h2>Task</h2><p>On the Linux lab shell, create <code>/tmp/lesson-37-etcd.yaml</code> from <code>lab/lesson-37-etcd-insecure.yaml</code>. Make it pass the supplied verifier.</p><ul><li>Require client and peer client certificates.</li><li>Disable automatic TLS for both client and peer traffic.</li><li>Keep the existing explicit CA, certificate, and key paths.</li><li>Ensure client traffic uses HTTPS only.</li><li>Bind the metrics listener only to <code>127.0.0.1:2381</code>.</li></ul><p>Do not edit the original fixture or verifier. Do not use <code>kubectl apply</code>; this is a static-manifest file exercise.</p><h2>Start and prove it</h2><pre><code>cd /mnt/c/Cloud-Team/04_Learning_and_Reference/Training/CKS
|
||||
cp lab/lesson-37-etcd-insecure.yaml /tmp/lesson-37-etcd.yaml
|
||||
nano /tmp/lesson-37-etcd.yaml
|
||||
bash lab/lesson-37-verify.sh /tmp/lesson-37-etcd.yaml</code></pre><p>Completion means every line reports <code>PASS</code>. Send that output only.</p><h2>Documentation</h2><p>Use the official <a href="https://etcd.io/docs/v3.6/op-guide/security/">etcd transport security guide</a> if needed. The CKS objective is preserving the required configuration while closing only the proven exposure.</p><footer>Previous: <a href="0036-kube-bench-cis-remediation.html">kube-bench CIS remediation</a> · Tracker: <a href="../CKS-MASTERY-CHECKLIST.md">CKS Mastery Checklist</a></footer></main></body></html>
|
||||
6
lessons/0038-kubelet-effective-configuration.html
Normal file
6
lessons/0038-kubelet-effective-configuration.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Lesson 38: kubelet effective configuration</title><link rel="stylesheet" href="../assets/course.css"></head><body><main><p class="eyebrow">Lesson 0038 · 15 minutes · Linux performance lab · Cluster Setup</p><h1>Reconcile kubelet configuration with effective flags</h1><p class="lede">Kubelet security faults often come from believing a configuration file is the whole truth. Inspect the effective arguments, then make the structured configuration agree with the required boundary.</p><div class="callout"><strong>Scope:</strong> the effective arguments in this task are the approved cluster policy. Correct the supplied <code>KubeletConfiguration</code>; do not change the argument file or add unrelated fields.</div><h2>Task</h2><p>On the Linux lab shell, create <code>/tmp/lesson-38-kubelet.yaml</code> from <code>lab/lesson-38-kubelet-config.yaml</code>. It must match the security posture expressed by <code>lab/lesson-38-effective-args.txt</code>.</p><p>Bring all five controls into agreement: anonymous authentication, webhook authentication, authorization mode, read-only port, and certificate rotation.</p><h2>Start and verify</h2><pre><code>cd /mnt/c/Cloud-Team/04_Learning_and_Reference/Training/CKS
|
||||
cat lab/lesson-38-effective-args.txt
|
||||
cp lab/lesson-38-kubelet-config.yaml /tmp/lesson-38-kubelet.yaml
|
||||
nano /tmp/lesson-38-kubelet.yaml
|
||||
bash lab/lesson-38-verify.sh /tmp/lesson-38-kubelet.yaml</code></pre><p>Completion means five <code>PASS</code> lines. Send only that output.</p><h2>Exam-speed inspection</h2><pre><code>docker exec cks-lab-worker ps -ef | grep '[k]ubelet'
|
||||
docker exec cks-lab-worker sed -n '1,120p' /var/lib/kubelet/config.yaml</code></pre><p>Use these after the task to compare the fixture with the real disposable worker. Do not modify the live worker configuration for this drill.</p><footer>Previous: <a href="0037-etcd-static-manifest-hardening.html">etcd static-manifest hardening</a> · Tracker: <a href="../CKS-MASTERY-CHECKLIST.md">CKS Mastery Checklist</a></footer></main></body></html>
|
||||
Reference in New Issue
Block a user