├── LICENSE
└── README.md
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Johannes Schnatterer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | cks-short-tips
2 | ===
3 |
4 | 1. [Have a plan for preparation](#have-a-plan-for-preparation)
5 | - [Curated CKS Resources](#curated-cks-resources)
6 | 2. [Train for speed](#train-for-speed)
7 | - [Disable unsafe pasting](#disable-unsafe-pasting)
8 | - [Use aliases and tab completion](#use-aliases-and-tab-completion)
9 | - [Be fast with CLI tools](#be-fast-with-cli-tools)
10 | 3. [Know your tools and technologies](#know-your-tools-and-technologies)
11 | 4. [Be thorough](#be-thorough)
12 | 5. [Don't give up](#dont-give-up)
13 |
14 |
15 |
16 | # Have a plan for preparation
17 |
18 | There a [tons of resources](#curated-cks-resources) out there.
19 | Use them to acquire a wider knowledge, before training specifically for the exam.
20 |
21 | Here's my plan, as an example:
22 |
23 | I invested about 5 working days over a period of three weeks before the exam.
24 | As a seasoned developer in the public cloud I was quick with kubectl, security-context and so on, but not so much with api-server config.
25 | Retrospectively, spending maybe one more day would not have been advisable, as I had to look up a lot of api-server-related stuff in the docs during the exam.
26 |
27 | 1. **Read the Docs for the Certs.**
28 | IMO most importantly: [Resources Allowed: All LF Certification Programs - T&C DOCS (Candidate Facing Resources)](https://docs.linuxfoundation.org/tc-docs/certification/certification-resources-allowed#certified-kubernetes-security-specialist-cks).
29 | 2. **Work your way through the curriculum.**
30 | * read through [Walid Shaari's curated resources](https://github.com/walidshaari/Certified-Kubernetes-Security-Specialist), which add a lot of useful detail to rather abstract curriculum.
31 | * follow-up reading on every topic!
32 | * get your handy dirty! Install every tool on your local kubernetes cluster and apply the getting started docs.
33 | I use k3d via [gitops playground](https://github.com/cloudogu/gitops-playground)
34 | 3. **Solve example questions, learn from the results and from your errors.**
35 | * [Mohamed Abukar's mock exam questions](https://github.com/moabukar/CKS-Exercises-Certified-Kubernetes-Security-Specialist/tree/main/7-mock-exam-questions)
36 | * [These](https://github.com/snigdhasambitak/cks) look like old killer.sh Questions with solutions, but no harm in having a look at them before having you first killer.sh try.
37 | * These look promising, including a learning platform: [ViktorUJ/cks](https://github.com/ViktorUJ/cks/tree/master/tasks/cks/labs)
38 | I discovered them only after I passed my CKS, though.
39 | 4. **Have your first try at killer.sh (the week before the exam)**
40 | * Take it serious, but be prepared to fail.
41 | * Main objective: Get accustomed to the exam environment and find out what to improve
42 | * Note down all your weak spots, both technologically as well es regarding efficiency on the shell/keyboard
43 | 5. **Have your second try at killer.sh (one or two days before the exam)**
44 | * This should give you confidence that you're now fully prepared and very time efficient with the tools
45 | * Note down some more fine-tuning
46 | * Follow up on the things that were not perfect
47 | 6. **Pass the exam**
48 | * Begin with the first question and try to solve as many questions as possible
49 | * Only if you're very unsure, flag some questions and come back later.
50 | Note that this takes some time, because you'll likely read the question and think about it twice.
51 | On the other hand, losing a lot of time with one question might lead to not having enough time to complete easier tasks later.
52 | * [Don't give up until the exam ends 💪](#dont-give-up)
53 | * 🥂
54 |
55 | ## Curated CKS Resources
56 |
57 | * Interactive learning environments
58 | * Two tries for interactive killer.sh included in your exam voucher. Use them, but use them wisely!
59 | * If you need more, create an account as [killercoda](https://killercoda.com/killer-shell-cka)
60 | * [ViktorUJ/cks](https://github.com/ViktorUJ/cks/tree/master/tasks/cks/labs) - local platform for learning kubernetes and preparation for CKS
61 | * Community resources
62 | * [Walid Shaari's curated resources](https://github.com/walidshaari/Certified-Kubernetes-Security-Specialist)
63 | * [Video Tutorials by Venkata Ramana Gali](https://www.youtube.com/watch?v=jvmShTBSBoA&list=PLFkEchqXDZx6Bw3B2NRVc499j1TavjOvm),
64 | corresponding [Repo](https://github.com/ramanagali/Interview_Guide/blob/main/CKS_Preparation_Guide.md)
65 | * Example questions
66 | * [Mohamed Abukar's mock exam questions](https://github.com/moabukar/CKS-Exercises-Certified-Kubernetes-Security-Specialist/tree/main/7-mock-exam-questions)
67 | * These look promising, including a learning platform: [ViktorUJ/cks](https://github.com/ViktorUJ/cks/tree/master/tasks/cks/labs)
68 | * [These](https://github.com/snigdhasambitak/cks) look like old killer.sh Questions with solutions, but no harm in having a look at them before having you first killer.sh try.
69 | * [Udemy Courses](https://www.udemy.com/topic/certified-kubernetes-security-specialist-cks/)
70 | even when you don't take a course, having a look at the content might help discovering topics that are relevant
71 | * There are a lot more, when you follow the links in the repos above.
72 |
73 | # Train for speed
74 |
75 | ## Disable unsafe pasting
76 |
77 | [Disable](https://killer.sh/faq) "unsafe pasting" in VM terminal emulator
78 | `"Terminal Preferences->General->Show unsafe paste dialog".`
79 |
80 | ## Use aliases and tab completion
81 |
82 | Those are the ones I used
83 | ```shell
84 | vi ~/.bashrc
85 | alias kg='k get'
86 | alias kd='k describe'
87 | alias ka='k apply -f'
88 | alias kn='k config set-context --current --namespace'
89 | # : wq
90 | source ~/.bashrc
91 | ```
92 |
93 | Note:
94 | * Tab completion does not work for aliases 😐️
95 | So I mainly use them to get a fast overview of pods, services, etc.
96 | ```bash
97 | kg po
98 | kg svc
99 | kg ing
100 | kg deploy
101 | ```
102 | * There already is an alias `k=kubectl`.
103 | Tab completion does work for it, so use e.g. `k get po ` instead of typing or copying pod names
104 | * killer.sh recommends defining these variables, but I use `ctrl` + `z` + `bg` instead
105 | ```bash
106 | export do="--dry-run=client -o yaml" # k create deploy nginx --image=nginx $do
107 |
108 | export now="--force --grace-period 0" # k delete pod x $now
109 | ```
110 | * vi is already set up with useful options, usually no need to edit `~/.vimrc`
111 |
112 | ## Be fast with CLI tools
113 |
114 | * Bash:
115 | * `ctrl` + `z`: keep open but return to shell
116 | * then `fg` return e.g. in `vi`
117 | * or `bg` keeps running in background e.g. for killing pods
118 | * `tmux` - first things in an exam: edit `bashrc` (see above), then start `tmux`
119 | * split pane, preferable horizontal (`ctrl`+`b`+`"`) (easier for copying with mouse)
120 | * move from pane to pane using `ctrl`+`b` + cursor keys
121 | * select mode (scrolling) `ctrl`+`b` + `]` - then use search or cursor keys or page up/down for navigating
122 | Careful: `ctrl`+`w` might close tab. Better use mouse for copying.
123 | * search: in select mode `ctrl`+`b`+`s` or `r` for reverse
124 | `n` for next hit; `Shift+n` for previous hit
125 | * increase size of pane by keeping `ctrl`+`b` pressed and using cursor keys
126 | * `ctrl`+`z` to toggle full screen for a pane
127 | * `vim`
128 | * `w` write, don't quit. Hints:
129 | * use other tmux pane to run `ka`, then come back to fix potential syntactic errors
130 | * or use `ctrl` + `z` to send `vim` to background, run `ka` then `fg` to return to `vim`
131 | * `q` quit, can be combined to `wq`
132 | * `y` = yank = copy
133 | * `p` = paste
134 | * `d` = delete = cut. If you want to delete more lines just to, e.g. `dddd`
135 | * `u` = undo
136 | * redo: `ctrl` + `r`
137 | * `v` = visual (select), use cursor keys, then `y` or `p`
138 | * indent: select then `>` or `<` (repeat with `.`)
139 | * `less`
140 | * switch search to case-insensitive using `:i`
141 | * search using `/`
142 | * `ssh` / `scp`, to access or copy files to/from nodes
143 | * `cut --delimiter ' ' --fields 9 # delimiter space, print field 9`
144 |
145 | # Know your tools and technologies
146 |
147 | * curl
148 | * Validate certificate: `curl -vk 2>&1 https://xyz | grep -i subject`
149 | * [Accessing the Kubernetes API from a Pod](https://kubernetes.io/docs/tasks/run-application/access-api-from-pod/)
150 | Note the path to the secrets
151 | ```bash
152 | k run debug-node --rm -it --image alpine --
153 | 'curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/default/secrets'
154 | ```
155 | * `kube-apiserver`, `kubelet`, etc.
156 | * interne YAMLs konfigurierbar:
157 | * `/etc/kubernetes/manifests`
158 | * `/etc/kubernetes/manifests/kube-apiserver.yaml`
159 | * `/etc/kubernetes/manifests/kube-controller-manager.yaml`
160 | * `/var/lib/kubelet/config.yaml`
161 | * apiserver is automatically restarted when `kube-apiserver.yaml` is changed.
162 | If need be this can be forced using `crictl rmp` , or even using `kubectl` (`k delete pod`) on a controlplane node or using restarting the service
163 | ```shell
164 | #SystemD
165 | systemctl status kubelet
166 | systemctl restart kubelet
167 | # or system V
168 | service kubelet restart
169 | service kubelet status
170 | ```
171 | * [AppArmor](https://kubernetes.io/docs/tutorials/security/apparmor/)
172 | * AppArmor profiles are specified _per-container_. To specify the AppArmor profile to run a Pod container with, add an annotation to the Pod's metadata
173 | * `container.apparmor.security.beta.kubernetes.io/: `
174 | * `container.apparmor.security.beta.kubernetes.io/c1: localhost/very-secure`
175 | * or `runtime/default`
176 | * Profile must be present on node
177 | * Accessing [App Armor Docs](https://gitlab.com/apparmor/apparmor/-/wikis/Documentation) ist permitted
178 | * See [k8s docs](https://kubernetes.io/docs/tutorials/security/apparmor/) for an example
179 | ```shell
180 | apparmor_parser -q < `cat /var/log/syslog | grep -i xyz` or `journalctl -fu falco | grep "xyz error"`
214 | * Output UID and Container ID: `%user.uid,%container.id` see [supported fields doc](https://falco.org/docs/reference/rules/supported-fields/) (allowed in exam!)
215 | ```yaml
216 | rules_file:
217 | - /etc/falco/falco_rules.yaml
218 | - /etc/falco/falco_rules.local.yaml
219 | - /etc/falco/rules.d # custom rules
220 | ```
221 | * Tracee
222 | similar to falco, ebpf kernel events, signatures tigger alert.
223 | * Trivy
224 | * `trivy image alpine --severity=HIGH,CRITICAL`
225 | * Kubesec
226 | * `kubesec scan k8s-deployment.yaml | jq`
227 | * `kubesec scan jenkins/tmp-docker-gid-grepper.yaml | jq '.[].scoring.advise'`
228 | ```yaml
229 | apiVersion: v1
230 | kind: Pod
231 | spec:
232 | enableServiceLinks: false
233 | automountServiceAccountToken: false
234 | containers:
235 | - name: restricted
236 | securityContext:
237 | runAsNonRoot: true
238 | runAsUser: 100000
239 | runAsGroup: 100000
240 | allowPrivilegeEscalation: false
241 | readOnlyRootFilesystem: true
242 | seccompProfile:
243 | type: RuntimeDefault
244 | capabilities:
245 | drop:
246 | - ALL
247 | ```
248 | * Kube-bench
249 | * Has to run on node! Either operator, pod or binary on node
250 | * `kube-bench run --targets=master > bench.txt`
251 | * `kube-bench run --targets=node > bench.txt`
252 | * Using `--target` makes solving specific tasks much easier because there usually are a lot of results
253 | * Writing to file allows for comparing the results after mitigation.
254 | * `kube-bench run --targets=master | less` also works
255 | * crictl, similar to `docker` but for CRI
256 | ```shell
257 | crictl pods
258 | crictl ps
259 |
260 | crictl ps --pod $podid # all containers of pod, also works with grep $podid
261 | crictl logs $containerid # see output of crcitcl ps --pod for $containerid
262 | crictl rmp $podid #remove pod
263 | ```
264 | * `etcdctl`: Access secrets directly: (command can be found in docs for [encryption at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)):
265 | ```shell
266 | ETCDCTL_API=3 etcdctl \
267 | --cacert=/etc/kubernetes/pki/etcd/ca.crt \
268 | --cert=/etc/kubernetes/pki/etcd/server.crt \
269 | --key=/etc/kubernetes/pki/etcd/server.key \
270 | get /registry/secrets/default/secret1 | hexdump -C
271 | ```
272 | * `strace`
273 | Count time, calls, and errors for each system call and report a summary on program exit:
274 | `strace -p pid -c`
275 | or ongoing output, e.g. in separate tmux pane/window `strace -p pid 2>&1 | grep -i kill`
276 | e.g. syscalls of container
277 | ```shell
278 | crictl pods # -> POD_ID
279 | critctl ps --pod POD_ID # -> CONTAINER_ID
280 | crictl inspect CONTAINER_ID | grep -i pid # -> PID
281 | strace -p PID -c
282 | # Ctrl + C
283 | #% time seconds usecs/call calls errors syscall
284 | #------ ----------- ----------- --------- --------- ---------------
285 | # 81,08 0,000030 30 1 1 rt_sigtimedwait
286 | # 18,92 0,000007 3 2 wait4
287 | #------ ----------- ----------- --------- --------- ----------------
288 | #100,00 0,000037 12 3 1 total
289 | ```
290 | * OPA [conftest](https://www.conftest.dev/)
291 | * `conftest test some.yaml`
292 | * looks for policies in folder `policy`
293 | * OPA [Gatekeeper](https://open-policy-agent.github.io/gatekeeper/website/)
294 | * OPA = general purpose policy engine; Gatekeeper = kubernetes-specific impl of OPA as K8s Admission controller
295 | * `ConstraintTemplate` -> describe rego
296 | * `Constraint` -> describes matching rules, parameters, etc., lists violations
297 | * Violations of constraints are listed in the `status` field of the corresponding constraint
298 | * The audit pod emits JSON-formatted audit logs to stdout.
299 | * Prometheus Metrics (not relevant for CKS)
300 | * [example](https://open-policy-agent.github.io/gatekeeper/website/docs/howto):
301 | ```yaml
302 | apiVersion: templates.gatekeeper.sh/v1
303 | kind: ConstraintTemplate
304 | metadata:
305 | name: k8srequiredlabels
306 | ---
307 | apiVersion: constraints.gatekeeper.sh/v1beta1
308 | kind: K8sRequiredLabels
309 | metadata:
310 | name: ns-must-have-gk
311 | spec:
312 | enforcementAction: dryrun # deny|warn
313 | ```
314 |
315 | ```sh
316 | # from killer.sh
317 | ## Question 7
318 | k get crd | grep gatekeeper
319 | k edit blacklistimages pod-trusted-images # constraint: add parameter
320 | k edit constrainttemplates blacklistimages #-> template: change rego expression
321 |
322 | ## Preview Question 2
323 | # constraint, add parameter for namespace
324 | k edit requiredlabels namespace-mandatory-labels
325 | # template, fix rego
326 | k edit constrainttemplates requiredlabels
327 | ```
328 | * `dmesg` - prints kernel logs
329 | * `kubeadm`
330 | ```shell
331 | # control plane
332 | k drain $NODE
333 | # ssh to master
334 | apt update && apt install kubeadm=1.29.0-1.1 # if necessary
335 | kubeadm upgrade plan # outputs commands for apply
336 | kubeadm upgrade apply v1.24.1 #use specific version! Outputs message to upgrade kubelet
337 | apt install kubelet=1.29.0-1.1 kubectl=1.29.0-1.1
338 | service kubelet restart #systemctl restart kubelet
339 | k uncordon $NODE
340 |
341 | # node: drain, ssh
342 | apt update && apt install kubeadm=1.29.0-1.1
343 | kubeadm upgrade node
344 | service kubelet restart
345 | # exit, k uncordon
346 | ```
347 | * sha512sum
348 | ```bash
349 | sha512sum -c FILE # can contain all sums and binaries
350 | # FILE
351 | #SUM1 /a/file
352 | #SUM2 another-file
353 | # or indivudal files
354 | sha512sum -c <<< "$1 $2"
355 | ```
356 |
357 | * You might want to install helpful software. Not sure if it is allowed, though
358 | * `apt install bat`-> binary is called `batcat` - syntax highlighted YAML files
359 | * or `tldr` if you need examples for using binaries
360 | or `curl cheat.sh/cut`
361 |
362 | # Be thorough
363 |
364 | * Switch to the correct kubecontext first (there is a command to copy at the beginning of each question)
365 | * Read questions carefully! There a several subtasks.
366 | * Read again when done to see if you did not miss anything.
367 | * Validate your work, e.g. `k get node`, `k get pod`, `k exec -it ...`
368 | * Double check if you wrote the result to the right file
369 | * Sometimes it has to be written to a file on the main host
370 | * Sometimes it has to be written to a file on a node
371 | * Sometimes it is not necessary to write a result
372 | * Every exercise features links to the relevant docs in the header. Have a look a them before searching in the docs first!
373 | * Copy each YAML before editing to your home folder, to be able to reset after possibly messing it up.
374 | Don't copy it to the folder of the original file, this might confuse a running api server, for example.
375 |
376 | In both my killer.sh tries I missed some points.
377 | Even though I solved things correctly or would have been able to, I wrote the result into a wrong file or missed to solve a subtask.
378 | Don't do that, be thorough!
379 |
380 | # Don't give up
381 |
382 | * You are going to need every point to can score and every second you're granted
383 | * If some tasks might seem to difficult, flag them and tackle them again at the end
384 | * Having only one or two minutes left is enough time to score some points by partially solving some question
385 | * You'll be surprised how fast you can learn to solve tasks under pressure
386 | * If you don't know how to solve, start by reading the docs linked at the top
387 | * You don't need to solve the whole question, partial solutions score points as well
388 | * You never know, a partial solution saved in the last seconds might be the one point you need for the 70% passing score!
389 |
390 | Don't give up until you're kicked out of the exam 💪
--------------------------------------------------------------------------------