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]>
77 lines
3.9 KiB
Markdown
77 lines
3.9 KiB
Markdown
# NetworkPolicy as a Security Control & Supply Chain Trust
|
|
|
|
## NetworkPolicy, revisited as a security posture
|
|
|
|
ROOT 07 introduced NetworkPolicy architecturally: Kubernetes doesn't isolate Pod-to-Pod traffic
|
|
by default, and NetworkPolicy is how you declare intended reachability. Here, the same
|
|
mechanism is the point of a deliberate SECURITY practice: **default deny**.
|
|
|
|
A default-deny policy blocks all traffic to selected Pods, and you then explicitly allow only
|
|
what's actually needed:
|
|
|
|
```yaml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: NetworkPolicy
|
|
metadata:
|
|
name: default-deny
|
|
spec:
|
|
podSelector: {} # selects EVERY Pod in the namespace
|
|
policyTypes: ["Ingress"]
|
|
```
|
|
|
|
An empty `podSelector: {}` with no ingress rules means "select every Pod, allow nothing in" —
|
|
the network equivalent of the SecurityContext principle from earlier in this course: start
|
|
from nothing, add back only what's proven necessary. This is exactly the opposite of
|
|
Kubernetes' un-configured default (everything open), which is precisely why it has to be
|
|
declared explicitly rather than relying on any built-in setting.
|
|
|
|
**Egress restriction** works the same way in reverse — restricting what a Pod can call OUT to,
|
|
not just what can call IN. A compromised Pod that can freely make outbound connections to
|
|
anything is far more dangerous (data exfiltration, calling out to an attacker's server) than one
|
|
restricted to only the specific destinations it legitimately needs.
|
|
|
|
## Supply chain: trusting what you run before it ever starts
|
|
|
|
Everything covered so far in this course assumes the container image itself is trustworthy.
|
|
Supply-chain security is about that assumption specifically:
|
|
|
|
- **Image-pull secrets** — when pulling from a private registry, the cluster needs credentials
|
|
to authenticate. Storing and using these correctly (rather than, say, a publicly-readable
|
|
registry with no access control) is a basic supply-chain control: only images from a trusted,
|
|
access-controlled source get pulled at all.
|
|
- **Minimizing image footprint** (referenced here, not a hands-on Lab in this module) — a
|
|
smaller image means fewer packages, fewer known CVEs, and a smaller attack surface if the
|
|
image is ever compromised.
|
|
|
|
## TLS at the Ingress layer: protecting data in transit
|
|
|
|
Recall ROOT 07's Ingress lesson — routing external HTTP(S) traffic by hostname/path. Configuring
|
|
TLS termination at that same Ingress layer means traffic between users and your cluster is
|
|
encrypted, protecting against interception on the network path. This is a security concern
|
|
layered on top of the same architectural mechanism, the same relationship NetworkPolicy has to
|
|
its ROOT 07 introduction.
|
|
|
|
## Instructor Notes
|
|
|
|
**Approximate timing:** 15 minutes read; 10 minutes live.
|
|
|
|
**Likely misconceptions to watch for:**
|
|
- Students sometimes think "default deny" means blocking ALL traffic including what the
|
|
application needs to function. Clarify: default deny is the STARTING point; you then add
|
|
specific allow rules for exactly what's needed — the goal state is fully functional AND fully
|
|
intentional, not non-functional.
|
|
- Egress restriction is sometimes seen as less important than ingress. Emphasize the
|
|
exfiltration angle explicitly — a compromised Pod's outbound reach is just as much a real
|
|
risk as inbound exposure.
|
|
|
|
**Discussion question:** "Why is 'default deny, then explicitly allow' a better starting
|
|
posture than 'default allow, then explicitly block known-bad traffic'?" (Answer: default-deny
|
|
means a NEW, unanticipated attempt to reach or leave a Pod is blocked by default; default-allow
|
|
means anything not YET identified as bad gets through — you're always one step behind an
|
|
attacker under the second model.)
|
|
|
|
**Optional extension:** ask what a real team would want to verify before trusting a
|
|
publicly-available container image from an unfamiliar source, beyond just "does it work" — a
|
|
good bridge into image scanning/provenance concepts (not built as a hands-on Lab in this course,
|
|
but worth naming as a real practice).
|