2 lines
4.3 KiB
HTML
2 lines
4.3 KiB
HTML
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>CKS lesson 17: Tenant isolation admission</title><link rel="stylesheet" href="../assets/course.css"></head><body><main><p class="eyebrow">Lesson 0017 · 45 minutes · Minimize Microservice Vulnerabilities</p><h1>Block host-escape settings before scheduling</h1><p class="lede">Namespace isolation is weak if a tenant can request host namespaces, host networking, privileged containers, or hostPath volumes. This drill uses native CEL admission controls to make those settings unrepresentable in one tenant namespace.</p><div class="callout"><strong>Exam reflex:</strong> protect optional fields with CEL <code>has(...)</code> checks. A policy must handle an omitted securityContext as safely as an explicit <code>false</code>.</div><h2>Timed task: 35 minutes</h2><p>Apply <code>lab/lesson-17-fixture.yaml</code>. Create <code>lab/lesson-17-answer.yaml</code> from scratch containing a <code>ValidatingAdmissionPolicy</code> and <code>ValidatingAdmissionPolicyBinding</code>.</p><p>Only in namespace <code>tenant-a</code>, deny Pod creates and updates when any of the following is true:</p><ul><li><code>hostNetwork</code>, <code>hostPID</code>, or <code>hostIPC</code> is true.</li><li>Any volume is a <code>hostPath</code> volume.</li><li>Any regular container is privileged.</li></ul><p>The policy must allow a normal unprivileged Pod that omits all of these fields. Use <code>failurePolicy: Fail</code>, a useful denial message, and <code>Deny</code> in the binding. Scope the binding with the supplied namespace label; do not apply it cluster-wide or use a webhook.</p><h2>Verification</h2><pre><code>kubectl --context kind-cks-lab apply -f .\lab\lesson-17-fixture.yaml kubectl --context kind-cks-lab apply -f .\lab\lesson-17-answer.yaml kubectl --context kind-cks-lab -n tenant-a run normal --image=busybox:1.37 --restart=Never -- sh -c 'sleep 60' kubectl --context kind-cks-lab -n tenant-a run host-net --image=busybox:1.37 --restart=Never --overrides '{"apiVersion":"v1","spec":{"hostNetwork":true}}' -- sh -c 'sleep 60' kubectl --context kind-cks-lab -n default run host-net-outside --image=busybox:1.37 --restart=Never --overrides '{"apiVersion":"v1","spec":{"hostNetwork":true}}' -- sh -c 'sleep 60'</code></pre><p>Expected: <code>normal</code> is admitted, <code>host-net</code> is rejected, and <code>host-net-outside</code> is admitted. Clean up the two admitted test Pods afterward. Also inspect your CEL carefully: the commands prove host networking, while the policy must cover all four listed controls.</p><h2>Retrieval check</h2><div class="quiz"><h3>Question</h3><p>Why is a plain expression such as <code>c.securityContext.privileged == false</code> unsafe for this task?</p><label><input type="radio" name="q" value="optional">A container can omit <code>securityContext</code>; the expression must handle optional fields without an evaluation error.</label><label><input type="radio" name="q" value="scope">Privileged is a namespace-level field.</label><label><input type="radio" name="q" value="port">Privileged containers always require a host port.</label><button onclick="check()">Check answer</button><p id="feedback" class="feedback" aria-live="polite"></p></div><h2>Documentation target</h2><p>Use the Kubernetes <a href="https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/">Validating Admission Policy</a> reference and inspect CEL field availability with <code>kubectl explain pod.spec</code>.</p><h2>What to send me</h2><p>Paste the policy and binding, plus the three admission outcomes. I’ll inspect scope, optional-field handling, and every escape path.</p><footer>Previous: <a href="0016-tls-ingress.html">TLS Ingress</a> · CKS domain: Minimize Microservice Vulnerabilities</footer></main><script>function check(){const c=document.querySelector('input[name=q]:checked'),f=document.getElementById('feedback');if(!c){f.textContent='Choose an answer.';f.className='feedback bad';return;}if(c.value==='optional'){f.textContent='Correct. CEL expressions must explicitly handle fields that are optional in the Kubernetes API.';f.className='feedback good';}else{f.textContent='Not quite. securityContext can be absent, so a robust policy must account for it.';f.className='feedback bad';}}</script></body></html>
|