World map

 

BM: Baca dalam Bahasa Melayu

World K6: Guards

Capstone mission 5: Guard it

You will learn: to give Kedai Kancil badges, locks, fences and seals, then prove the cluster refuses a root or unsigned image.

Checked with Kubernetes 1.37 on 31 Oct 2026

The problem

You are here: cluster kind-dev namespace default
A dry run of a root nginx pod in the kedai zone is forbidden: it violates PodSecurity restricted. Terminal output: $ kubectl apply -f root.yaml --dry-run=server Error from server (Forbidden): error when creating "root.yaml": pods "root-test" is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "web" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "web" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "web" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "web" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")

Mission 5: Guard it. Your goal: your own cluster refuses a root or unsigned image, like this. Four jobs: badges, locks, fences, seals.

Try it

Step 1: badges and locks. kubectl can write the YAML for you with --dry-run=client -o yaml.

Real mission

  1. kubectl create serviceaccount ci-bot -n kedai --dry-run=client -o yaml > k8s/base/rbac.yaml
  2. echo "---" >> k8s/base/rbac.yaml && kubectl create role deployer -n kedai --verb=get,list,patch --resource=deployments --dry-run=client -o yaml >> k8s/base/rbac.yaml
  3. echo "---" >> k8s/base/rbac.yaml && kubectl create rolebinding ci-bot-deployer -n kedai --role=deployer --serviceaccount=kedai:ci-bot --dry-run=client -o yaml >> k8s/base/rbac.yaml
  4. kubectl label --dry-run=server --overwrite ns kedai pod-security.kubernetes.io/enforce=restricted
  5. kubectl auth can-i get secrets -n kedai --as=system:serviceaccount:kedai:ci-bot

0 of 8 steps done · Your ticks are saved.

Watch

Your kedai zone will carry two guard labels. One checks locks. One checks seals.

Tap the label that refuses a root tray.

0 of 1 found

Try it

Step 2: fences and seals. The seal commands come from GitHub’s guide, written for Helm 4.

Real mission

  1. kubectl run probe --rm -it --restart=Never --image=busybox:1.37 -- wget -qO- -T 2 http://api.kedai
  2. helm upgrade policy-controller --install --rollback-on-failure --create-namespace --namespace artifact-attestations oci://ghcr.io/sigstore/helm-charts/policy-controller --version 0.10.5
  3. helm upgrade trust-policies --install --rollback-on-failure --namespace artifact-attestations oci://ghcr.io/github/artifact-attestations-helm-charts/trust-policies --version v0.7.0 --set policy.enabled=true --set policy.organization=YOUR-NAME
  4. kubectl label namespace kedai policy.sigstore.dev/include=true

0 of 8 steps done · Your ticks are saved.

Check

Let GitHub’s public API confirm your files. Type your username, then check.

Check it on GitHub

Your username is sent only to api.github.com.

  • Your Kedai Kancil repo is publicNot checked yet
  • It has k8s/base/rbac.yamlNot checked yet
  • It has k8s/base/networkpolicy.yamlNot checked yet

Check

The API can’t see inside your cluster. Check these yourself.

Real mission

  1. kubectl auth can-i patch deployments -n kedai --as=system:serviceaccount:kedai:ci-bot
  2. kubectl run root-test -n kedai --image=nginx:1.29-alpine --dry-run=server

0 of 4 steps done · Your ticks are saved.

You did it!

You can now guard Kedai Kancil with badges, locks, fences and seals.

Go deeper (optional)

Safety: use your kind cluster only, never a work cluster. Read the pink “you are here” bar before each label or delete. Stuck pods? Run kubectl get events -n kedai. Kyverno or Gatekeeper can check seals too, if your team already uses one.