<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Day 4 on Eriks training corner</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/index.html</link><description>Recent content in Day 4 on Eriks training corner</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://training.caha.cloud/en/kubernetes-gt/day-04/index.xml" rel="self" type="application/rss+xml"/><item><title>Authentication and authorization</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/01-authn-authz/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-04/01-authn-authz/index.html</guid><description>&lt;h1 id="authentication-and-authorization"&gt;Authentication and authorization&lt;/h1&gt;
&lt;p&gt;Every request to the API server passes three gates.&lt;/p&gt;
&lt;div class="mermaid align-center"&gt;graph LR
R[kubectl / Pod / controller] --&amp;gt; A1[&amp;#34;1. Authentication&amp;lt;br/&amp;gt;who are you?&amp;#34;]
A1 --&amp;gt; A2[&amp;#34;2. Authorization&amp;lt;br/&amp;gt;may you do this?&amp;#34;]
A2 --&amp;gt; A3[&amp;#34;3. Admission&amp;lt;br/&amp;gt;is this object acceptable?&amp;#34;]
A3 --&amp;gt; E[(etcd)]
A1 --&amp;gt;|unknown| X1[401]
A2 --&amp;gt;|denied| X2[403]
A3 --&amp;gt;|rejected| X3[denied by policy]&lt;/div&gt;&lt;h2 id="authentication"&gt;Authentication&lt;/h2&gt;
&lt;p&gt;Kubernetes has &lt;strong&gt;no User objects&lt;/strong&gt;. A user is whatever an authenticator says:
a name and a list of groups.&lt;/p&gt;</description></item><item><title>RBAC and least privilege</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/02-rbac/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-04/02-rbac/index.html</guid><description>&lt;h1 id="rbac-and-least-privilege"&gt;RBAC and least privilege&lt;/h1&gt;
&lt;div class="mermaid align-center"&gt;graph LR
S[&amp;#34;Subject&amp;lt;br/&amp;gt;User / Group / ServiceAccount&amp;#34;] --&amp;gt; B[RoleBinding]
B --&amp;gt; R[&amp;#34;Role&amp;lt;br/&amp;gt;verbs on resources&amp;#34;]
R -.valid in.-&amp;gt; NS[one namespace]
S2[Subject] --&amp;gt; CB[ClusterRoleBinding]
CB --&amp;gt; CR[ClusterRole]
CR -.valid in.-&amp;gt; ALL[whole cluster]&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Object&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Contains&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Role&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;namespace&lt;/td&gt;
&lt;td&gt;rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ClusterRole&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;cluster&lt;/td&gt;
&lt;td&gt;rules (also for nodes, PVs, non-resource URLs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RoleBinding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;namespace&lt;/td&gt;
&lt;td&gt;subjects -&amp;gt; Role &lt;strong&gt;or ClusterRole&lt;/strong&gt; (limited to this namespace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ClusterRoleBinding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;cluster&lt;/td&gt;
&lt;td&gt;subjects -&amp;gt; ClusterRole everywhere&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Binding a &lt;strong&gt;ClusterRole with a RoleBinding&lt;/strong&gt; is the common pattern: define
&amp;ldquo;developer&amp;rdquo; once, grant it per namespace.&lt;/p&gt;</description></item><item><title>Service accounts</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/03-service-accounts/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-04/03-service-accounts/index.html</guid><description>&lt;h1 id="service-accounts"&gt;Service accounts&lt;/h1&gt;
&lt;p&gt;Identity for &lt;strong&gt;workloads&lt;/strong&gt;. Every namespace has a &lt;code&gt;default&lt;/code&gt; ServiceAccount and
every Pod runs as one.&lt;/p&gt;
&lt;div class="mermaid align-center"&gt;graph LR
SA[ServiceAccount app] --&amp;gt; P[Pod serviceAccountName: app]
K[kubelet] --&amp;gt;|projected token&amp;lt;br/&amp;gt;1 h, bound to Pod| P
P --&amp;gt;|Authorization: Bearer ...| API[API server]
RB[RoleBinding] --&amp;gt; SA&lt;/div&gt;&lt;p&gt;The kubelet mounts a short-lived, audience-bound &lt;strong&gt;JWT&lt;/strong&gt; into
&lt;code&gt;/var/run/secrets/kubernetes.io/serviceaccount/&lt;/code&gt; (plus CA and namespace) and
refreshes it. The token dies with the Pod. The API sees the Pod as
&lt;code&gt;system:serviceaccount:&amp;lt;ns&amp;gt;:&amp;lt;name&amp;gt;&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Security context and container hardening</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/04-security-context/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-04/04-security-context/index.html</guid><description>&lt;h1 id="security-context-and-container-hardening"&gt;Security context and container hardening&lt;/h1&gt;
&lt;p&gt;A container is a process on the node. The security context decides how much
of the node that process can touch.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;securityContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Pod level - applies to all containers&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runAsUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10001&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fsGroup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10001&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;seccompProfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;RuntimeDefault }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginxinc/nginx-unprivileged:1.27 &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# listens on 8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;securityContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# container level - wins over Pod level&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ALL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumeMounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- {&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tmp, mountPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/tmp } &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# writable scratch space&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- {&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tmp, emptyDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{}&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Protects against&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;runAsNonRoot&lt;/code&gt; / &lt;code&gt;runAsUser&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;root in the container = root-owned files on the node if it escapes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowPrivilegeEscalation: false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;setuid binaries, &lt;code&gt;sudo&lt;/code&gt; inside&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;readOnlyRootFilesystem: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;attacker dropping tools or changing the app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;capabilities.drop: [ALL]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;raw sockets, changing ownership, binding ports &amp;lt; 1024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;seccompProfile: RuntimeDefault&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;~300 rarely needed syscalls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;never&lt;/strong&gt; &lt;code&gt;privileged: true&lt;/code&gt;, &lt;code&gt;hostPID&lt;/code&gt;, &lt;code&gt;hostNetwork&lt;/code&gt;, &lt;code&gt;hostPath: /&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;these are the node&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="container-hardening-checklist"&gt;Container hardening checklist&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Minimal base image (distroless, alpine, chiselled) - fewer CVEs, no shell.&lt;/li&gt;
&lt;li&gt;Image built to run as &lt;strong&gt;non-root&lt;/strong&gt; (&lt;code&gt;USER 10001&lt;/code&gt; in the Dockerfile).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pinned&lt;/strong&gt; tag or digest (&lt;code&gt;@sha256:...&lt;/code&gt;), never &lt;code&gt;latest&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Scanned in the pipeline (Trivy - Lab 33), signed (cosign).&lt;/li&gt;
&lt;li&gt;Resource limits set (Day 3) - a runaway container cannot starve the node.&lt;/li&gt;
&lt;li&gt;Only the ServiceAccount token it needs (usually none).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many public images (nginx, httpd) expect root. Use their unprivileged variants
or build your own.&lt;/p&gt;</description></item><item><title>Pod Security Standards and Admission</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/05-pod-security/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-04/05-pod-security/index.html</guid><description>&lt;h1 id="pod-security-standards-and-admission"&gt;Pod Security Standards and Admission&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Pod Security Standards&lt;/strong&gt; define three levels. &lt;strong&gt;Pod Security Admission&lt;/strong&gt;
(built in) enforces them per namespace with labels.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Allows&lt;/th&gt;
&lt;th&gt;For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;privileged&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;everything&lt;/td&gt;
&lt;td&gt;system namespaces, CNI, storage drivers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;baseline&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;no privileged, no host namespaces, no hostPath, no dangerous capabilities&lt;/td&gt;
&lt;td&gt;most legacy apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;restricted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;baseline + non-root, drop ALL, no privilege escalation, seccomp&lt;/td&gt;
&lt;td&gt;new apps - the target&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enforce&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;violating Pods are &lt;strong&gt;rejected&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;audit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;allowed, recorded in the audit log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;warn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;allowed, the user sees a warning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Namespace&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;shop&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;baseline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pod-security.kubernetes.io/enforce-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pod-security.kubernetes.io/warn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;restricted&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pod-security.kubernetes.io/audit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;restricted&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The typical rollout: &lt;strong&gt;warn/audit restricted, enforce baseline&lt;/strong&gt; - then fix
the warnings and raise &lt;code&gt;enforce&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Admission policies</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/06-admission-policies/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-04/06-admission-policies/index.html</guid><description>&lt;h1 id="admission-policies"&gt;Admission policies&lt;/h1&gt;
&lt;p&gt;PSA covers Pod security only. Organisation rules - &amp;ldquo;every Deployment has an
owner label&amp;rdquo;, &amp;ldquo;images only from our registry&amp;rdquo;, &amp;ldquo;no &lt;code&gt;latest&lt;/code&gt;&amp;rdquo; - need a
&lt;strong&gt;policy engine&lt;/strong&gt; in the admission chain.&lt;/p&gt;
&lt;div class="mermaid align-center"&gt;graph LR
R[request, authorized] --&amp;gt; M[mutating admission&amp;lt;br/&amp;gt;add defaults, sidecars]
M --&amp;gt; S[schema validation]
S --&amp;gt; V[validating admission&amp;lt;br/&amp;gt;PSA, VAP, Kyverno, Gatekeeper]
V --&amp;gt;|allowed| E[(etcd)]
V --&amp;gt;|denied| X[error to the user]&lt;/div&gt;&lt;h2 id="validatingadmissionpolicy-built-in"&gt;ValidatingAdmissionPolicy (built in)&lt;/h2&gt;
&lt;p&gt;Rules written in &lt;strong&gt;CEL&lt;/strong&gt;, evaluated inside the API server - no extra
component. GA since Kubernetes 1.30.&lt;/p&gt;</description></item><item><title>Network policies and segmentation</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/07-network-policies/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-04/07-network-policies/index.html</guid><description>&lt;h1 id="network-policies-and-segmentation"&gt;Network policies and segmentation&lt;/h1&gt;
&lt;p&gt;By default &lt;strong&gt;every Pod can talk to every Pod&lt;/strong&gt; in every namespace. A
compromised frontend can reach the database directly.&lt;/p&gt;
&lt;div class="mermaid align-center"&gt;graph LR
subgraph shop
F[frontend] --&amp;gt;|allowed| B[backend]
B --&amp;gt;|allowed| D[(db)]
F -.x.-&amp;gt; D
end
O[other namespace] -.x.-&amp;gt; B&lt;/div&gt;&lt;h2 id="networkpolicy"&gt;NetworkPolicy&lt;/h2&gt;
&lt;p&gt;Selects Pods and lists what may reach them (&lt;strong&gt;ingress&lt;/strong&gt;) and what they may
reach (&lt;strong&gt;egress&lt;/strong&gt;). Enforced by the CNI - here &lt;strong&gt;Calico&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;networking.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NetworkPolicy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db-from-backend, namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;shop }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;podSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;db } &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# the Pods this policy protects&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policyTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Ingress&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;podSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;backend }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- {&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TCP, port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5432&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="the-rules-of-the-game"&gt;The rules of the game&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A Pod selected by &lt;strong&gt;no&lt;/strong&gt; policy: everything allowed.&lt;/li&gt;
&lt;li&gt;A Pod selected by &lt;strong&gt;any&lt;/strong&gt; policy for a direction: only what a policy allows.&lt;/li&gt;
&lt;li&gt;Policies are &lt;strong&gt;additive&lt;/strong&gt; - there is no &amp;ldquo;deny&amp;rdquo; rule, only &amp;ldquo;allow&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;from&lt;/code&gt; entries: &lt;code&gt;podSelector&lt;/code&gt;, &lt;code&gt;namespaceSelector&lt;/code&gt;, both combined (AND in
one item, OR as separate items), &lt;code&gt;ipBlock&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;With egress policies, &lt;strong&gt;allow DNS&lt;/strong&gt; (UDP/TCP 53 to kube-system) or nothing
resolves.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# default deny in a namespace - start here&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;networking.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NetworkPolicy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;default-deny, namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;shop }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;podSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policyTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Ingress&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Egress&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="calico-extras"&gt;Calico extras&lt;/h2&gt;
&lt;p&gt;The standard API is namespaced and allow-only. Calico adds
(&lt;code&gt;projectcalico.org/v3&lt;/code&gt;, visible to kubectl through the Calico API server):&lt;/p&gt;</description></item><item><title>Images, secrets and audit</title><link>https://training.caha.cloud/en/kubernetes-gt/day-04/08-supply-chain/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-04/08-supply-chain/index.html</guid><description>&lt;h1 id="images-secrets-and-audit"&gt;Images, secrets and audit&lt;/h1&gt;
&lt;h2 id="image-scanning"&gt;Image scanning&lt;/h2&gt;
&lt;div class="mermaid align-center"&gt;graph LR
C[code] --&amp;gt; B[build image] --&amp;gt; S[&amp;#34;scan&amp;lt;br/&amp;gt;Trivy / Grype&amp;#34;] --&amp;gt; SIGN[&amp;#34;sign&amp;lt;br/&amp;gt;cosign&amp;#34;] --&amp;gt; R[(registry)]
R --&amp;gt; A[&amp;#34;admission&amp;lt;br/&amp;gt;allowed registry? signed?&amp;#34;] --&amp;gt; K[cluster]&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;trivy image nginx:1.27 --severity HIGH,CRITICAL
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;trivy config ./manifests/ &lt;span class="c1"&gt;# misconfigurations in YAML, Helm, Dockerfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;trivy k8s --report summary &lt;span class="c1"&gt;# scan the running cluster&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Fix order: base image update &amp;gt; fewer packages &amp;gt; accept with justification.&lt;/p&gt;
&lt;div class="box notices cstyle warning"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-triangle"&gt;&lt;/i&gt; Warning&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;&lt;strong&gt;The scanner is part of your supply chain too.&lt;/strong&gt; In March 2026 attackers
published a malicious Trivy &lt;strong&gt;v0.69.4&lt;/strong&gt; and hijacked the &lt;code&gt;trivy-action&lt;/code&gt; /
&lt;code&gt;setup-trivy&lt;/code&gt; GitHub Action tags to steal CI secrets. Pin tools and actions to
verified versions or commit SHAs, and verify checksums and signatures.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item></channel></rss>