How to pass CKS — Kubernetes Security Specialist exam. Part 1

CKS certification is a performance-based, hands-on exam that tests knowledge of K8s security in a simulated, real-world environment. I had 15 different tasks and 120 min to complete them. 68 % required to pass.

CKS requires CKA (Certified Kubernetes Administrator) passed first. It is a mandatory pre-request. I shared my tips in a different post on how to pass CKA and CKAD. If you received CKA, know how to use kubectl and Kubernetes documentation in an efficient way, you can start study for CKS. CKS is harder than the other two K8s exams. Good preparation requires deep study of native and external Kubernetes security tools, best security practices, and also requires a good knowledge of Kubernetes architecture, especially about API server, etcd, and kubelet. The exam covers the following areas: gVisor, AppArmor, RBAC, Network Policies, Auditing, Falco,Trivy, Admission Controllers, CIS Benchmark, Pod Security Policies, writing secure Dockerfiles, Secrets, Privileged Pods.

In the next episodes, I will share my experience of how to solve the exam tasks. I keep tips in the GitHub repo

  1. Episode — Network Policies

Network Policies

Configure bash auto-completion on Linux before you start the exam:

source <(kubectl completion bash)
alias k=kubectl
complete -F __start_kubectl k

Network Policies are an important topic on the exam. If you want to control traffic flow at the IP address or port level (OSI layer 3 or 4), then you should use K8s Network Policies. By default, all pods in a cluster can communicate with any other pod on the same cluster, including pods from different namespaces, and this includes the main kube-system namespace where the control plane is hosted. Unless changed, this is the network policy that is configured when you install Kubernetes and deploy your cluster. Network policies specify how groups of pods are allowed to communicate with each other and other network endpoints. You can think of them as the Kubernetes equivalent of a firewall.

“default-deny-all” network policy. It is a good practice to create default deny all Ingress traffic first and later Egress traffic in the namespace and just open necessary communication between pods or namespaces

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: test
spec:
podSelector: {}
policyTypes:
- Ingress

Ingress (above) and Egress (below) default deny

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: test
spec:
podSelector: {}
policyTypes:
- Egress

If we want to allow some traffic to or from Pods or namespaces, there are four kinds of selectors that can be specified in an ingress from section or egress to section:

podSelector — selects particular Pods in the same namespace as the NetworkPolicy which should be allowed as ingress sources or egress destinations,

namespaceSelector -selects particular namespaces for which all Pods should be allowed as ingress sources or egress destinations,

namespaceSelector and podSelector - both selectors must match

namespaceSelector or podSelector - one selector in an array must match

problem 1 allow traffic to Pod with a label pod=ingress in namespace test from pods in the namespace default or from pods in the local Namespace with the label demo=pod

solution — you need to explicitly set the label for namespace default , the label is not added automatically during namespace creation

k label ns default ns=default
k get ns --show-labels

and apply the following YAML file (k apply -f file.yaml)

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-ingress
namespace: test
spec:
podSelector:
matchLabels:
pod: ingress
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
ns: default
- podSelector:
matchLabels:
demo: pod

problem 2 — allow traffic from Pod with a label pod=egress in namespace test to pods in the namespace default and with the label demo=pod .

solution — let's create required label:

k label ns default ns=default
k get ns --show-labels

and apply the following YAML file (k apply -f file.yaml)

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-egress
namespace: test
spec:
podSelector:
matchLabels:
pod: egress
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
ns: default
podSelector:
matchLabels:
demo: pod

problem 3 allow traffic to all Pods in a namespace test from pods in the namespace default

solution:

k label ns default ns=default
k get ns --show-labels

and create the following network policy

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-ingress
namespace: test
spec:
podSelector:{}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
ns: default

if you need to display already existing labels

k get pods --show-labels
k get ns --show-labels

Examples from this post are available on GitHub. Thank you and see you soon in the next episode! The next post will be about gVisor.