Files
rootnode-academy/content/root/root-09-kubernetes-security/m01-security-model-and-securitycontext/01-lesson-security-model.md
T
ced4568andClaude Sonnet 5 960a638ec9 feat(root): add Kubernetes security curriculum
Four new modules, moving ROOT 09 off PLANNED and building the
22-scenario CKS-style bank into a coherent course instead of
disconnected exam tasks — see docs/ROOT_CURRICULUM_COVERAGE_MATRIX.md
for the CORE/GUIDED/INDEPENDENT/ADVANCED/ASSESSMENT-BANK classification
behind every placement.

root-09-m01-security-model-and-securitycontext — READY, full
gold-standard pattern: defense in depth, least privilege, hardening a
Pod with SecurityContext. Lesson, demonstration (a Pod before/after
hardening), knowledge check, guided exercise (a hardening checklist),
real Labs (CORE: non-root/drop-capabilities/read-only-fs/
pod-security-context; GUIDED: seccomp; ADVANCED: AppArmor; INDEPENDENT:
the generic pod-security-context duplicate), and a reflection.

root-09-m02-serviceaccounts-and-rbac — PARTIAL: workload identity and
least-privilege permissions. Lesson + knowledge check + real Labs.

root-09-m03-network-and-supplychain-security — PARTIAL: NetworkPolicy
as a security control (default-deny), image/registry trust, TLS
ingress. Lesson + knowledge check + real Labs.

root-09-m04-cluster-hardening-and-runtime — PARTIAL, deliberately
survey-depth: Pod Security Admission and a lighter treatment of
audit-policy/runtime-sandboxing topics that don't belong in the core
daily-driver path.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:07:07 -05:00

4.6 KiB

Defense in Depth & the Kubernetes Security Model

Security is a posture, not a single setting

There is no single "make it secure" switch in Kubernetes. Real security comes from defense in depth — multiple independent layers, each reducing what an attacker (or a bug) can do if an earlier layer fails. If a container has a vulnerability that lets an attacker execute arbitrary code, the question that actually matters is: what can that code DO once it's running? A container running as root, with every Linux capability, on a writable filesystem, with no restrictions at all, can do far more damage than one deliberately hardened to need almost nothing.

Least privilege: grant only what's actually needed

The organizing principle behind everything in this course is least privilege: a workload should have exactly the permissions and capabilities it needs to do its job, and nothing more. This sounds obvious stated plainly, but the DEFAULT behavior of a plain container is closer to "maximum privilege unless told otherwise" — root user, all standard Linux capabilities, a writable filesystem. Hardening a Pod means deliberately narrowing that down.

SecurityContext: where you actually configure this

securityContext (settable at the Pod level and per-container) is where you declare these restrictions:

spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
  containers:
  - name: app
    securityContext:
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
  • runAsNonRoot / runAsUser — the container process runs as a specific non-root user instead of root. If a container image was built to require root and you set this, it will fail to start — which is a good, loud failure, not a silent security gap. Hardening sometimes surfaces an image's OWN bad assumptions.
  • capabilities: drop: ["ALL"] — Linux capabilities are fine-grained permissions (NET_BIND_SERVICE, SYS_ADMIN, dozens more) a process can hold even without full root. Dropping all of them, then adding back only the specific ones actually needed, is the least-privilege pattern applied to capabilities specifically.
  • readOnlyRootFilesystem: true — the container's own filesystem cannot be written to at all (use an explicit emptyDir volume, ROOT 08, for anything that genuinely needs to write temporary files). This closes off a whole category of attack that relies on writing a malicious file to disk.

Why this matters even when "nothing is currently wrong"

None of these settings fix a bug or a vulnerability — they limit the BLAST RADIUS if one exists that you don't yet know about. A container hardened with non-root, dropped capabilities, and a read-only filesystem gives a successful exploit dramatically less to work with than an unhardened one, even against the exact same vulnerability. This is the entire point of defense in depth: you don't rely on any single layer being perfect.

Instructor Notes

Approximate timing: 15 minutes read; 10-12 minutes live with the demonstration.

Demo plan: Have the demonstration activity ready to run right after this lesson — seeing a concrete before/after Pod definition lands the abstract "least privilege" principle far better than the lesson text alone.

Likely misconceptions to watch for:

  • Students sometimes think hardening settings are only relevant "if you expect to be attacked." Reframe: defense in depth assumes SOMETHING will eventually go wrong somewhere (a vulnerability, a bug, a misconfiguration) and prepares for that, rather than betting everything on nothing ever going wrong.
  • runAsNonRoot: true failing a Pod's startup is sometimes read as "the security setting is broken." It's the opposite — it's correctly refusing to let a root-requiring image start, which is valuable, actionable information about the image itself.

Discussion question: "If dropping all capabilities breaks a container that turns out to genuinely need one specific capability, what's the right fix — removing the drop, or something more targeted?" (Answer: add back only that ONE specific capability rather than removing the blanket drop — least privilege means "exactly what's needed," not "give up and grant everything again.")

Optional extension: ask students to identify one setting from this lesson that would have made zero difference against a vulnerability that lets an attacker read environment variables (a good check that they understand these are layered, not universal, protections — the answer is that none of SecurityContext's settings here directly protect secrets stored in env vars; that's a different concern, covered later in this course).