diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d411f3..bf6a2e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,9 @@ Every entry names the commit it came in. - CKS Q4 gave 3 of its 12 points untouched: its token check took any Pod of the Deployment, and an untouched Deployment's Pods run as `default`, with a token mounted. It now takes a Pod that runs as `-sa`. +- CKS Q103 failed to seed once, six hosts at a time: a minute passed without a Falco alert naming + the Pod. Its setup now tries a new Pod - a container Falco's container plugin looks up afresh - + before it gives up. - Building a host image for a kind image not pulled yet: podman's pull progress was read as the etcd image's name. - A solution or lesson step that prints binary data (an etcd value) no longer stops the audit. diff --git a/README.md b/README.md index 6de7994..9c7449f 100644 --- a/README.md +++ b/README.md @@ -208,15 +208,19 @@ cluster from v1.36.4 to v1.37.1, worker included. their own, score nothing when graded untouched 45 seconds after seeding, and reach full marks when their scripted solution is run on the host as `candidate`. -**CKS, as audited on 2026-10-19** (v1.37, Ubuntu hosts): 109 of 110 tasks seed cleanly on a host -of their own, score nothing when graded untouched 45 seconds after seeding, and reach full marks -when their scripted solution is run on the host as `candidate`. Q103, a Falco task on a VM host, -failed to seed once — Falco raised no alert naming the Pod within a minute — and is still to be -audited again. The 26 objectives are the curriculum's own (`cks/curriculum.py`), each with notes, -commands, traps and the documentation the exam allows — which, per the Linux Foundation's list -read on 2026-10-12, is the Kubernetes docs and blog plus Falco, bom, etcd, the NGINX Ingress +**CKS, as audited on 2026-10-19** (v1.37, Ubuntu hosts): all 110 tasks seed cleanly on a host of +their own, score nothing when graded untouched 45 seconds after seeding, and reach full marks when +their scripted solution is run on the host as `candidate`. Q103, a Falco task on a VM host, failed +to seed once that day — a minute passed without an alert naming the Pod — and passed on +2026-10-20, alone and with the other seven VM tasks six at a time; its setup now tries a new Pod +before it gives up. The 26 objectives are the curriculum's own (`cks/curriculum.py`), each with +notes, commands, traps and the documentation the exam allows — which, per the Linux Foundation's +list read on 2026-10-12, is the Kubernetes docs and blog plus Falco, bom, etcd, the NGINX Ingress Controller, Cilium and Istio. Trivy's and AppArmor's own documentation are not on it. +**On 2026-10-20**, after `hexdump` and `xxd` were added to the hosts, CKA Q132 (the upgrade from +v1.36), CKAD Q1 and CKS Q60, Q61 and Q64 passed again on the rebuilt images. + ### A task ```python diff --git a/cks/bank_vm.py b/cks/bank_vm.py index 93854d5..2068cad 100644 --- a/cks/bank_vm.py +++ b/cks/bank_vm.py @@ -57,8 +57,18 @@ for d in frontend worker cache reports; do $K -n %{ns} create deploy $d --image=busybox:1.36 -- sh -c "$cmd" >/dev/null done for d in frontend worker cache reports; do $K -n %{ns} rollout status deploy $d --timeout=240s >/dev/null || exit 1; done -pod=$($K -n %{ns} get pod -l app=%{bad} -o jsonpath='{.items[0].metadata.name}'); echo "%{ns}/$pod" > "$PRIV/q103" -falco_up && alerted "Sensitive file opened.*k8s_pod_name=$pod " 60 || { echo "Falco raised no alert for the Pod" >&2; exit 1; } +# Once, in an audit of 19 tasks six hosts at a time, a minute passed without an alert naming the +# Pod. A new Pod is a new container, which Falco's container plugin looks up afresh: the setup +# tries one before it gives up. +named= +for try in 1 2; do + pod=$($K -n %{ns} get pod -l app=%{bad} -o jsonpath='{.items[0].metadata.name}'); echo "%{ns}/$pod" > "$PRIV/q103" + falco_up && alerted "Sensitive file opened.*k8s_pod_name=$pod " 60 && { named=1; break; } + [ $try = 2 ] && break + $K -n %{ns} delete pod "$pod" --grace-period=1 >/dev/null 2>&1 + $K -n %{ns} wait --for=condition=Ready pod -l app=%{bad} --timeout=240s >/dev/null || exit 1 +done +[ -n "$named" ] || { echo "Falco raised no alert for the Pod" >&2; exit 1; } """, "checks": [ C("pod.txt names the Pod that reads /etc/shadow", 3, r"""eq "$(tr -d ' \n\r' < "$WS/q103/pod.txt" 2>/dev/null)" "$(cat "$PRIV/q103")" """),