Files
ced4568andClaude Sonnet 5 7f6e1857c0 feat(curriculum): Phase 6C module upgrades, security assessment bank, ROOT 11 orientation
Upgrades six PARTIAL modules to the gold-module standard (lesson/demonstration/
knowledge-check/guided-exercise/lab(s)/reflection), preserving every existing lab
activity_id and scenario_id: root-06-m03 (jobs/cronjobs/daemonsets), root-07-m04
(ingress/networkpolicy), root-07-m02 (configuration/secrets, converted in place
from a bare 5-lab bank), root-09-m02 (serviceaccounts/rbac), root-09-m03
(network/supply-chain security), root-10-m03 (troubleshooting framework).

root-05-m01 (20-task kubectl-fluency bank) gets a minimal bookending lesson +
reflection rather than a full redesign, since each task already carries its own
explanation. root-12-m01, root-capstone-m01, and root-09-m04 are promoted to
READY via documented exceptions (no new activities) where adding one would
misrepresent their intentional design.

Wires a new rootnode-security-assessment (exam, 60min, hint_policy disabled)
using the existing Phase 3B assessment engine: 3 required hands-on CORE
scenarios + 4 random-draw pools covering SecurityContext, RBAC, network
policy, and the 7 previously-unwired CKS MCQs. Wires the previously-unwired
readiness-probe-task scenario as an OPTIONAL practice lab in root-10-m01,
using the existing is_required model.

Adds root-11-m01-devops-platform-thinking — an honest, lesson-only ROOT 11
orientation module naming DevOps/platform engineering practices already
exercised in ROOT 05-10/12, explicit that GitOps/CI-CD/IaC/observability need
lab infrastructure this platform doesn't yet provide. No fake labs.

Adds infra/scripts/validate-course-content.js: cross-checks the DB against
scenario/content files for duplicate ids, orphans, invalid references, cycles,
sequence collisions, instructor-notes leakage, and (new) self-paced content
deferring explanation to a live instructor. 0 errors against the resulting
22 courses/modules, 163 activities, 98 scenario files.

No application code changed — every gap was satisfiable with existing tables
(course_modules, module_activities, assessment_definitions) and the existing
content-delivery pipeline.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 11:20:17 -05:00

46 lines
2.4 KiB
Markdown

# Guided Exercise: Writing a Least-Privilege Role
Paper-and-thinking exercise before the Labs.
## The scenario
A monitoring agent needs to run inside your cluster. Its ONLY job is to periodically list Pods
and read their status, across the whole cluster, to report health metrics elsewhere. It never
needs to create, modify, or delete anything, and it never needs to touch Secrets, ConfigMaps, or
any object type other than Pods.
## Your task
1. Should this use a Role or a ClusterRole? Justify your answer based on scope.
2. Which verbs does it actually need? Which common verbs (create, update, delete, patch) should
be deliberately left OUT?
3. Does it need access to Secrets? Why is it tempting to grant broader access "just in case,"
and why should you resist that?
4. What would you check, using `kubectl auth can-i`, to CONFIRM your Role is exactly as narrow
as intended before deploying it?
## A worked answer to check yourself against
1. **ClusterRole** (bound via a ClusterRoleBinding) — it needs to see Pods across the WHOLE
cluster, not just one namespace, so a namespace-scoped Role can't satisfy the requirement.
2. **`get`, `list`, `watch`** on `pods` — read-only verbs only. Deliberately exclude `create`,
`update`, `patch`, `delete` — this workload never legitimately needs to change anything.
3. No — it never touches Secrets, so it should get zero permission on them. The temptation to
"just in case" grant broader access is exactly what least privilege exists to resist: every
unused permission is pure risk with no corresponding benefit if this workload is ever
compromised.
4. Run `kubectl auth can-i delete pods --as=<the ServiceAccount>` and confirm it returns `no` —
and similarly check a Secrets verb returns `no` — proving the Role is bounded, not just
assuming it from reading the YAML.
## Instructor Notes
**Facilitation:** Question 3 is the core judgment call this exercise is testing — push on WHY
"just in case" access is a real anti-pattern, not just point out that it is one.
**Approximate timing:** 10-12 minutes live with discussion; 10 minutes self-paced.
**Optional extension:** ask what would change about the answer if this monitoring agent later
needed to also restart crash-looping Pods automatically — a good check that students can reason
about incrementally expanding a Role's scope only as far as a genuinely new requirement demands.