diff --git a/CKS-MASTERY-CHECKLIST.md b/CKS-MASTERY-CHECKLIST.md new file mode 100644 index 0000000..c68a2ba --- /dev/null +++ b/CKS-MASTERY-CHECKLIST.md @@ -0,0 +1,597 @@ +# CKS Mastery Checklist + +Canonical progress record for CKS preparation. Update this file after every graded task so another computer or agent can resume without relying on chat history. + +## Dashboard + +Last updated: 2026-08-26 + +| Domain | Weight | Hero | Training | Not started | Total | +|---|---:|---:|---:|---:|---:| +| Cluster Setup | 15% | 0 | 5 | 0 | 5 | +| Cluster Hardening | 15% | 0 | 3 | 1 | 4 | +| System Hardening | 10% | 0 | 2 | 2 | 4 | +| Minimize Microservice Vulnerabilities | 20% | 0 | 4 | 0 | 4 | +| Supply Chain Security | 20% | 0 | 3 | 1 | 4 | +| Monitoring, Logging and Runtime Security | 20% | 0 | 5 | 0 | 5 | +| **Total** | **100%** | **0** | **22** | **4** | **26** | + +The syllabus supplied for this program contains 26 tracked topics. + +## Status Legend + +- `[ ] NOT STARTED`: no dedicated practical evidence. +- `[~] TRAINING`: relevant lessons exist, but the Hero gate is incomplete. +- `[x] HERO`: tool drill, timed capstone, evidence, and cold retest all passed. +- `BLOCKED`: environment prevents practice; record the exact limitation and use a valid alternate environment. + +## Hero Gate + +A topic becomes Hero only when every item is checked: + +- [ ] Tool drill completed using the topic's primary operational tools. +- [ ] Original capstone completed at exam difficulty or harder within its time limit. +- [ ] Verification evidence saved: commands plus meaningful output, not YAML alone. +- [ ] No critical security or scope error remains after review. +- [ ] Cold retest passed in a later session without stepwise prompting. +- [ ] Evidence paths and date added to this checklist. + +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. + +## Resume Protocol + +1. Read `MISSION.md`, `NOTES.md`, the newest learning record, and this file. +2. Show the dashboard and list Hero, Training, Not Started, and Blocked topics. +3. Continue `Next task` unless the learner selects another topic. +4. Save each answer under `lab/`, each lesson under `lessons/`, and durable insight under `learning-records/`. +5. After grading, update status, Hero-gate boxes, evidence, attempt log, dashboard counts, and `Next task`. +6. Show the learner the updated done-versus-remaining summary. + +## 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. + +--- + +## Cluster Setup - 15% + +### CS-01 - Use network security policies to restrict cluster-level access + +Status: `[~] TRAINING` + +Tools: `kubectl`, NetworkPolicy API, `curl`/`wget`, temporary test Pods, CNI policy observability where available. + +Prior evidence: Lessons 0002, 0008, 0029, and 0034. The learner can build default-deny and selector-scoped ingress/egress policies, include CoreDNS, and combine Namespace and Pod selectors. + +Question bank: + +- `CS-01.Q1` - Given five namespaces and six traffic requirements, produce the minimum additive policy set and prove every allowed and denied flow with disposable client Pods. +- `CS-01.Q2` - Repair a policy where split peer items accidentally OR namespace and Pod selectors; demonstrate the over-permitted flow before and denial after. +- `CS-01.Q3` - Isolate control-plane and node endpoints from an application namespace while preserving DNS and one internal API dependency. +- `CS-01.Q4` - Hard capstone: troubleshoot a syntactically valid policy that has no effect because of selectors, CNI behavior, or existing additive policies; submit packet-flow evidence. + +Hero-specific acceptance: prove ingress and egress outcomes, explain additive policy behavior, and avoid wildcard peers, IP-based shortcuts, or accidental DNS failure. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### CS-02 - Use CIS benchmarks to review Kubernetes components + +Status: `[~] TRAINING` + +Tools: `kube-bench`, `systemctl`, `ps`, `grep`, `kubectl`, static manifests, kubelet config, CoreDNS ConfigMap. + +Prior evidence: Lessons 0015, 0022, 0028, and 0035 cover kubelet and kube-apiserver manually. Dedicated kube-bench, etcd, and CoreDNS review evidence is missing. + +Question bank: + +- `CS-02.Q1` - Run `kube-bench` for control-plane and node checks; classify PASS, FAIL, WARN, and manual checks without blindly applying recommendations. +- `CS-02.Q2` - Harden an etcd static manifest: client certificate authentication, peer TLS, trusted CAs, ownership, and metrics exposure; preserve cluster membership flags. +- `CS-02.Q3` - Review kubelet flags plus `KubeletConfiguration`, reconcile conflicting settings, and verify the effective running process. +- `CS-02.Q4` - Review CoreDNS deployment, ServiceAccount, RBAC, ConfigMap, image, and security context; distinguish CIS-relevant component configuration from workload hardening. +- `CS-02.Q5` - Hard capstone: given kube-bench output containing false positives and manual checks, remediate only proven failures across API server, etcd, kubelet, and CoreDNS. + +Hero-specific acceptance: correlate scanner output with effective configuration and preserve required component behavior. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### CS-03 - Properly set up Ingress with TLS + +Status: `[~] TRAINING` + +Tools: `openssl`, `kubectl`, Ingress API, TLS Secrets, `curl -vk`, `openssl s_client`. + +Prior evidence: Lesson 0016. Ingress v1 nesting and host alignment required correction; live certificate inspection needs more practice. + +Question bank: + +- `CS-03.Q1` - Generate a certificate and key, create a TLS Secret, configure v1 Ingress, and verify hostname, chain, and backend routing. +- `CS-03.Q2` - Repair mismatched rule host, TLS host, Secret namespace, backend schema, and path type without changing the Service. +- `CS-03.Q3` - Use `openssl s_client` and `curl --resolve` to distinguish certificate, DNS, Ingress, and backend failures. +- `CS-03.Q4` - Hard capstone: migrate two HTTP routes to TLS with separate hostnames and prove that plaintext behavior matches stated redirect requirements. + +Hero-specific acceptance: certificate identity, Secret scope, route semantics, and end-to-end TLS evidence must all be correct. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### CS-04 - Protect node metadata and endpoints + +Status: `[~] TRAINING` + +Tools: NetworkPolicy, `curl`, cloud metadata addresses, CNI policy tools, workload identity controls, `ss`, `systemctl`, kubelet configuration, client certificates. + +Prior evidence: Lessons 0015, 0028, and 0029 cover link-local metadata isolation plus kubelet anonymous auth, webhook modes, read-only port, and certificate rotation. + +Question bank: + +- `CS-04.Q1` - Demonstrate metadata reachability from a disposable Pod, then deny it without breaking required internal egress. +- `CS-04.Q2` - Compare broad `ipBlock` denial with positive egress allowlisting and explain residual paths through proxies or host networking. +- `CS-04.Q3` - Harden a cloud workload using both network isolation and workload identity rather than static cloud credentials. +- `CS-04.Q4` - Hard capstone: contain metadata access for selected tenants while preserving DNS, API-server access, and one external HTTPS destination. +- `CS-04.Q5` - Enumerate listening Kubernetes node endpoints and identify which require authentication, authorization, or removal. +- `CS-04.Q6` - Harden kubelet config and prove anonymous requests fail while authorized health and management paths remain functional. +- `CS-04.Q7` - Review metrics, health, debug, and read-only ports; distinguish binding exposure from application-layer authorization. +- `CS-04.Q8` - Hard capstone: remediate metadata, kubelet, and node-firewall exposure together, then prove effective endpoint behavior. + +Hero-specific acceptance: show before-and-after metadata requests, verify listening sockets and authenticated endpoint behavior, and identify NetworkPolicy limitations for host-network or unsupported CNI cases. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### CS-05 - Verify platform binaries before deploying + +Status: `[~] TRAINING` + +Tools: `sha256sum`/`Get-FileHash`, signed checksum files, `gpg`, release metadata, package-manager verification. + +Prior evidence: Lesson 0019 verifies pinned Kubernetes binaries against checksums. + +Question bank: + +- `CS-05.Q1` - Download a pinned Kubernetes binary and official checksum, verify it, and record provenance. +- `CS-05.Q2` - Detect a tampered binary among valid artifacts without executing any candidate. +- `CS-05.Q3` - Verify a signed checksum manifest with GPG, then verify the binary against that trusted manifest. +- `CS-05.Q4` - Hard capstone: build a repeatable verification chain for kubelet, kubectl, and a security scanner, including failure handling. + +Hero-specific acceptance: pin versions, verify the trust root, fail closed on mismatch, and save exact commands and hashes. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +--- + +## Cluster Hardening - 15% + +### CH-01 - Use RBAC to minimize exposure + +Status: `[~] TRAINING` + +Tools: `kubectl auth can-i`, `kubectl auth reconcile`, RBAC API, impersonation flags, structured manifest inspection. + +Prior evidence: Lessons 0003, 0009, and 0024. Namespace scope, subresources, `resourceNames`, and negative permission tests are established strengths after correction. + +Question bank: + +- `CH-01.Q1` - Replace a wildcard Role with the smallest verbs, API groups, resources, subresources, and named resources that satisfy a workload. +- `CH-01.Q2` - Find privilege-escalation paths involving bind, escalate, impersonate, token creation, and workload creation. +- `CH-01.Q3` - Prove positive and negative permissions using impersonation for users, groups, and ServiceAccounts. +- `CH-01.Q4` - Hard capstone: remediate overlapping RoleBindings and ClusterRoleBindings without breaking one required cross-namespace workflow. + +Hero-specific acceptance: no wildcard privilege, every required permission proven, and every prohibited permission denied. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### CH-02 - Exercise caution with ServiceAccounts + +Status: `[~] TRAINING` + +Tools: `kubectl`, TokenRequest API, projected ServiceAccount tokens, RBAC, Pod inspection. + +Prior evidence: Lessons 0007 and 0034 cover automount suppression and least privilege. + +Question bank: + +- `CH-02.Q1` - Disable the default token for a namespace and enable a short-lived projected token only for one container with a fixed audience. +- `CH-02.Q2` - Replace use of the default ServiceAccount with a dedicated identity and minimal Role/RoleBinding. +- `CH-02.Q3` - Inspect a Pod for legacy Secret-based tokens, projected tokens, audiences, expiration, and unintended mounts. +- `CH-02.Q4` - Hard capstone: preserve one API-calling sidecar while preventing every other container from receiving cluster credentials. + +Hero-specific acceptance: token exposure and RBAC authority must both be minimized and verified. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### CH-03 - Restrict access to the Kubernetes API + +Status: `[~] TRAINING` + +Tools: kube-apiserver flags, authentication and authorization config, admission plugins, firewall/listener inspection, audit logs. + +Prior evidence: Lessons 0022 and 0035 cover anonymous auth, Node/RBAC authorization, ServiceAccount lookup, profiling, NodeRestriction, and audit integration. + +Question bank: + +- `CH-03.Q1` - Harden an API-server static manifest while preserving certificates, etcd, ServiceAccount signing, and admission configuration. +- `CH-03.Q2` - Restrict network reachability to the secure API endpoint and prove unauthorized and authorized outcomes. +- `CH-03.Q3` - Identify dangerous authentication files, anonymous paths, permissive authorization, and insecure profiling/debug exposure. +- `CH-03.Q4` - Hard capstone: reconcile flags with structured authentication/authorization configuration and verify the effective process. + +Hero-specific acceptance: preserve control-plane availability and prove both network and request-layer restrictions. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### CH-04 - Upgrade Kubernetes to avoid vulnerabilities + +Status: `[ ] NOT STARTED` + +Tools: `kubeadm`, `kubectl drain`, `apt`/`dnf`, package holds, version-skew policy, release notes. + +Prior evidence: none dedicated. + +Question bank: + +- `CH-04.Q1` - Inspect current versions, choose a supported target using version-skew rules, and produce the control-plane upgrade plan. +- `CH-04.Q2` - Upgrade `kubeadm`, run `kubeadm upgrade plan`, apply the selected version, then upgrade kubelet and kubectl safely. +- `CH-04.Q3` - Drain, upgrade, restart, and uncordon a worker while preserving workload availability. +- `CH-04.Q4` - Hard capstone: recover from a partially completed upgrade with mismatched kubeadm, kubelet, and API-server versions. + +Hero-specific acceptance: version selection, node ordering, drain behavior, package holds, health verification, and rollback reasoning must be demonstrated. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +--- + +## System Hardening - 10% + +### SH-01 - Minimize host OS footprint + +Status: `[ ] NOT STARTED` + +Tools: `systemctl`, `ss`, `ps`, package manager, filesystem permissions, system logs. + +Prior evidence: none dedicated. + +Question bank: + +- `SH-01.Q1` - Inventory installed packages, running services, listening sockets, and scheduled jobs on a Kubernetes node. +- `SH-01.Q2` - Disable and remove unnecessary services without disrupting kubelet, runtime, networking, storage, or time synchronization. +- `SH-01.Q3` - Review sensitive Kubernetes directories and correct unsafe ownership or permissions. +- `SH-01.Q4` - Hard capstone: reduce an intentionally bloated node image and prove cluster health plus reduced attack surface. + +Hero-specific acceptance: every removal needs a dependency justification and post-change node-health evidence. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### SH-02 - Use least-privilege host identity and access management + +Status: `[ ] NOT STARTED` + +Tools: Linux users/groups, `sudo`, SSH configuration, systemd unit identity, file capabilities, ownership and modes. + +Prior evidence: Kubernetes RBAC experience exists, but host IAM has no dedicated practical evidence. + +Question bank: + +- `SH-02.Q1` - Replace shared root access with named accounts and narrowly scoped sudo commands. +- `SH-02.Q2` - Run a node service under a dedicated non-login account with minimal filesystem access. +- `SH-02.Q3` - Audit SSH root login, password authentication, authorized keys, group membership, and sudoers fragments. +- `SH-02.Q4` - Hard capstone: contain a compromised maintenance account without breaking kubelet or container runtime operation. + +Hero-specific acceptance: prove denied privilege escalation and preserved operational access using audit-friendly named identities. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### SH-03 - Minimize external network access + +Status: `[~] TRAINING` + +Tools: `ss`, `nft`/`iptables`, cloud firewall/security groups, host firewall, `curl`, `nc`, NetworkPolicy. + +Prior evidence: Lessons 0015, 0029, and 0034 cover workload and kubelet exposure; host-firewall evidence is missing. + +Question bank: + +- `SH-03.Q1` - Enumerate listeners and map each socket to process, interface, required clients, and authentication control. +- `SH-03.Q2` - Restrict node management ports to an administration CIDR while preserving cluster traffic. +- `SH-03.Q3` - Distinguish host firewall, cloud firewall, Service exposure, and NetworkPolicy responsibilities. +- `SH-03.Q4` - Hard capstone: reduce external exposure across a node, NodePort Service, and host-network workload, then prove allowed and denied paths. + +Hero-specific acceptance: evidence must cover effective listeners and remote reachability from both permitted and prohibited sources. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### SH-04 - Use AppArmor and seccomp appropriately + +Status: `[~] TRAINING` + +Tools: `apparmor_parser`, `aa-status`, AppArmor profiles, seccomp profiles, Pod securityContext, runtime events. + +Prior evidence: Lessons 0004, 0011, and 0033. AppArmor enforcement was blocked by the Docker Desktop/WSL2 kernel; seccomp manifest work is established. + +Question bank: + +- `SH-04.Q1` - Create, load, and enforce an AppArmor profile that permits required reads but denies a sensitive write. +- `SH-04.Q2` - Apply `RuntimeDefault` seccomp and diagnose a workload that requires a narrowly justified custom profile. +- `SH-04.Q3` - Compare Pod-level and container-level profile scope and prove enforcement with an attempted forbidden operation. +- `SH-04.Q4` - Hard capstone: harden a multi-container workload with different profiles and debug a node/profile-name mismatch. + +Hero-specific acceptance: must run on an AppArmor-enabled Linux host for AppArmor Hero; manifest-only evidence remains Training. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +--- + +## Minimize Microservice Vulnerabilities - 20% + +### MM-01 - Use appropriate Pod Security Standards + +Status: `[~] TRAINING` + +Tools: Pod Security Admission labels, PSS documentation, dry runs, admission output, workload security contexts. + +Prior evidence: Lessons 0005, 0021, 0031, 0033, and 0034. + +Question bank: + +- `MM-01.Q1` - Classify workloads against Privileged, Baseline, and Restricted, identifying every violating field. +- `MM-01.Q2` - Migrate a namespace through warn, audit, and enforce with pinned policy versions and no avoidable outage. +- `MM-01.Q3` - Remediate a Deployment to Restricted while preserving required writable paths and network binding. +- `MM-01.Q4` - Hard capstone: manage exemptions and mixed legacy workloads without weakening the entire namespace. + +Hero-specific acceptance: prove admitted compliant workloads and rejected noncompliant workloads at the correct scope. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### MM-02 - Manage Kubernetes Secrets + +Status: `[~] TRAINING` + +Tools: Secret API, projected volumes, encryption configuration, RBAC, `etcdctl`, rotation workflow. + +Prior evidence: Lessons 0010, 0018, and 0032 cover selective projection, encryption at rest, exposure investigation, and rotation reasoning. + +Question bank: + +- `MM-02.Q1` - Project only one Secret key into one container with correct file mode and no environment-variable exposure. +- `MM-02.Q2` - Configure encryption at rest, rewrite existing Secrets, and prove ciphertext in etcd plus readable API behavior. +- `MM-02.Q3` - Identify Secret exposure through RBAC, Pod specs, logs, shell history, and mounted tokens; remediate each path. +- `MM-02.Q4` - Hard capstone: rotate an accessed external credential across producers and consumers without retaining the old value. + +Hero-specific acceptance: minimize distribution, prove storage encryption, and demonstrate actual credential invalidation. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### MM-03 - Implement isolation and multi-tenancy + +Status: `[~] TRAINING` + +Tools: namespaces, RBAC, quotas, NetworkPolicy, Pod Security Admission, admission policy, RuntimeClass/sandboxed runtime. + +Prior evidence: Lessons 0017, 0031, and 0034 cover scoped admission and workload/network isolation. Sandboxed runtime evidence is missing. + +Question bank: + +- `MM-03.Q1` - Build a tenant namespace baseline combining RBAC, quotas, PSS, default-deny networking, and dedicated ServiceAccounts. +- `MM-03.Q2` - Prevent host namespace, privileged, hostPath, and unsafe capability use with correctly scoped admission logic. +- `MM-03.Q3` - Configure and select a sandboxed RuntimeClass, then verify the effective runtime handler. +- `MM-03.Q4` - Hard capstone: isolate two tenants while preserving one explicitly shared service and administrative break-glass path. + +Hero-specific acceptance: prove cross-tenant denials at API, network, storage, and runtime boundaries. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### MM-04 - Implement Pod-to-Pod encryption + +Status: `[~] TRAINING` + +Tools: Cilium CLI/status, WireGuard status, Istio `istioctl`, PeerAuthentication, AuthorizationPolicy, traffic capture where allowed. + +Prior evidence: Lessons 0023, 0025, and 0026 cover Cilium WireGuard, Istio strict mTLS, and workload authorization. + +Question bank: + +- `MM-04.Q1` - Enable Cilium WireGuard and prove node encryption status plus encrypted Pod traffic. +- `MM-04.Q2` - Enforce namespace-wide Istio STRICT mTLS and identify workloads that fail because they lack sidecars. +- `MM-04.Q3` - Pair mTLS with AuthorizationPolicy so encryption does not become mistaken for authorization. +- `MM-04.Q4` - Hard capstone: diagnose mixed plaintext/encrypted traffic across namespaces and prove the final data path. + +Hero-specific acceptance: use implementation-specific status tools and traffic evidence, not policy YAML alone. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +--- + +## Supply Chain Security - 20% + +### SC-01 - Minimize base image footprint + +Status: `[ ] NOT STARTED` + +Tools: Docker/BuildKit, multi-stage builds, distroless or minimal images, Trivy, Dive where available. + +Prior evidence: no dedicated image-rebuild and comparison task. + +Question bank: + +- `SC-01.Q1` - Convert a development image into a multi-stage production build with no compiler or package manager in the final stage. +- `SC-01.Q2` - Compare package count, size, users, shell availability, and vulnerability results before and after minimization. +- `SC-01.Q3` - Run the final image as non-root with a read-only root filesystem and explicit writable paths. +- `SC-01.Q4` - Hard capstone: minimize an image without breaking TLS roots, timezone data, health checks, or runtime dependencies. + +Hero-specific acceptance: quantitative before/after evidence plus successful runtime behavior is required. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### SC-02 - Understand the supply chain + +Status: `[~] TRAINING` + +Tools: Syft, CycloneDX/SPDX, CI logs, artifact repositories, provenance/attestations, dependency metadata. + +Prior evidence: Lesson 0030 generates and interprets a CycloneDX SBOM with Syft. + +Question bank: + +- `SC-02.Q1` - Generate CycloneDX and SPDX SBOMs with Syft and compare component identity and relationships. +- `SC-02.Q2` - Trace a deployed digest back through registry metadata, build job, source revision, and SBOM. +- `SC-02.Q3` - Use an SBOM to answer impact from a newly disclosed component vulnerability without claiming exploitability. +- `SC-02.Q4` - Hard capstone: investigate a mismatched SBOM, image digest, and deployment reference and identify the broken provenance link. + +Hero-specific acceptance: distinguish inventory, vulnerability, provenance, signature, and deployment policy evidence. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### SC-03 - Secure permitted registries and validate artifacts + +Status: `[~] TRAINING` + +Tools: Cosign, container registry, image digests, admission policy, public-key or keyless verification, attestations. + +Prior evidence: Lessons 0013 and 0019 cover digest enforcement and artifact checksum verification. Cosign signing and verification are missing. + +Question bank: + +- `SC-03.Q1` - Sign a pinned image digest with Cosign and verify it using the intended trust identity. +- `SC-03.Q2` - Enforce an allowed registry and immutable digest policy across regular, init, and ephemeral containers. +- `SC-03.Q3` - Validate an SBOM or provenance attestation and reject a signature from the wrong identity or repository. +- `SC-03.Q4` - Hard capstone: admit only correctly signed images from permitted registries while preserving an audited break-glass process. + +Hero-specific acceptance: verification must bind identity, repository, and digest; signature presence alone is insufficient. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### SC-04 - Perform static analysis of workloads and images + +Status: `[~] TRAINING` + +Tools: Kubesec, KubeLinter, Trivy config/image, scanner exit codes, CI integration. + +Prior evidence: Lesson 0027 uses Trivy configuration scanning. Kubesec, KubeLinter, and Trivy image scanning remain unpracticed. + +Question bank: + +- `SC-04.Q1` - Scan the same manifest with Kubesec, KubeLinter, and Trivy; normalize overlapping and tool-specific findings. +- `SC-04.Q2` - Scan a pinned image with Trivy, prioritize exploitable/runtime-relevant findings, and avoid equating count with risk. +- `SC-04.Q3` - Configure CI to fail on a justified severity/fixability policy while preserving machine-readable reports. +- `SC-04.Q4` - Hard capstone: remediate manifest and image findings, rerun every scanner, and explain accepted residual risk and false positives. + +Hero-specific acceptance: use at least three named tools, preserve raw reports, and distinguish configuration from package-vulnerability results. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +--- + +## Monitoring, Logging and Runtime Security - 20% + +### MR-01 - Perform behavioral analytics + +Status: `[~] TRAINING` + +Tools: Falco, rule files, JSON output, baseline comparison, process/network telemetry. + +Prior evidence: Lesson 0020 covers runtime shell detection with Falco-style evidence. + +Question bank: + +- `MR-01.Q1` - Establish a workload behavior baseline and identify process, file, and network deviations. +- `MR-01.Q2` - Write and test a Falco rule for an interactive shell or sensitive file access inside a container. +- `MR-01.Q3` - Tune a noisy rule using workload identity and syscall context without hiding real attacks. +- `MR-01.Q4` - Hard capstone: correlate multiple low-confidence events into one high-confidence malicious sequence. + +Hero-specific acceptance: provide triggering and non-triggering tests plus a justified noise-control strategy. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### MR-02 - Detect threats across infrastructure, apps, networks, data, users, and workloads + +Status: `[~] TRAINING` + +Tools: Falco, audit logs, host logs, NetworkPolicy/CNI flow logs, application logs, identity events, file-integrity evidence. + +Prior evidence: Lessons 0012, 0020, and 0032 cover API and runtime signals; full cross-layer correlation is missing. + +Question bank: + +- `MR-02.Q1` - Map one signal source and one high-value detection to each of the six threat surfaces. +- `MR-02.Q2` - Detect suspicious node login, privileged workload creation, lateral network movement, Secret access, and runtime execution. +- `MR-02.Q3` - Separate preventive controls from detective evidence and identify blind spots in each layer. +- `MR-02.Q4` - Hard capstone: correlate host, Kubernetes, network, and application telemetry into one defensible incident timeline. + +Hero-specific acceptance: identify principal, asset, action, outcome, source, and timestamp from more than one telemetry layer. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### MR-03 - Investigate phases of attack and bad actors + +Status: `[~] TRAINING` + +Tools: `jq`/PowerShell JSON parsing, audit logs, Falco events, Pod and RBAC inspection, timeline notes. + +Prior evidence: Lessons 0012 and 0032 reconstruct escalation, Secret access, and exec activity with ordered containment. + +Question bank: + +- `MR-03.Q1` - Reconstruct initial access, privilege escalation, discovery, credential access, execution, and persistence from mixed logs. +- `MR-03.Q2` - Distinguish rejected attempts from successful actions using response codes and runtime outcomes. +- `MR-03.Q3` - Pivot by authenticated principal, source IP, workload identity, resource, and time without using audit IDs as identities. +- `MR-03.Q4` - Hard capstone: produce a concise incident report with evidence, confidence, blast radius, and ordered containment. + +Hero-specific acceptance: include the exact structured query command and cite the event evidence for every conclusion. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### MR-04 - Ensure container immutability at runtime + +Status: `[~] TRAINING` + +Tools: securityContext, read-only root filesystem, volumes, image digests, admission policy, Falco/file-integrity checks. + +Prior evidence: Lessons 0006, 0013, 0033, and 0034 cover immutable images and read-only roots with explicit writable volumes. + +Question bank: + +- `MR-04.Q1` - Harden a workload with read-only roots and discover every required writable runtime path empirically. +- `MR-04.Q2` - Enforce digest-only image references and prove mutable-tag rejection. +- `MR-04.Q3` - Detect executable creation or package installation inside a running container and contain it. +- `MR-04.Q4` - Hard capstone: combine preventive admission, runtime filesystem controls, and behavioral detection without breaking the application. + +Hero-specific acceptance: prove immutable image identity, failed root writes, allowed explicit writes, and runtime alert behavior. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +### MR-05 - Use Kubernetes audit logs to monitor access + +Status: `[~] TRAINING` + +Tools: audit Policy, kube-apiserver flags and mounts, `jq`, log rotation, event correlation. + +Prior evidence: Lessons 0012, 0014, 0032, and 0035 cover policy design, persistent logging, filtering, and incident reconstruction. + +Question bank: + +- `MR-05.Q1` - Design an ordered audit policy for Secrets, RBAC changes, Pod exec, authentication failures, and a Metadata catch-all. +- `MR-05.Q2` - Configure file-backend persistence and rotation in a kube-apiserver static Pod and prove the effective process flags. +- `MR-05.Q3` - Write structured queries for principal, source, verb, resource, response code, and time windows. +- `MR-05.Q4` - Hard capstone: diagnose missing events caused by rule ordering, level choice, omitted stages, path mounts, or log rotation. + +Hero-specific acceptance: prove event generation end to end from API request through persisted log and structured query. + +Hero gate: [ ] Tool drill [ ] Timed capstone [ ] Evidence [ ] Cold retest + +--- + +## Attempt Log + +Append one row after every graded attempt. + +| Date | Task | Topic | Time | Result | Critical errors | Evidence | Next action | +|---|---|---|---:|---|---:|---|---| +| 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 | + +## Current Summary + +Hero topics: none yet. + +Training topics: CS-01, CS-02, CS-03, CS-04, CS-05, CH-01, CH-02, CH-03, SH-03, SH-04, MM-01, MM-02, MM-03, MM-04, SC-02, SC-03, SC-04, MR-01, MR-02, MR-03, MR-04, MR-05. + +Not started: CH-04, SH-01, SH-02, SC-01. + +Blocked: AppArmor runtime enforcement on the current Docker Desktop/WSL2 kernel. Use an AppArmor-enabled Linux host for the Hero attempt. diff --git a/NOTES.md b/NOTES.md index 8270cc3..fd944b3 100644 --- a/NOTES.md +++ b/NOTES.md @@ -3,3 +3,7 @@ - Learner goal: career advancement and deeper technical security skills. - Background: CKA, CKAD, and KodeKloud CKS training completed. - Priority: build confidence through timed retrieval and hands-on feedback, not rewatching broad course material. +- Learner prefers original performance-based tasks at public CKS curriculum level or harder, with multi-control requirements and strict verification, so the real exam feels comparatively easy. +- 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. +- Confidence priority: deliberately rotate through named CKS tools instead of relying mainly on hand-written YAML. diff --git a/lab/lesson-33-answer.yaml b/lab/lesson-33-answer.yaml new file mode 100644 index 0000000..1aefbdc --- /dev/null +++ b/lab/lesson-33-answer.yaml @@ -0,0 +1,50 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: context-lab +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: report-api + namespace: context-lab +spec: + replicas: 1 + selector: + matchLabels: + app: report-api + template: + metadata: + labels: + app: report-api + spec: + securityContext: + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + volumes: + - name: log-exporter-vol + emptyDir: {} + containers: + - name: api + image: nginxinc/nginx-unprivileged:1.27-alpine + ports: + - containerPort: 8080 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + - name: log-exporter + image: busybox:1.37 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + readOnlyRootFilesystem: true + command: ["sh", "-c", "while true; do date >> /var/cache/exporter/events.log; sleep 30; done"] + volumeMounts: + - name: log-exporter-vol + mountPath: /var/cache/exporter \ No newline at end of file diff --git a/lab/lesson-33-fixture.yaml b/lab/lesson-33-fixture.yaml new file mode 100644 index 0000000..d1b944c --- /dev/null +++ b/lab/lesson-33-fixture.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: context-lab +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: report-api + namespace: context-lab +spec: + replicas: 1 + selector: + matchLabels: + app: report-api + template: + metadata: + labels: + app: report-api + spec: + containers: + - name: api + image: nginxinc/nginx-unprivileged:1.27-alpine + ports: + - containerPort: 8080 + - name: log-exporter + image: busybox:1.37 + command: ["sh", "-c", "while true; do date >> /var/cache/exporter/events.log; sleep 30; done"] diff --git a/lab/lesson-34-answer.yaml b/lab/lesson-34-answer.yaml new file mode 100644 index 0000000..3753dec --- /dev/null +++ b/lab/lesson-34-answer.yaml @@ -0,0 +1,106 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: orders-api + namespace: orders-prod +spec: + replicas: 2 + selector: + matchLabels: + app: orders-api + template: + metadata: + labels: + app: orders-api + tier: backend + spec: + automountServiceAccountToken: false + serviceAccountName: orders-api + securityContext: + runAsNonRoot: true + runAsUser: 10001 + runAsGroup: 10001 + fsGroup: 10001 + seccompProfile: + type: RuntimeDefault + volumes: + - name: orders + emptyDir: {} + - name: srv + emptyDir: {} + containers: + - name: api + image: busybox:1.37 + volumeMounts: + - name: orders + mountPath: /var/log/orders + - name: srv + mountPath: /srv + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + command: ["sh", "-c", "mkdir -p /srv; echo ready > /srv/index.html; httpd -f -p 8080 -h /srv"] + ports: + - name: http + containerPort: 8080 + - name: audit-writer + image: busybox:1.37 + command: ["sh", "-c", "while true; do date >> /var/log/orders/audit.log; sleep 20; done"] + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + volumeMounts: + - name: orders + mountPath: /var/log/orders +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: orders-api-boundary + namespace: orders-prod +spec: + podSelector: + matchLabels: + app: orders-api + policyTypes: + - Ingress + - Egress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: edge + podSelector: + matchLabels: + app: edge-gateway + ports: + - protocol: TCP + port: 8080 + egress: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: data + podSelector: + matchLabels: + app: orders-db + ports: + - protocol: TCP + port: 5432 + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + podSelector: + matchLabels: + k8s-app: kube-dns + ports: + - protocol: TCP + port: 53 + - protocol: UDP + port: 53 diff --git a/lab/lesson-34-fixture.yaml b/lab/lesson-34-fixture.yaml new file mode 100644 index 0000000..fd720b8 --- /dev/null +++ b/lab/lesson-34-fixture.yaml @@ -0,0 +1,82 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: orders-prod +--- +apiVersion: v1 +kind: Namespace +metadata: + name: edge +--- +apiVersion: v1 +kind: Namespace +metadata: + name: data +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: orders-api + namespace: orders-prod +spec: + replicas: 2 + selector: + matchLabels: + app: orders-api + template: + metadata: + labels: + app: orders-api + tier: backend + spec: + serviceAccountName: orders-api + containers: + - name: api + image: busybox:1.37 + command: ["sh", "-c", "mkdir -p /srv; echo ready > /srv/index.html; httpd -f -p 8080 -h /srv"] + ports: + - name: http + containerPort: 8080 + - name: audit-writer + image: busybox:1.37 + command: ["sh", "-c", "while true; do date >> /var/log/orders/audit.log; sleep 20; done"] +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: edge-gateway + namespace: edge +spec: + replicas: 1 + selector: + matchLabels: + app: edge-gateway + template: + metadata: + labels: + app: edge-gateway + spec: + containers: + - name: gateway + image: busybox:1.37 + command: ["sleep", "1d"] +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: orders-db + namespace: data +spec: + replicas: 1 + selector: + matchLabels: + app: orders-db + template: + metadata: + labels: + app: orders-db + spec: + containers: + - name: database + image: busybox:1.37 + command: ["sleep", "1d"] diff --git a/lab/lesson-35-audit-policy.yaml b/lab/lesson-35-audit-policy.yaml new file mode 100644 index 0000000..5f5782c --- /dev/null +++ b/lab/lesson-35-audit-policy.yaml @@ -0,0 +1,26 @@ +apiVersion: audit.k8s.io/v1 # This is required. +kind: Policy +omitStages: + - "RequestReceived" +rules: + - level: RequestResponse + namespaces: ["payments","orders-prod"] + resources: + - group: "" + resources: ["secrets"] + + + - level: Metadata + verbs: ["create","update","patch","delete","deletecollection"] + resources: + - group: "rbac.authorization.k8s.io" + resources: ["roles","rolebindings","clusterroles","clusterrolebindings"] + + - level: Request + resources: + - group: "" + resources: ["pods/exec"] + + - level: Metadata + omitStages: + - "RequestReceived" \ No newline at end of file diff --git a/lab/lesson-35-kube-apiserver-answer.yaml b/lab/lesson-35-kube-apiserver-answer.yaml new file mode 100644 index 0000000..e8b9cd9 --- /dev/null +++ b/lab/lesson-35-kube-apiserver-answer.yaml @@ -0,0 +1,57 @@ +apiVersion: v1 +kind: Pod +metadata: + name: kube-apiserver + namespace: kube-system + labels: + component: kube-apiserver + tier: control-plane +spec: + hostNetwork: true + priorityClassName: system-node-critical + containers: + - name: kube-apiserver + image: registry.k8s.io/kube-apiserver:v1.34.1 + command: + - kube-apiserver + - --anonymous-auth=false + - --authorization-mode=Node,RBAC + - --profiling=false + - --service-account-lookup=true + - --enable-admission-plugins=NamespaceLifecycle,ServiceAccount,NodeRestriction + - --audit-policy-file=/etc/kubernetes/audit-policy.yaml + - --audit-log-path=/var/log/kubernetes/audit/audit.log + - --audit-log-maxage=14 + - --audit-log-maxbackup=10 + - --audit-log-maxsize=100 + - --etcd-servers=https://127.0.0.1:2379 + - --service-cluster-ip-range=10.96.0.0/12 + - --client-ca-file=/etc/kubernetes/pki/ca.crt + - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt + - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key + - --service-account-issuer=https://kubernetes.default.svc.cluster.local + - --service-account-key-file=/etc/kubernetes/pki/sa.pub + - --service-account-signing-key-file=/etc/kubernetes/pki/sa.key + - --allow-privileged=true + volumeMounts: + - name: k8s-certs + mountPath: /etc/kubernetes/pki + readOnly: true + - name: audit-config + mountPath: /etc/kubernetes/audit-policy.yaml + readOnly: true + - name: audit-log + mountPath: /var/log/kubernetes/audit + volumes: + - name: k8s-certs + hostPath: + path: /etc/kubernetes/pki + type: DirectoryOrCreate + - name: audit-config + hostPath: + path: /etc/kubernetes/audit-policy.yaml + type: File + - name: audit-log + hostPath: + path: /var/log/kubernetes/audit + type: DirectoryOrCreate \ No newline at end of file diff --git a/lab/lesson-35-kube-apiserver-insecure.yaml b/lab/lesson-35-kube-apiserver-insecure.yaml new file mode 100644 index 0000000..4c07e85 --- /dev/null +++ b/lab/lesson-35-kube-apiserver-insecure.yaml @@ -0,0 +1,40 @@ +apiVersion: v1 +kind: Pod +metadata: + name: kube-apiserver + namespace: kube-system + labels: + component: kube-apiserver + tier: control-plane +spec: + hostNetwork: true + priorityClassName: system-node-critical + containers: + - name: kube-apiserver + image: registry.k8s.io/kube-apiserver:v1.34.1 + command: + - kube-apiserver + - --anonymous-auth=true + - --authorization-mode=AlwaysAllow + - --profiling=true + - --service-account-lookup=false + - --enable-admission-plugins=NamespaceLifecycle,ServiceAccount + - --audit-log-path=- + - --etcd-servers=https://127.0.0.1:2379 + - --service-cluster-ip-range=10.96.0.0/12 + - --client-ca-file=/etc/kubernetes/pki/ca.crt + - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt + - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key + - --service-account-issuer=https://kubernetes.default.svc.cluster.local + - --service-account-key-file=/etc/kubernetes/pki/sa.pub + - --service-account-signing-key-file=/etc/kubernetes/pki/sa.key + - --allow-privileged=true + volumeMounts: + - name: k8s-certs + mountPath: /etc/kubernetes/pki + readOnly: true + volumes: + - name: k8s-certs + hostPath: + path: /etc/kubernetes/pki + type: DirectoryOrCreate diff --git a/lab/lesson-36-coredns.yaml b/lab/lesson-36-coredns.yaml new file mode 100644 index 0000000..f8ab7d4 --- /dev/null +++ b/lab/lesson-36-coredns.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: coredns + namespace: kube-system +spec: + replicas: 2 + selector: + matchLabels: + k8s-app: kube-dns + template: + metadata: + labels: + k8s-app: kube-dns + spec: + serviceAccountName: coredns + automountServiceAccountToken: true + containers: + - name: coredns + image: registry.k8s.io/coredns/coredns:v1.12.1 + args: ["-conf", "/etc/coredns/Corefile"] + securityContext: + runAsUser: 0 + allowPrivilegeEscalation: true + readOnlyRootFilesystem: false + ports: + - name: dns + containerPort: 53 + protocol: UDP + - name: dns-tcp + containerPort: 53 + protocol: TCP diff --git a/lab/lesson-36-etcd.yaml b/lab/lesson-36-etcd.yaml new file mode 100644 index 0000000..b5b7ad7 --- /dev/null +++ b/lab/lesson-36-etcd.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Pod +metadata: + name: etcd + namespace: kube-system +spec: + hostNetwork: true + containers: + - name: etcd + image: registry.k8s.io/etcd:3.6.4-0 + command: + - etcd + - --listen-client-urls=https://127.0.0.1:2379,https://10.0.0.10:2379 + - --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=true + - --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 + volumeMounts: + - name: etcd-certs + mountPath: /etc/kubernetes/pki/etcd + readOnly: true + volumes: + - name: etcd-certs + hostPath: + path: /etc/kubernetes/pki/etcd + type: DirectoryOrCreate diff --git a/lab/lesson-36-kube-bench.json b/lab/lesson-36-kube-bench.json new file mode 100644 index 0000000..c3a9e8e --- /dev/null +++ b/lab/lesson-36-kube-bench.json @@ -0,0 +1,202 @@ +{ + "Controls": [ + { + "id": "1", + "version": "cis-1.11", + "detected_version": "v1.34.1", + "text": "Control Plane Security Configuration", + "node_type": "master", + "tests": [ + { + "section": "1.2", + "type": "controlplane", + "pass": 1, + "fail": 2, + "warn": 1, + "info": 0, + "desc": "API Server", + "results": [ + { + "test_number": "1.2.1", + "test_desc": "Ensure that the --anonymous-auth argument is set to false (Automated)", + "audit": "Inspect the kube-apiserver process arguments", + "type": "Automated", + "remediation": "Set --anonymous-auth=false in the kube-apiserver static Pod manifest.", + "test_info": [], + "status": "FAIL", + "actual_value": "--anonymous-auth=true", + "scored": true, + "expected_result": "false" + }, + { + "test_number": "1.2.7", + "test_desc": "Ensure that the --authorization-mode argument includes Node and RBAC (Automated)", + "audit": "Inspect the kube-apiserver process arguments", + "type": "Automated", + "remediation": "Set --authorization-mode=Node,RBAC.", + "test_info": [], + "status": "FAIL", + "actual_value": "--authorization-mode=AlwaysAllow", + "scored": true, + "expected_result": "Node,RBAC" + }, + { + "test_number": "1.2.21", + "test_desc": "Ensure that the --service-account-lookup argument is set to true (Automated)", + "audit": "Inspect the kube-apiserver process arguments", + "type": "Automated", + "remediation": "Set --service-account-lookup=true.", + "test_info": [], + "status": "PASS", + "actual_value": "--service-account-lookup=true", + "scored": true, + "expected_result": "true" + }, + { + "test_number": "1.2.22", + "test_desc": "Ensure that the audit log path is configured (Manual)", + "audit": "Review the audit backend path and persistence mounts", + "type": "Manual", + "remediation": "Configure a persistent audit log file and verify its host mount.", + "test_info": ["A non-empty flag alone does not prove persistence."], + "status": "WARN", + "actual_value": "--audit-log-path=-", + "scored": false, + "expected_result": "persistent file path" + } + ] + } + ] + }, + { + "id": "2", + "version": "cis-1.11", + "detected_version": "v1.34.1", + "text": "etcd Node Configuration", + "node_type": "etcd", + "tests": [ + { + "section": "2", + "type": "etcd", + "pass": 1, + "fail": 2, + "warn": 0, + "info": 0, + "desc": "etcd", + "results": [ + { + "test_number": "2.2", + "test_desc": "Ensure that the --client-cert-auth argument is set to true (Automated)", + "audit": "Inspect the etcd process arguments", + "type": "Automated", + "remediation": "Set --client-cert-auth=true and configure --trusted-ca-file.", + "test_info": [], + "status": "FAIL", + "actual_value": "--client-cert-auth=false", + "scored": true, + "expected_result": "true" + }, + { + "test_number": "2.3", + "test_desc": "Ensure that the --auto-tls argument is not set to true (Automated)", + "audit": "Inspect the etcd process arguments", + "type": "Automated", + "remediation": "Set --auto-tls=false and use trusted certificate files.", + "test_info": [], + "status": "FAIL", + "actual_value": "--auto-tls=true", + "scored": true, + "expected_result": "false" + }, + { + "test_number": "2.4", + "test_desc": "Ensure that the --peer-client-cert-auth argument is set to true (Automated)", + "audit": "Inspect the etcd process arguments", + "type": "Automated", + "remediation": "Set --peer-client-cert-auth=true.", + "test_info": [], + "status": "PASS", + "actual_value": "--peer-client-cert-auth=true", + "scored": true, + "expected_result": "true" + } + ] + } + ] + }, + { + "id": "4", + "version": "cis-1.11", + "detected_version": "v1.34.1", + "text": "Worker Node Security Configuration", + "node_type": "node", + "tests": [ + { + "section": "4.2", + "type": "node", + "pass": 1, + "fail": 3, + "warn": 0, + "info": 0, + "desc": "Kubelet", + "results": [ + { + "test_number": "4.2.1", + "test_desc": "Ensure that anonymous authentication is disabled (Automated)", + "audit": "Inspect KubeletConfiguration authentication.anonymous.enabled", + "type": "Automated", + "remediation": "Set authentication.anonymous.enabled=false.", + "test_info": [], + "status": "FAIL", + "actual_value": "enabled: true", + "scored": true, + "expected_result": "false" + }, + { + "test_number": "4.2.2", + "test_desc": "Ensure that webhook authentication is enabled (Automated)", + "audit": "Inspect KubeletConfiguration authentication.webhook.enabled", + "type": "Automated", + "remediation": "Set authentication.webhook.enabled=true.", + "test_info": [], + "status": "FAIL", + "actual_value": "enabled: false", + "scored": true, + "expected_result": "true" + }, + { + "test_number": "4.2.3", + "test_desc": "Ensure that the authorization mode is Webhook (Automated)", + "audit": "Inspect KubeletConfiguration authorization.mode", + "type": "Automated", + "remediation": "Set authorization.mode=Webhook.", + "test_info": [], + "status": "FAIL", + "actual_value": "mode: AlwaysAllow", + "scored": true, + "expected_result": "Webhook" + }, + { + "test_number": "4.2.4", + "test_desc": "Ensure that the read-only port is disabled (Automated)", + "audit": "Inspect KubeletConfiguration readOnlyPort", + "type": "Automated", + "remediation": "Set readOnlyPort=0.", + "test_info": [], + "status": "PASS", + "actual_value": "readOnlyPort: 0", + "scored": true, + "expected_result": "0" + } + ] + } + ] + } + ], + "Totals": { + "total_pass": 3, + "total_fail": 7, + "total_warn": 1, + "total_info": 0 + } +} diff --git a/learning-records/0006-audit-impact-and-containment-order.md b/learning-records/0006-audit-impact-and-containment-order.md new file mode 100644 index 0000000..677697b --- /dev/null +++ b/learning-records/0006-audit-impact-and-containment-order.md @@ -0,0 +1,11 @@ +# Audit impact and containment order + +The learner completed the substantive reasoning in Lesson 32. They distinguished a rejected RBAC attempt from a successful RoleBinding creation by checking `responseStatus.code`, identified the authenticated ServiceAccount principal, traced Secret access and Pod exec, and ordered containment as RBAC revocation, workload isolation, then credential rotation. + +## Evidence + +The incident note correctly identifies `system:serviceaccount:checkout:release-bot`, RoleBinding `checkout/release-bot-secret-reader`, Secret `checkout/payment-gateway`, and the exec target `checkout/checkout-api-6d8f`. + +## Remaining evidence gap + +The answer does not include the exact structured JSON filter command requested by the lesson. Continue requiring commands or output when a task asks for reproducible investigation evidence. diff --git a/learning-records/0007-security-context-placement.md b/learning-records/0007-security-context-placement.md new file mode 100644 index 0000000..3af9e4c --- /dev/null +++ b/learning-records/0007-security-context-placement.md @@ -0,0 +1,11 @@ +# SecurityContext placement retrieval + +The learner completed Lesson 33 and explicitly preferred its manifest-hardening format. The final static manifest correctly separates Pod-wide identity and seccomp settings from container-level privilege escalation, capabilities, and read-only-root controls. It also confines the sidecar's writable state to an `emptyDir` mount. + +## Coaching adjustment + +Increase subsequent work to original, timed, multi-control tasks aligned with the public CKS curriculum or harder. Preserve exam-style brevity, require verification evidence, and continue listing all issues while correcting one per review round. + +## Evidence limitation + +The manifest passed static review. Runtime rollout and filesystem verification were not observed in the teaching shell. diff --git a/learning-records/0008-multicontrol-workload-and-network-boundary.md b/learning-records/0008-multicontrol-workload-and-network-boundary.md new file mode 100644 index 0000000..9b6b2dd --- /dev/null +++ b/learning-records/0008-multicontrol-workload-and-network-boundary.md @@ -0,0 +1,15 @@ +# Multi-control workload and network boundary + +The learner completed Lesson 34, an original hard-mode task combining a hardened two-container Deployment with one bidirectional NetworkPolicy. The final static manifest correctly preserves workload fields, disables automatic token mounting, applies Pod- and container-level security controls, provides only deliberate writable paths, and composes namespace and Pod selectors in the same NetworkPolicy peer. + +## Evidence + +The final NetworkPolicy isolates ingress and egress, permits only the edge gateway, database, and CoreDNS flows, and includes TCP and UDP DNS. The learner corrected schema placement and exact resource naming during review. + +## Evidence limitation + +Elapsed time was not recorded. Runtime rollout and connectivity checks were not observed in the teaching shell. + +## Coaching adjustment + +Continue with original multi-file, node-level, and multi-domain tasks at public CKS curriculum difficulty or harder. Require the learner to preserve unrelated operational configuration while correcting security weaknesses. diff --git a/learning-records/0009-hero-based-cks-mastery-system.md b/learning-records/0009-hero-based-cks-mastery-system.md new file mode 100644 index 0000000..e5e2fd9 --- /dev/null +++ b/learning-records/0009-hero-based-cks-mastery-system.md @@ -0,0 +1,11 @@ +# Hero-based CKS mastery system + +The learner requested an exhaustive, persistent checklist for every public CKS syllabus topic, with several tool-based questions per topic and visible done-versus-remaining status. The canonical state is stored in `CKS-MASTERY-CHECKLIST.md` so a different computer or agent can resume from repository files. + +## Hero standard + +A topic receives Hero only after the learner completes its tool drill, a timed original capstone at exam difficulty or harder, supplies verification evidence, and passes a cold retest on a later session without stepwise prompting. Existing lessons count as training evidence but do not grant Hero retroactively. + +## Coaching behavior + +At the start and end of each future CKS session, update the checklist dashboard, topic evidence, attempt log, next task, and done-versus-remaining summary. Prefer tools that have not yet been exercised enough, including kube-bench, kubeadm, Kubesec, KubeLinter, Trivy image scanning, Syft, Cosign, Falco, AppArmor tooling, and host-network inspection tools. diff --git a/lessons/0033-security-context-placement.html b/lessons/0033-security-context-placement.html new file mode 100644 index 0000000..597f502 --- /dev/null +++ b/lessons/0033-security-context-placement.html @@ -0,0 +1,60 @@ + + + + + + Lesson 33: SecurityContext placement + + + +
+

Lesson 0033 · 25 minutes · Minimize Microservice Vulnerabilities

+

Place hardening controls at the correct scope

+

A correct control at the wrong YAML level is still an invalid solution. Harden both containers while preserving the sidecar's one required writable path.

+ +

Timed task: 15 minutes

+

Read lab/lesson-33-fixture.yaml. Create lab/lesson-33-answer.yaml from scratch. Preserve the namespace, Deployment name, replica count, selector, labels, container names, images, commands, and port.

+

Your completed Deployment must:

+ +

Do not duplicate Pod-wide fields under each container, mount the writable volume into api, add capabilities, or change either image.

+ +
Placement reflex: identity and Pod-wide syscall policy belong under template.spec.securityContext. Privilege escalation, capabilities, and root-filesystem mutability belong under each entry in template.spec.containers.
+ +

Verification

+
kubectl apply --dry-run=client -f .\lab\lesson-33-answer.yaml
+kubectl apply -f .\lab\lesson-33-answer.yaml
+kubectl -n context-lab rollout status deployment/report-api --timeout=90s
+kubectl -n context-lab exec deploy/report-api -c log-exporter -- test -f /var/cache/exporter/events.log
+kubectl -n context-lab exec deploy/report-api -c api -- sh -c 'touch /root/blocked'
+

Expected: schema validation passes, the rollout completes, the sidecar writes its event file, and the API container cannot write to its root filesystem.

+ +

Retrieval check

+
+

Question

+

Where does readOnlyRootFilesystem belong?

+ + + + + +
+ +

Documentation target

+

Use the official Kubernetes security context documentation after your first attempt. Use kubectl explain deployment.spec.template.spec.securityContext and kubectl explain deployment.spec.template.spec.containers.securityContext to confirm scope.

+ +

What to send me

+

Save the YAML, then say check. I will list all issues and help you correct only one per round. Ask me a follow-up question whenever a field's scope is unclear.

+ +
+ + + diff --git a/lessons/0034-harden-and-isolate-orders-api.html b/lessons/0034-harden-and-isolate-orders-api.html new file mode 100644 index 0000000..78be717 --- /dev/null +++ b/lessons/0034-harden-and-isolate-orders-api.html @@ -0,0 +1,70 @@ + + + + + + Lesson 34: Harden and isolate orders-api + + + +
+

Lesson 0034 · 35 minutes · Hard mode · Multi-domain

+

Harden and isolate a production API

+

This original performance task is deliberately denser than a focused drill. Secure the workload and its traffic boundary without changing its application contract.

+ +

Task

+

Apply lab/lesson-34-fixture.yaml. Create lab/lesson-34-answer.yaml containing exactly two resources: the corrected orders-api Deployment and one NetworkPolicy named orders-api-boundary.

+

Preserve the Deployment's name, namespace, replicas, selector, labels, ServiceAccount name, container names, images, commands, and port.

+ +

Workload requirements

+ + +

Network requirements

+

The single NetworkPolicy must select only app=orders-api, isolate both ingress and egress, and allow only:

+ +

Use the immutable namespace label kubernetes.io/metadata.name. Do not use ipBlock, empty peer selectors, additional policies, or wildcard ports.

+ +
Hard-mode traps: a Namespace selector and Pod selector must be in the same peer item to mean AND. Separate list items mean OR. NetworkPolicies are additive, DNS needs both protocols, and a read-only root filesystem needs every required writable path mounted explicitly.
+ +

Verification

+
kubectl apply --dry-run=client -f .\lab\lesson-34-answer.yaml
+kubectl apply -f .\lab\lesson-34-answer.yaml
+kubectl -n orders-prod rollout status deployment/orders-api --timeout=90s
+kubectl -n orders-prod get deployment orders-api -o jsonpath='{.spec.template.spec.automountServiceAccountToken}{"\n"}'
+kubectl -n orders-prod exec deploy/orders-api -c api -- sh -c 'test -f /srv/index.html && touch /var/log/orders/api.log'
+kubectl -n orders-prod exec deploy/orders-api -c audit-writer -- test -f /var/log/orders/audit.log
+ +

Retrieval check

+
+

Question

+

How do you require both a namespace label and a Pod label for one NetworkPolicy peer?

+ + + + + +
+ +

Documentation targets

+

After your first attempt, use the official Kubernetes Security Context and NetworkPolicy documentation.

+ +

What to send me

+

Save the two-resource answer and record your elapsed time. Then say check. I will list all issues and correct one per round. Ask a follow-up question whenever a requirement is ambiguous.

+ +
+ + + diff --git a/lessons/0035-apiserver-audit-hard-mode.html b/lessons/0035-apiserver-audit-hard-mode.html new file mode 100644 index 0000000..e146424 --- /dev/null +++ b/lessons/0035-apiserver-audit-hard-mode.html @@ -0,0 +1,80 @@ + + + + + + Lesson 35: API server and audit hard mode + + + +
+

Lesson 0035 · 45 minutes · Hard mode · Control plane

+

Harden the API server and preserve forensic evidence

+

Repair an insecure static Pod and connect it to an ordered audit policy. Treat this as a control-plane maintenance task: preserve required configuration, make paths persistent, and avoid using kubectl apply.

+ +

Task

+

Read lab/lesson-35-kube-apiserver-insecure.yaml. Create both:

+ +

Preserve every metadata field, Pod field, container field, image, PKI mount, and command flag unless a requirement below explicitly changes it.

+ +

API-server requirements

+ + +

Audit-policy requirements

+

Use audit.k8s.io/v1, kind Policy, globally omit RequestReceived, and order rules so the first match produces:

+ +

Do not add a None rule, omit any existing required flag, use a relative path, mount the audit log directory read-only, or apply the static manifest to the API server.

+ +
Hard-mode traps: audit rules are first-match wins; RBAC resources use group rbac.authorization.k8s.io; exec is resource pods with subresource exec, represented as pods/exec; and API-server file paths are useless unless the static Pod mounts their host locations.
+ +

Verification

+
# These are configuration files, not objects to apply.
+grep -E -- '--anonymous-auth|--authorization-mode|--profiling|--service-account-lookup|--enable-admission-plugins|--audit-' lab/lesson-35-kube-apiserver-answer.yaml
+
+# Confirm the two mount paths appear in commands, mounts, and hostPath volumes.
+grep -nE '/etc/kubernetes/audit-policy.yaml|/var/log/kubernetes/audit' lab/lesson-35-kube-apiserver-answer.yaml
+
+# Inspect rule order and spelling.
+cat lab/lesson-35-audit-policy.yaml
+ +

Retrieval check

+
+

Question

+

Why must the Secret rule appear before the catch-all Metadata rule?

+ + + + + +
+ +

Documentation targets

+

After your first attempt, use the official Kubernetes kube-apiserver flag reference and auditing documentation.

+ +

What to send me

+

Save both files and say check. I will list all detected issues and correct one per round. Ask a follow-up question whenever a flag, mount, or audit-rule match is unclear.

+ +
+ + + diff --git a/lessons/0036-kube-bench-cis-triage.html b/lessons/0036-kube-bench-cis-triage.html new file mode 100644 index 0000000..7b8a5f9 --- /dev/null +++ b/lessons/0036-kube-bench-cis-triage.html @@ -0,0 +1,73 @@ + + + + + + Lesson 36: kube-bench CIS triage + + + +
+

Lesson 0036 · 35 minutes · Tool drill · Cluster Setup

+

Triage kube-bench findings without obeying the scanner blindly

+

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.

+ +

Environment note

+

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.

+ +

Task: 25 minutes

+

Analyze these files without modifying them:

+ +

Create lab/lesson-36-answer.md containing:

+
    +
  1. The exact PowerShell command used to extract every non-PASS result from the JSON.
  2. +
  3. A table for all seven FAIL results and the one WARN result: check ID, component, status, scanner evidence, configuration evidence, verdict, and precise remediation.
  4. +
  5. Your first three remediations in operational priority order, with one sentence of justification each.
  6. +
  7. At least four security findings from the CoreDNS Deployment that kube-bench did not report.
  8. +
  9. One paragraph explaining why WARN does not mean FAIL, why PASS is not universal proof, and why CoreDNS requires manual review here.
  10. +
  11. 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.
  12. +
+ +
Tool reflex: 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 actual_value and reason with effective configuration before changing a node.
+ +

PowerShell starting shape

+
$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
+ +

Linux Hero rerun shape

+
# 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
+

You must determine and record the complete pinned installation and checksum-verification commands yourself.

+ +

Retrieval check

+
+

Question

+

kube-bench reports WARN for a manual check. What should you do?

+ + + + + +
+ +

Documentation targets

+

Use the official kube-bench repository, its installation guide, and the applicable CIS benchmark guidance after your first analysis.

+ +

What to send me

+

Save the Markdown answer and say check. 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.

+ +
+ + +