{"id":16514846,"url":"https://github.com/schnatterer/cks-short-tips","last_synced_at":"2025-06-22T01:33:46.262Z","repository":{"id":225813579,"uuid":"766927997","full_name":"schnatterer/cks-short-tips","owner":"schnatterer","description":"Five short tips for passing the CKS exam (Certified Kubernetes Security Specialist)","archived":false,"fork":false,"pushed_at":"2024-03-04T12:46:48.000Z","size":8,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-02T13:30:17.590Z","etag":null,"topics":["apparmor","certified-kubernetes-security-specialist","cks","etcd","falco","k8s","kube-apiserver","kube-bench","kubectl","kubernetes","kubesec","opa","open-policy-agent","psa","seccomp","security","trivy"],"latest_commit_sha":null,"homepage":"https://trainingportal.linuxfoundation.org/courses/certified-kubernetes-security-specialist-cks","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/schnatterer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-04T11:49:45.000Z","updated_at":"2024-12-03T03:01:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"63727a4f-bc78-4fd0-814c-4ae2173faf73","html_url":"https://github.com/schnatterer/cks-short-tips","commit_stats":null,"previous_names":["schnatterer/cks-short-tips"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/schnatterer/cks-short-tips","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schnatterer%2Fcks-short-tips","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schnatterer%2Fcks-short-tips/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schnatterer%2Fcks-short-tips/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schnatterer%2Fcks-short-tips/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schnatterer","download_url":"https://codeload.github.com/schnatterer/cks-short-tips/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schnatterer%2Fcks-short-tips/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261220241,"owners_count":23126717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apparmor","certified-kubernetes-security-specialist","cks","etcd","falco","k8s","kube-apiserver","kube-bench","kubectl","kubernetes","kubesec","opa","open-policy-agent","psa","seccomp","security","trivy"],"created_at":"2024-10-11T16:14:11.165Z","updated_at":"2025-06-22T01:33:41.226Z","avatar_url":"https://github.com/schnatterer.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"cks-short-tips\n===\n\n1. [Have a plan for preparation](#have-a-plan-for-preparation)\n   - [Curated CKS Resources](#curated-cks-resources)\n2. [Train for speed](#train-for-speed)\n   - [Disable unsafe pasting](#disable-unsafe-pasting)\n   - [Use aliases and tab completion](#use-aliases-and-tab-completion)\n   - [Be fast with CLI tools](#be-fast-with-cli-tools)\n3. [Know your tools and technologies](#know-your-tools-and-technologies)\n4. [Be thorough](#be-thorough)\n5. [Don't give up](#dont-give-up)\n\n\u003cimg width=\"25%\" style=\"float: right\" src=\"https://www.cncf.io/wp-content/uploads/2020/11/kubernetes-security-specialist-logo.svg\" \u003e\u003c/img\u003e\n\n# Have a plan for preparation\n\nThere a [tons of resources](#curated-cks-resources) out there. \nUse them to acquire a wider knowledge, before training specifically for the exam.\n\nHere's my plan, as an example:\n\nI invested about 5 working days over a period of three weeks before the exam.  \nAs 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.  \nRetrospectively, 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.\n\n1. **Read the Docs for the Certs.**  \n   IMO most importantly: [Resources Allowed: All LF Certification Programs - T\u0026C DOCS (Candidate Facing Resources)](https://docs.linuxfoundation.org/tc-docs/certification/certification-resources-allowed#certified-kubernetes-security-specialist-cks).\n2. **Work your way through the curriculum.**  \n   * 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.\n   * follow-up reading on every topic!\n   * get your handy dirty! Install every tool on your local kubernetes cluster and apply the getting started docs.  \n     I use k3d via [gitops playground](https://github.com/cloudogu/gitops-playground)  \n3. **Solve example questions, learn from the results and from your errors.**  \n   * [Mohamed Abukar's mock exam questions](https://github.com/moabukar/CKS-Exercises-Certified-Kubernetes-Security-Specialist/tree/main/7-mock-exam-questions)\n   * [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.\n   * These look promising, including a learning platform: [ViktorUJ/cks](https://github.com/ViktorUJ/cks/tree/master/tasks/cks/labs)  \n     I discovered them only after I passed my CKS, though.\n4. **Have your first try at killer.sh (the week before the exam)**  \n   * Take it serious, but be prepared to fail.\n   * Main objective: Get accustomed to the exam environment and find out what to improve\n   * Note down all your weak spots, both technologically as well es regarding efficiency on the shell/keyboard\n5. **Have your second try at killer.sh (one or two days before the exam)**\n   * This should give you confidence that you're now fully prepared and very time efficient with the tools\n   * Note down some more fine-tuning\n   * Follow up on the things that were not perfect\n6. **Pass the exam**\n   * Begin with the first question and try to solve as many questions as possible\n   * Only if you're very unsure, flag some questions and come back later.  \n     Note that this takes some time, because you'll likely read the question and think about it twice.  \n     On the other hand, losing a lot of time with one question might lead to not having enough time to complete easier tasks later.\n   * [Don't give up until the exam ends 💪](#dont-give-up)\n   * 🥂\n\n## Curated CKS Resources\n\n* Interactive learning environments\n  * Two tries for interactive killer.sh included in your exam voucher. Use them, but use them wisely!\n  * If you need more, create an account as [killercoda](https://killercoda.com/killer-shell-cka)\n  * [ViktorUJ/cks](https://github.com/ViktorUJ/cks/tree/master/tasks/cks/labs) - local platform for learning kubernetes and preparation for CKS\n* Community resources\n  * [Walid Shaari's curated resources](https://github.com/walidshaari/Certified-Kubernetes-Security-Specialist)\n  * [Video Tutorials by Venkata Ramana Gali](https://www.youtube.com/watch?v=jvmShTBSBoA\u0026list=PLFkEchqXDZx6Bw3B2NRVc499j1TavjOvm),\n    corresponding [Repo](https://github.com/ramanagali/Interview_Guide/blob/main/CKS_Preparation_Guide.md)\n* Example questions\n  * [Mohamed Abukar's mock exam questions](https://github.com/moabukar/CKS-Exercises-Certified-Kubernetes-Security-Specialist/tree/main/7-mock-exam-questions)\n  * These look promising, including a learning platform: [ViktorUJ/cks](https://github.com/ViktorUJ/cks/tree/master/tasks/cks/labs)\n  * [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.\n* [Udemy Courses](https://www.udemy.com/topic/certified-kubernetes-security-specialist-cks/)  \n  even when you don't take a course, having a look at the content might help discovering topics that are relevant\n* There are a lot more, when you follow the links in the repos above.\n\n# Train for speed\n\n## Disable unsafe pasting\n\n[Disable](https://killer.sh/faq) \"unsafe pasting\" in VM terminal emulator\n  `\"Terminal Preferences-\u003eGeneral-\u003eShow unsafe paste dialog\".`\n\n## Use aliases and tab completion\n\nThose are the ones I used\n```shell\nvi ~/.bashrc\nalias kg='k get'\nalias kd='k describe'\nalias ka='k apply -f'\nalias kn='k config set-context --current --namespace'\n# : wq\nsource ~/.bashrc\n```\n\nNote:\n* Tab completion does not work for aliases 😐️   \n So I mainly use them to get a fast overview of pods, services, etc.\n```bash\nkg po\nkg svc\nkg ing\nkg deploy\n```\n* There already is an alias `k=kubectl`.  \n  Tab completion does work for it, so use e.g. `k get po \u003cTAB\u003e` instead of typing or copying pod names\n* killer.sh recommends defining these variables, but I use `ctrl` + `z` + `bg` instead\n```bash\nexport do=\"--dry-run=client -o yaml\"    # k create deploy nginx --image=nginx $do\n\nexport now=\"--force --grace-period 0\"   # k delete pod x $now\n```\n* vi is already set up with useful options, usually no need to edit `~/.vimrc`\n\n## Be fast with CLI tools\n\n* Bash:\n    * `ctrl` + `z`: keep open but return to shell\n    * then `fg` return e.g. in `vi`\n    * or `bg` keeps running in background e.g. for killing pods\n* `tmux` - first things in an exam: edit `bashrc` (see above), then start `tmux`\n\t* split pane, preferable horizontal (`ctrl`+`b`+`\"`) (easier for copying with mouse)\n\t* move from pane to pane using `ctrl`+`b` + cursor keys\n\t* select mode (scrolling) `ctrl`+`b` + `]` - then use search or cursor keys or page up/down for navigating\n\t  Careful: `ctrl`+`w` might close tab. Better use mouse for copying.\n\t* search: in select mode `ctrl`+`b`+`s` or `r` for reverse\n\t  `n` for next hit; `Shift+n` for previous hit\n\t* increase size of pane by keeping `ctrl`+`b` pressed and using cursor keys\n    * `ctrl`+`z` to toggle full screen for a pane\n* `vim`\n\t* `w` write, don't quit. Hints:\n      * use other tmux pane to run `ka`, then come back to fix potential syntactic errors\n      * or use `ctrl` + `z` to send `vim` to background, run `ka` then `fg` to return to `vim` \n    * `q` quit, can be combined to `wq` \n\t* `y`  = yank = copy\n\t* `p` = paste\n\t* `d` = delete = cut. If you want to delete more lines just to, e.g. `dddd`\n    * `u` = undo\n\t* redo: `ctrl` + `r`\n\t* `v` = visual (select), use cursor keys, then `y` or `p`\n\t* indent: select then `\u003e` or `\u003c` (repeat with `.`)\n* `less`\n\t* switch search to case-insensitive using `:i`\n\t* search using `/`\n* `ssh` / `scp`, to access or copy files to/from nodes\n* `cut --delimiter ' ' --fields 9 # delimiter space, print field 9`\n\n# Know your tools and technologies\n\n* curl\n    * Validate certificate: `curl -vk 2\u003e\u00261  https://xyz | grep -i subject`\n    * [Accessing the Kubernetes API from a Pod](https://kubernetes.io/docs/tasks/run-application/access-api-from-pod/)\n      Note the path to the secrets\n```bash\nk run debug-node --rm -it --image alpine --\n'curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\" -X GET ${APISERVER}/api/v1/namespaces/default/secrets'\n```\n* `kube-apiserver`, `kubelet`, etc.\n    *  interne YAMLs konfigurierbar:\n    * `/etc/kubernetes/manifests`\n    * `/etc/kubernetes/manifests/kube-apiserver.yaml`\n    * `/etc/kubernetes/manifests/kube-controller-manager.yaml`\n    * `/var/lib/kubelet/config.yaml`\n    * apiserver is automatically restarted when `kube-apiserver.yaml` is changed.  \n      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\n```shell\n#SystemD\nsystemctl status kubelet\nsystemctl restart kubelet\n# or system V\nservice kubelet restart\nservice kubelet status\n```\n* [AppArmor](https://kubernetes.io/docs/tutorials/security/apparmor/)\n    * 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\n    * `container.apparmor.security.beta.kubernetes.io/\u003ccontainer_name\u003e: \u003cprofile_ref\u003e`\n    * `container.apparmor.security.beta.kubernetes.io/c1: localhost/very-secure`\n    * or `runtime/default`\n    * Profile must be present on node\n    * Accessing [App Armor Docs](https://gitlab.com/apparmor/apparmor/-/wikis/Documentation) ist permitted\n    * See [k8s docs](https://kubernetes.io/docs/tutorials/security/apparmor/) for an example\n```shell\napparmor_parser -q \u003c\u003cEOF\nEOF\n# or\nscp profile.txt node:/tmp/profile.txt\n#then\napparmor_parser -q profile.txt\n# optional check\napparmor_status\n# or just load it again\napparmor_parser -q profile.txt # Output profile alrady exists\n```\n* [Seccomp](https://kubernetes.io/docs/tutorials/security/seccomp/)\n    * Kubernetes lets you automatically apply seccomp profiles loaded onto a node to your Pods and containers.\n    * [Enable the use of `RuntimeDefault` as the default seccomp profile for all workloads](https://kubernetes.io/docs/tutorials/security/seccomp/#enable-the-use-of-runtimedefault-as-the-default-seccomp-profile-for-all-workloads)\n      run the kubelet with the `--seccomp-default` [command line flag](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet)\n      in `/var/lib/kubelet/config.yaml` as in [this example](https://github.com/moabukar/CKS-Exercises-Certified-Kubernetes-Security-Specialist/blob/main/7-mock-exam-questions/Q5-Seccomp.md#2---change-the-seccomp-profile-by-adding-the-below-argument-in-the-kubelet-config-file) then `systemctl restart kubelet`\n    * Set default profile or an explicit one as shown in docs\n```yaml\n  securityContext:\n    seccompProfile:\n      type: RuntimeDefault\n# or\n  securityContext:\n    seccompProfile:\n      type: Localhost\n      localhostProfile: profiles/audit.json\n```\n* [PSA](https://kubernetes.io/docs/concepts/security/pod-security-admission/)\n    * PSAs are set namespace-wide\n    * Try out e.g. this example: [Apply predefined Pod-level security policies using PodSecurity  |  Google Kubernetes Engine (GKE)  |  Google Cloud](https://cloud.google.com/kubernetes-engine/docs/how-to/podsecurityadmission)\n    * `kubectl label --overwrite ns restricted-ns pod-security.kubernetes.io/enforce=restricted`\n    * `kubectl label --overwrite ns baseline-ns pod-security.kubernetes.io/warn=baseline`\n* Falco\n    * Might log to syslog -\u003e `cat /var/log/syslog | grep -i xyz` or `journalctl -fu falco | grep \"xyz error\"`\n    * Output UID and Container ID: `%user.uid,%container.id` see [supported fields doc](https://falco.org/docs/reference/rules/supported-fields/) (allowed in exam!)\n```yaml\nrules_file:\n  - /etc/falco/falco_rules.yaml\n  - /etc/falco/falco_rules.local.yaml\n  - /etc/falco/rules.d # custom rules\n```\n* Tracee\n  similar to falco, ebpf kernel events, signatures tigger alert.\n* Trivy\n    * `trivy image alpine --severity=HIGH,CRITICAL`\n* Kubesec\n    * `kubesec scan k8s-deployment.yaml | jq`\n    * `kubesec scan jenkins/tmp-docker-gid-grepper.yaml | jq '.[].scoring.advise'`\n```yaml\napiVersion: v1\nkind: Pod\nspec:\n  enableServiceLinks: false\n  automountServiceAccountToken: false\n  containers:\n  - name: restricted\n    securityContext:\n      runAsNonRoot: true\n      runAsUser: 100000\n      runAsGroup: 100000\n      allowPrivilegeEscalation: false\n      readOnlyRootFilesystem: true\n      seccompProfile:\n        type: RuntimeDefault\n      capabilities:\n        drop:\n        - ALL\n```\n*  Kube-bench\n\t* Has to run on node! Either operator, pod or binary on node\n\t* `kube-bench run --targets=master \u003e bench.txt`\n\t* `kube-bench run --targets=node \u003e bench.txt`\n\t* Using `--target` makes solving specific tasks much easier because there usually are a lot of results\n\t* Writing to file allows for comparing the results after mitigation.\n\t* `kube-bench run --targets=master | less` also works\n* crictl, similar to `docker` but for CRI\n```shell\ncrictl pods\ncrictl ps\n\ncrictl ps --pod $podid # all containers of pod, also works with grep $podid\ncrictl logs $containerid # see output of crcitcl ps --pod for $containerid\ncrictl rmp $podid #remove pod\n```\n* `etcdctl`: Access secrets directly: (command can be found in docs for [encryption at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)):\n```shell\n  ETCDCTL_API=3 etcdctl \\\n   --cacert=/etc/kubernetes/pki/etcd/ca.crt   \\\n   --cert=/etc/kubernetes/pki/etcd/server.crt \\\n   --key=/etc/kubernetes/pki/etcd/server.key  \\\n   get /registry/secrets/default/secret1 | hexdump -C\n```\n* `strace`\n  Count time, calls, and errors for each system call and report a summary on program exit:\n  `strace -p pid -c`\n  or ongoing output, e.g. in separate tmux pane/window `strace -p pid 2\u003e\u00261 | grep -i kill`\n  e.g. syscalls of container\n```shell\ncrictl pods # -\u003e POD_ID\ncritctl ps --pod POD_ID # -\u003e CONTAINER_ID\ncrictl inspect CONTAINER_ID | grep -i pid # -\u003e PID\nstrace -p PID -c\n# Ctrl + C \n#% time     seconds  usecs/call     calls    errors syscall\n#------ ----------- ----------- --------- --------- ---------------\n# 81,08    0,000030          30         1         1 rt_sigtimedwait\n# 18,92    0,000007           3         2           wait4\n#------ ----------- ----------- --------- --------- ----------------\n#100,00    0,000037          12         3         1 total\n```\n* OPA [conftest](https://www.conftest.dev/)\n    * `conftest test some.yaml`\n    * looks for policies in folder `policy`\n* OPA [Gatekeeper](https://open-policy-agent.github.io/gatekeeper/website/)\n    *  OPA = general purpose policy engine; Gatekeeper = kubernetes-specific impl of OPA as K8s Admission controller\n    * `ConstraintTemplate` -\u003e describe rego\n    * `Constraint` -\u003e describes matching rules, parameters, etc., lists violations\n        * Violations of constraints are listed in the `status` field of the corresponding constraint\n        * The audit pod emits JSON-formatted audit logs to stdout.\n        * Prometheus Metrics (not relevant for CKS)\n    * [example](https://open-policy-agent.github.io/gatekeeper/website/docs/howto):\n```yaml\napiVersion: templates.gatekeeper.sh/v1\nkind: ConstraintTemplate\nmetadata:\n  name: k8srequiredlabels\n---\napiVersion: constraints.gatekeeper.sh/v1beta1\nkind: K8sRequiredLabels\nmetadata:\n  name: ns-must-have-gk\nspec:\n  enforcementAction: dryrun # deny|warn\n```\n\n```sh\n# from killer.sh\n## Question 7\nk get crd | grep gatekeeper\nk edit blacklistimages pod-trusted-images # constraint: add parameter\nk edit constrainttemplates blacklistimages #-\u003e template: change rego expression\n\n## Preview Question 2\n# constraint, add parameter for namespace\nk edit requiredlabels namespace-mandatory-labels\n# template, fix rego\nk edit constrainttemplates requiredlabels\n``` \n* `dmesg` - prints kernel logs\n* `kubeadm`\n```shell\n# control plane\nk drain $NODE\n# ssh to master\napt update \u0026\u0026 apt install kubeadm=1.29.0-1.1 # if necessary\nkubeadm upgrade plan # outputs commands for apply\nkubeadm upgrade apply v1.24.1 #use specific version! Outputs message to upgrade kubelet\napt install kubelet=1.29.0-1.1 kubectl=1.29.0-1.1\nservice kubelet restart #systemctl restart kubelet\nk uncordon $NODE\n\n# node: drain, ssh\napt update \u0026\u0026 apt install kubeadm=1.29.0-1.1\nkubeadm upgrade node\nservice kubelet restart\n# exit, k uncordon\n```\n* sha512sum\n```bash\n  sha512sum -c FILE # can contain all sums and binaries\n  # FILE\n  #SUM1  /a/file\n  #SUM2  another-file\n  # or indivudal files\n  sha512sum -c \u003c\u003c\u003c \"$1  $2\"\n```\n\n* You might want to install helpful software. Not sure if it is allowed, though\n    * `apt install bat`-\u003e binary is called `batcat` - syntax highlighted YAML files\n    * or `tldr` if you need examples for using binaries\n      or `curl cheat.sh/cut`\n\n# Be thorough\n\n* Switch to the correct kubecontext first (there is a command to copy at the beginning of each question)\n* Read questions carefully! There a several subtasks.\n* Read again when done to see if you did not miss anything.  \n* Validate your work, e.g. `k get node`, `k get pod`, `k exec -it ...`\n* Double check if you wrote the result to the right file\n  * Sometimes it has to be written to a file on the main host\n  * Sometimes it has to be written to a file on a node\n  * Sometimes it is not necessary to write a result\n* Every exercise features links to the relevant docs in the header. Have a look a them before searching in the docs first!\n* Copy each YAML before editing to your home folder, to be able to reset after possibly messing it up.  \n  Don't copy it to the folder of the original file, this might confuse a running api server, for example.\n\nIn both my killer.sh tries I missed some points.  \nEven 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.  \nDon't do that, be thorough!\n\n# Don't give up\n\n* You are going to need every point to can score and every second you're granted\n* If some tasks might seem to difficult, flag them and tackle them again at the end\n* Having only one or two minutes left is enough time to score some points by partially solving some question\n* You'll be surprised how fast you can learn to solve tasks under pressure\n* If you don't know how to solve, start by reading the docs linked at the top\n* You don't need to solve the whole question, partial solutions score points as well\n* You never know, a partial solution saved in the last seconds might be the one point you need for the 70% passing score!\n\nDon't give up until you're kicked out of the exam 💪","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschnatterer%2Fcks-short-tips","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschnatterer%2Fcks-short-tips","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschnatterer%2Fcks-short-tips/lists"}