Skip to content
Published on

CKS (Certified Kubernetes Security Specialist) Complete Practice Exam

Authors

1. CKS Exam Overview

The CKS (Certified Kubernetes Security Specialist) is an advanced Kubernetes security certification offered by CNCF and the Linux Foundation.

ItemDetails
Exam Duration120 minutes
Question Type15-20 performance-based practical tasks
Passing Score67% or higher
PrerequisitesActive CKA certification
Exam EnvironmentRemote proctored, browser-based terminal
Validity2 years

Domain Weights

DomainWeight
Cluster Setup10%
Cluster Hardening15%
System Hardening15%
Minimizing Microservice Vulnerabilities20%
Supply Chain Security20%
Monitoring, Logging and Runtime Security20%

2. Key Kubernetes Security Concepts

2.1 RBAC (Role-Based Access Control)

RBAC is the core mechanism for controlling Kubernetes API access. Roles/ClusterRoles define permissions; RoleBindings/ClusterRoleBindings bind those permissions to subjects (users, groups, service accounts).

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
  - apiGroups: ['']
    resources: ['pods']
    verbs: ['get', 'watch', 'list']

2.2 Pod Security Standards (PSS)

ProfileDescription
PrivilegedNo restrictions, all permissions allowed
BaselineMinimal restrictions, prevents known privilege escalation
RestrictedStrong security policies, enforces best practices

2.3 Network Policy

NetworkPolicy controls traffic between Pods at L3/L4. By default all traffic is allowed; once a NetworkPolicy is applied, only explicitly permitted traffic flows.

2.4 Falco Runtime Security

Falco monitors kernel system calls to detect runtime threats. It fires alerts based on rules that describe suspicious activity.

2.5 Supply Chain Security

  • Image Scanning: Trivy, Snyk for CVE detection
  • Image Signing: Cosign for signing and verification
  • SBOM: Software Bill of Materials
  • Admission Controllers: ImagePolicyWebhook for image policy enforcement

3. Practice Questions (Q1-Q55)

Cluster Setup (Q1-Q10)

Q1. On which standard does kube-bench base its Kubernetes cluster security checks?

A) NIST SP 800-190 B) CIS Kubernetes Benchmark C) PCI DSS D) ISO 27001

Answer: B

Explanation: kube-bench automatically audits cluster component configurations against the CIS (Center for Internet Security) Kubernetes Benchmark. It checks master nodes, worker nodes, etcd, and the API server.

Q2. Where do you configure encryption at rest for etcd data?

A) --etcd-encryption-key flag in /etc/kubernetes/manifests/kube-apiserver.yaml B) Write /etc/kubernetes/encryption-config.yaml and reference it with kube-apiserver's --encryption-provider-config C) --cipher-suites flag on etcd D) --encrypt-data flag on kubelet

Answer: B

Explanation: etcd at-rest encryption is enabled by writing an EncryptionConfiguration YAML and pointing kube-apiserver's --encryption-provider-config flag to it. You configure encryption providers (aescbc, aesgcm, secretbox, etc.) for specific resource types such as Secrets and ConfigMaps.

Q3. Where should TLS certificates and keys be stored when configuring Kubernetes Ingress with TLS?

A) ConfigMap B) Secret (type: kubernetes.io/tls) C) PersistentVolume D) ServiceAccount token

Answer: B

Explanation: TLS certificates and private keys are stored in a Secret of type kubernetes.io/tls, with tls.crt for the certificate and tls.key for the private key, both base64-encoded. The Ingress resource references this Secret in its spec.tls section.

Q4. In a cloud environment, what is the best way to prevent Pods from directly accessing the Instance Metadata Service (IMDS)?

A) Block 169.254.169.254 with NetworkPolicy B) Set hostNetwork: true on the Pod C) Disable ServiceAccount automount D) Disallow hostPID in PSP

Answer: A

Explanation: AWS IMDSv1 allows unauthenticated access to 169.254.169.254 to steal IAM credentials. Block outbound egress to that IP with NetworkPolicy, or upgrade to IMDSv2 and set the hop limit to 1, preventing containers from reaching the metadata endpoint directly.

Q5. Which NetworkPolicy selector allows only Pods from a specific namespace?

A) podSelector B) namespaceSelector C) ipBlock D) serviceSelector

Answer: B

Explanation: namespaceSelector matches namespaces by label, allowing traffic only from Pods in those namespaces. Combined with podSelector you can permit only specific Pods within a specific namespace.

Q6. When fixing a [FAIL] item from kube-bench, what should you do first?

A) Immediately restart the cluster B) Read the remediation section for that finding C) Create a new cluster D) Delete etcd backups

Answer: B

Explanation: Each kube-bench [FAIL] item includes a remediation section with specific commands or configuration changes to fix the issue. Always review it carefully before applying changes.

Q7. Which kube-apiserver flag disables anonymous authentication?

A) --anonymous-auth=false B) --disable-anonymous=true C) --allow-anonymous=false D) --auth-anonymous=disabled

Answer: A

Explanation: Setting --anonymous-auth=false on kube-apiserver prevents unauthenticated requests from being treated as the system:anonymous user, causing them to be rejected instead.

Q8. Which combination of etcd flags enables TLS for peer communication?

A) --peer-cert-file, --peer-key-file, --peer-trusted-ca-file B) --tls-cert-file, --tls-key-file C) --client-cert-auth, --trusted-ca-file D) --peer-auth=tls

Answer: A

Explanation: etcd peer TLS requires --peer-cert-file (peer certificate), --peer-key-file (peer private key), and --peer-trusted-ca-file (peer CA certificate). Adding --peer-client-cert-auth=true also enforces mutual peer authentication.

Q9. What information does the RequestResponse audit log level capture?

A) Event metadata only B) Request metadata and request body C) Metadata, request body, and response body D) Response body only

Answer: C

Explanation: The four audit levels are None, Metadata, Request, and RequestResponse. RequestResponse is the most verbose; it captures all of: event metadata, request body, and response body. This provides the most detail but also generates the most data and storage cost.

Q10. What admission controllers does CIS Benchmark recommend enabling on kube-apiserver?

A) AlwaysAllow B) NodeRestriction and PodSecurityAdmission among others C) AlwaysDeny D) LimitRanger only

Answer: B

Explanation: CIS Benchmark recommends enabling security-hardening admission controllers: NodeRestriction (limits nodes to modifying only their own resources), PodSecurityAdmission (enforces PSS policies), ResourceQuota, LimitRanger, and others.

Cluster Hardening (Q11-Q22)

Q11. How do you prevent a ServiceAccount token from being automatically mounted into a Pod?

A) Set automountServiceAccountToken: false on the ServiceAccount B) Set serviceAccountName: none in the Pod spec C) Delete the serviceaccount resource with RBAC D) Delete the Secret

Answer: A

Explanation: Setting automountServiceAccountToken: false on the ServiceAccount or the Pod spec prevents automatic token mounting. The Pod-level setting overrides the ServiceAccount-level setting.

Q12. What is the correct approach when configuring RBAC following the Principle of Least Privilege?

A) Bind cluster-admin ClusterRole to all ServiceAccounts B) Create custom Roles with only the required resources and verbs C) Disable RBAC and use ABAC instead D) Use wildcards (*) for all resources

Answer: B

Explanation: The Principle of Least Privilege requires granting only the minimum permissions necessary. Create custom Roles with specific namespaces, resources, and verbs, and bind them only to the subjects that need them.

Q13. Which kubelet flags should be set to harden kubelet authentication?

A) --authentication-token-webhook=true, --authorization-mode=Webhook B) --anonymous-auth=true C) --read-only-port=10255 D) --allow-all-requests=true

Answer: A

Explanation: To harden kubelet: set --anonymous-auth=false to block anonymous access, --authentication-token-webhook=true to enable token webhook authentication, and --authorization-mode=Webhook so the API server handles authorization.

Q14. Why does the Kubernetes version upgrade cadence matter for security?

A) To add new features B) To apply CVE patches and security fixes C) To improve performance D) For kubectl version compatibility

Answer: B

Explanation: Kubernetes releases a minor version approximately every 4 months, with each version supported for about 14 months. Running outdated versions leaves known CVEs (Common Vulnerabilities and Exposures) unpatched, increasing security risk. CKS recommends staying on a supported version.

Q15. Why is the following ClusterRoleBinding dangerous?
subjects:
  - kind: Group
    name: system:authenticated
roleRef:
  kind: ClusterRole
  name: cluster-admin

A) The subjects field is wrong B) It grants cluster-admin to every authenticated user C) The ClusterRoleBinding has no name D) The apiGroup is missing

Answer: B

Explanation: The system:authenticated group includes every authenticated user in the cluster. Binding cluster-admin to it gives maximum privileges to everyone who can authenticate. Similarly, granting permissions to system:unauthenticated is extremely dangerous.

Q16. How do you record only mutating verbs (create/update/delete) in an Audit Policy while excluding get/list?

A) Specify only the desired verbs in the rules' verbs field B) Use the resourceNames field C) Filter by namespace field D) Set level to None

Answer: A

Explanation: Use the verbs field in Audit Policy rules to log only specific HTTP verbs. For example, verbs: ["create", "update", "delete", "patch"] records only write operations in the audit log.

Q17. How do you disable the kubelet read-only port (default 10255)?

A) --read-only-port=0 B) --disable-readonly=true C) --secure-port=0 D) --port=0

Answer: A

Explanation: Setting --read-only-port=0 disables the unauthenticated HTTP read-only port (default 10255) on kubelet. This port exposes Pod information and metrics without authentication, so disabling it is a security best practice.

Q18. Which is the best practice for applying least privilege to ServiceAccounts?

A) All Pods use the default ServiceAccount B) Create a dedicated ServiceAccount per application with only the required permissions C) Grant cluster-admin to all ServiceAccounts D) Use file-based access control instead of RBAC

Answer: B

Explanation: Create a dedicated ServiceAccount per workload and bind a Role that permits only the specific resources and verbs that application actually needs. Sharing the default ServiceAccount risks over-provisioning permissions.

Q19. What is the correct security setting for kube-apiserver's --insecure-port flag?

A) Set to 8080 B) Set to 0 to disable it C) Change to 443 D) Add a TLS certificate

Answer: B

Explanation: Setting --insecure-port=0 disables the unauthenticated HTTP port. This flag is deprecated since Kubernetes 1.20 with a default of 0, but explicitly setting it to 0 is the CIS Benchmark recommendation.

Q20. What does Node Authorization mode do?

A) Allows all users to access any node B) Restricts kubelets to accessing only resources needed by the Pods running on their node C) Encrypts inter-node network communication D) Controls OS-level access on nodes

Answer: B

Explanation: Node Authorization limits kubelet API server requests to only the resources (Secrets, ConfigMaps, PersistentVolumes, etc.) needed by Pods scheduled on that kubelet's node. Using --authorization-mode=Node,RBAC together is recommended.

Q21. What is the correct order for issuing a user certificate via CertificateSigningRequest (CSR)?

A) Create CSR → approve → create CSR object → extract certificate B) Generate private key → create CSR file → create CSR object → approve → extract certificate C) Sign directly with CA → configure kubeconfig D) Use ServiceAccount token

Answer: B

Explanation: The correct order is: 1) Generate a private key with openssl, 2) Create a CSR file, 3) Base64-encode and create a CertificateSigningRequest object, 4) Approve with kubectl certificate approve, 5) Extract the certificate with kubectl get csr -o jsonpath='{.status.certificate}'.

Q22. What is kubectl auth can-i used for?

A) Renewing cluster certificates B) Checking whether a specific user/ServiceAccount can perform a specific action C) Applying RBAC rules D) Reviewing audit logs

Answer: B

Explanation: Use it as kubectl auth can-i get pods --namespace default to verify whether the current user can perform an action. The --as flag lets you impersonate another user. This is invaluable for validating RBAC configurations.

System Hardening (Q23-Q32)

Q23. What is the annotation format for applying an AppArmor profile to a Pod?

A) security.alpha.kubernetes.io/apparmor: runtime/default B) container.apparmor.security.beta.kubernetes.io/CONTAINER_NAME: localhost/PROFILE_NAME C) apparmor.kubernetes.io/profile: enforced D) securityContext.appArmorProfile: localhost/custom

Answer: B

Explanation: Before Kubernetes 1.30, AppArmor was applied with the annotation container.apparmor.security.beta.kubernetes.io/containerName: localhost/profileName. From 1.30 onward use the securityContext.appArmorProfile field. The profile must be pre-loaded on the node.

Q24. How do you apply the RuntimeDefault Seccomp profile to a Pod?

A) Set only via Pod annotation B) securityContext.seccompProfile.type: RuntimeDefault C) Create a separate CRD D) Can only be set at the Node level

Answer: B

Explanation: Since Kubernetes 1.19, use the securityContext.seccompProfile field. type: RuntimeDefault uses the container runtime's default Seccomp profile; type: Localhost allows a custom profile.

Q25. Which tools harden OS-level security for processes running inside containers?

A) NetworkPolicy B) RBAC C) AppArmor, Seccomp D) PodDisruptionBudget

Answer: C

Explanation: AppArmor enforces MAC (Mandatory Access Control) restricting which files, network, and capabilities a process can access. Seccomp restricts which system calls a process can invoke. Both operate at the OS level to limit container process behavior.

Q26. Which command is appropriate for identifying unnecessary services and open ports on a node?

A) kubectl describe node B) ss -tlnp or netstat -tlnp C) docker ps D) journalctl -u kubelet

Answer: B

Explanation: ss -tlnp (socket statistics) or netstat -tlnp shows which TCP ports are listening on the node and the corresponding processes. Any unnecessary services found should be disabled or removed.

Q27. Which securityContext setting removes Linux capabilities from a container?

A) securityContext.privileged: false B) securityContext.capabilities.drop: ["ALL"] C) securityContext.runAsRoot: false D) securityContext.allowPrivilegeEscalation: false

Answer: B

Explanation: securityContext.capabilities.drop: ["ALL"] removes all Linux capabilities, then capabilities.add selectively re-adds only what is needed. Using this with allowPrivilegeEscalation: false provides strong hardening.

Q28. How do you apply a RuntimeClass that uses gVisor (runsc) to a Pod?

A) spec.runtimeClassName: gvisor B) spec.securityContext.runtime: gvisor C) Set via annotation D) Automatically selected by Node label

Answer: A

Explanation: First create a RuntimeClass object with handler: runsc, then reference it in the Pod spec's runtimeClassName field. gVisor implements a user-space kernel, sandboxing the container from the host kernel.

Q29. What is the recommended way to grant IAM permissions to a Pod on AWS (IRSA)?

A) Grant all permissions to the node IAM role B) Store access key / secret key in a Secret C) Connect an IAM Role to a ServiceAccount via OIDC Provider and annotation D) Use only EC2 instance profiles

Answer: C

Explanation: IRSA (IAM Roles for Service Accounts) uses the EKS OIDC Provider to link Kubernetes ServiceAccounts with IAM Roles. Adding the eks.amazonaws.com/role-arn annotation to a ServiceAccount grants that IAM role only to Pods using that SA.

Q30. Which securityContext field makes a container's filesystem read-only?

A) securityContext.immutable: true B) securityContext.readOnlyRootFilesystem: true C) securityContext.noWrite: true D) volumeMounts.readOnly: true

Answer: B

Explanation: securityContext.readOnlyRootFilesystem: true makes the container's root filesystem read-only, preventing attackers from creating malicious files or tampering with binaries. Paths that need write access should be mounted as emptyDir volumes.

Q31. Which setting forces a container not to run as root?

A) securityContext.runAsUser: 0 B) securityContext.runAsNonRoot: true C) securityContext.privileged: false D) Control via RBAC

Answer: B

Explanation: securityContext.runAsNonRoot: true causes Kubernetes to reject the container if it tries to run as root (UID 0). Specifying runAsUser: 1000 (or another non-zero UID) is also a good practice.

Q32. What is a key characteristic of Kata Containers?

A) Shared-kernel container isolation like standard containers B) Each container/Pod runs on a lightweight VM with its own independent kernel C) Only provides network isolation D) Seccomp profile-based isolation

Answer: B

Explanation: Kata Containers runs each container (or Pod) on a lightweight VM. Each workload has its own independent kernel, making kernel-exploit container escapes extremely difficult. Unlike gVisor, Kata uses a real Linux kernel.

Minimizing Microservice Vulnerabilities (Q33-Q42)

Q33. What is the difference between enforce and warn modes in Pod Security Admission (PSA)?

A) No difference B) enforce rejects policy-violating Pods; warn allows them but shows a warning C) warn is stricter D) enforce applies retroactively to existing Pods

Answer: B

Explanation: Among PSA's three modes: enforce rejects Pods that violate the policy. warn returns a warning message but still creates the Pod. audit logs a violation but also allows the Pod.

Q34. What do OPA Gatekeeper and Kyverno have in common?

A) They use the same policy language B) Both operate as Kubernetes admission webhooks to enforce policies C) They are runtime monitoring tools D) They manage network policies

Answer: B

Explanation: Both OPA Gatekeeper and Kyverno work as Kubernetes ValidatingAdmissionWebhooks; they inspect resources at creation/modification time and reject violations. Gatekeeper uses the Rego language; Kyverno uses YAML-based policies.

Q35. What is the benefit of enabling mTLS (mutual TLS) in a service mesh like Istio?

A) Performance improvement B) Bidirectional authentication and encryption of service-to-service communication C) Blocking external traffic D) Database encryption

Answer: B

Explanation: mTLS requires both client and server to authenticate each other with certificates. Setting PeerAuthentication to STRICT mTLS in Istio encrypts all service-to-service traffic and allows only authenticated services to communicate, preventing lateral movement attacks.

Q36. Which is NOT a secure way to manage Kubernetes Secrets?

A) Enable etcd at-rest encryption B) Use Vault or Sealed Secrets C) Store Secrets in plaintext in a Git repository D) Restrict Secret access with RBAC

Answer: C

Explanation: Storing Secrets in plaintext in Git is extremely dangerous. Correct approaches include etcd encryption, Bitnami Sealed Secrets (encrypted SealedSecrets committed to Git), HashiCorp Vault (dynamic secret management), and AWS Secrets Manager integration.

Q37. Which setting violates the Restricted Pod Security Standard?

A) runAsNonRoot: true B) seccompProfile.type: RuntimeDefault C) privileged: true D) capabilities.drop: ["ALL"]

Answer: C

Explanation: Restricted PSS is the strictest profile; it forbids privileged: true, hostNetwork, hostPID, hostIPC, adding certain capabilities, and requires runAsNonRoot. Only the Privileged PSS profile permits privileged: true.

Q38. Why was PodSecurityPolicy (PSP) deprecated and what replaced it?

A) Performance issues; replaced by RuntimeClass B) Complexity and privilege escalation risk; replaced by Pod Security Admission C) Insufficient features; replaced by OPA D) etcd compatibility issues

Answer: B

Explanation: PSP was deprecated in Kubernetes 1.21 and removed in 1.25. Using PSP required granting a use ClusterRole to services, which created privilege escalation vectors and was complex to configure. It was replaced by Pod Security Admission (PSA); OPA Gatekeeper and Kyverno are also commonly used.

Q39. Which of the following is NOT a container sandboxing technology?

A) gVisor B) Kata Containers C) Firecracker D) Calico

Answer: D

Explanation: gVisor, Kata Containers, and Firecracker are all sandboxing technologies that enhance container isolation. Calico is a CNI network plugin that implements network policies; it is not a sandboxing technology.

Q40. What is the purpose of Istio's AuthorizationPolicy?

A) Automatic certificate renewal B) Service-to-service access control (defining who can make requests to whom) C) Traffic load balancing D) Container image scanning

Answer: B

Explanation: Istio AuthorizationPolicy implements L7-level access control within the service mesh. It defines which services/users may access specific services, paths, and methods. Combined with mTLS it enables Zero Trust networking.

Q41. What is the security risk of using a Secret as an environment variable?

A) Performance degradation B) Exposed in the process environment and readable via /proc/PID/environ, or accidentally logged C) Size limitation D) Type restriction

Answer: B

Explanation: Environment variables can be read through /proc/PID/environ and may be accidentally printed in application logs. Volume mount injection is safer; tools like Vault Agent Injector or the CSI Secret Store provider are recommended.

Q42. How is a Zero Trust security model implemented in Kubernetes?

A) Use only a firewall B) Combination of mTLS + RBAC + NetworkPolicy + PSA C) Use only a VPN D) Physical network separation

Answer: B

Explanation: Zero Trust follows the principle "never trust, always verify." In Kubernetes this is achieved by combining mTLS (service-to-service authentication), RBAC (least privilege), NetworkPolicy (network micro-segmentation), and PSA (workload security standards).

Supply Chain Security (Q43-Q52)

Q43. What is the correct command to scan a container image with Trivy?

A) trivy scan IMAGE_NAME B) trivy image IMAGE_NAME C) trivy check IMAGE_NAME D) trivy docker IMAGE_NAME

Answer: B

Explanation: Use trivy image nginx:latest. The trivy image subcommand scans OS packages and language-specific dependencies for CVEs. Use --severity HIGH,CRITICAL to filter by severity.

Q44. What does the ImagePolicyWebhook admission controller do?

A) Automatically updates images to the latest version B) Queries an external webhook service about whether an image is allowed C) Automatically fixes image vulnerabilities D) Restricts image size

Answer: B

Explanation: ImagePolicyWebhook queries an external webhook service at Pod creation time to determine if an image is permitted. The webhook service can base its decision on scan results, signature verification, registry policies, and more.

Q45. What is the correct Cosign command to sign a container image?

A) cosign sign --key cosign.key IMAGE_DIGEST B) cosign create-signature IMAGE C) docker sign IMAGE D) kubectl sign image IMAGE

Answer: A

Explanation: Use cosign sign --key cosign.key IMAGE@sha256:DIGEST. Signatures are stored in the OCI registry as a separate tag. Verify with cosign verify --key cosign.pub IMAGE. A Kyverno policy can enforce that only signed images are admitted.

Q46. What is an SBOM (Software Bill of Materials)?

A) A list of software licenses B) A list of all components, libraries, and dependencies that make up a software artifact C) A software cost breakdown D) A software release plan

Answer: B

Explanation: An SBOM is an inventory of all open-source and proprietary components, versions, licenses, and vulnerability information in a software artifact. CycloneDX and SPDX are standard formats. SBOMs are essential for supply chain attack prevention and vulnerability tracking.

Q47. What is the security benefit of using distroless images?

A) Smaller image size means faster builds B) Minimizes attack surface by removing shells, package managers, and other unnecessary tools C) Available for free D) Easy CI/CD pipeline integration

Answer: B

Explanation: Distroless images contain only the runtime needed to run the application, without a shell (/bin/sh), package manager, or utilities. Even if an attacker breaks into the container there are no tools to leverage, minimizing potential damage.

Q48. How do you block Pods lacking a specific label using ValidatingWebhookConfiguration?

A) Add an RBAC rule B) The webhook service inspects the admission review request and returns a denial response C) Configure a NetworkPolicy D) Deploy a Pod deletion controller

Answer: B

Explanation: ValidatingWebhookConfiguration sends an AdmissionReview request to an external webhook service at resource create/update time. The service inspects the request and returns allowed: false with a message, which causes the Kubernetes API server to reject the resource.

Q49. Why should the latest tag not be used for container images?

A) The latest tag is deprecated B) No reproducibility — you cannot know which exact image version is running C) Wastes registry storage D) Slows down builds

Answer: B

Explanation: The latest tag is mutable; a different image can be pushed under the same tag at any time. This makes deployments non-reproducible, and an image with security vulnerabilities could be deployed as latest. Always use a SHA256 digest or a pinned version tag.

Q50. Which Kyverno policy type blocks the use of the latest tag?

A) MutatePolicy B) ClusterPolicy with validate rule C) GeneratePolicy D) SyncPolicy

Answer: B

Explanation: A Kyverno ClusterPolicy with a validate rule can deny images whose tag is latest. The deny condition checks the image tag and returns a message on violation. A mutate rule can also automatically transform image references.

Q51. Which of the following is NOT an example of a software supply chain attack?

A) SolarWinds hack B) Distribution of a malicious npm package C) DDoS attack D) Dependency confusion attack

Answer: C

Explanation: Supply chain attacks exploit vulnerabilities in the software development and delivery pipeline (SolarWinds build server compromise, malicious npm/PyPI packages, dependency confusion where a public package shadows a private one). A DDoS attack targets availability, not the supply chain.

Q52. Which Kubernetes resource provides credentials to pull images from a private container registry?

A) ServiceAccount B) imagePullSecret C) ConfigMap D) PersistentVolumeClaim

Answer: B

Explanation: Create a Secret of type docker-registry and reference it in the Pod spec's imagePullSecrets, or add it to the ServiceAccount's imagePullSecrets so all Pods using that SA authenticate automatically.

Monitoring, Logging and Runtime Security (Q53-Q55)

Q53. Which Falco condition generates an alert when a shell is executed inside a container?

A) evt.type=connect and fd.type=ipv4 B) evt.type=execve and container.id!=host and proc.name in (sh, bash, zsh) C) evt.type=open and fd.name contains /etc/passwd D) evt.type=write and fd.name startswith /tmp

Answer: B

Explanation: In Falco, the execve event type signals a new process execution. container.id!=host scopes the rule to containers, and proc.name in (sh, bash, zsh) filters for shell processes. The built-in rule "Terminal shell in container" uses this exact pattern.

Q54. How do you exclude get requests for Secrets in the kube-system namespace from the Kubernetes Audit Policy?

A) Remove the relevant rule from the audit policy B) Write a level: None rule for that resource/namespace/verb first, before other rules C) Delete the kube-system namespace D) Change the Secret type

Answer: B

Explanation: Audit Policy rules are evaluated in order, with the first matching rule applied. To skip logging certain requests with level: None, that rule must appear before any broader rule. For example, place a level: None rule for resources: secrets, namespaces: kube-system, verbs: get at the top of the policy file.

Q55. What is the correct response order when a compromised Pod is discovered?

A) Delete immediately then redeploy B) Collect evidence (logs, forensics) → isolate Pod (NetworkPolicy) → assess scope of compromise → remediate and redeploy C) Restart the node D) Redeploy the entire cluster

Answer: B

Explanation: The correct incident response order is: 1) Preserve evidence (collect logs, memory dumps), 2) Isolate the Pod with a NetworkPolicy to prevent further lateral movement, 3) Determine the attack vector and scope, 4) Fix the vulnerability, build a new image, and redeploy. Deleting immediately destroys forensic evidence.


4. Hands-On Scenarios (P1-P10)

P1. Isolating Pods with NetworkPolicy

# NetworkPolicy that allows only the backend app to reach the DB
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-allow-app-only
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: production
      podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 5432
EOF

P2. Hardening a ServiceAccount

# 1. Create a dedicated ServiceAccount with automount disabled
kubectl create serviceaccount app-sa -n default

kubectl patch serviceaccount app-sa -n default \
  -p '{"automountServiceAccountToken": false}'

# 2. Create a Role with only the required permissions
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-role
  namespace: default
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list"]
EOF

# 3. Bind the role
kubectl create rolebinding app-binding \
  --role=app-role \
  --serviceaccount=default:app-sa \
  -n default

# 4. Verify
kubectl auth can-i get configmaps \
  --as=system:serviceaccount:default:app-sa \
  -n default

P3. Configuring etcd Encryption

# 1. Generate an encryption key
head -c 32 /dev/urandom | base64

# 2. Write the EncryptionConfiguration
cat <<EOF > /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <BASE64_32BYTE_KEY>
  - identity: {}
EOF

# 3. Edit the kube-apiserver manifest
# Add: --encryption-provider-config=/etc/kubernetes/encryption-config.yaml

# 4. Re-encrypt existing Secrets
kubectl get secrets --all-namespaces -o json | kubectl replace -f -

# 5. Verify (should be unreadable)
ETCDCTL_API=3 etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  get /registry/secrets/default/my-secret

P4. Applying an AppArmor Profile

# 1. Check AppArmor status on the node
ssh worker-node-1 "aa-status"

# 2. Create a custom profile (on the node)
cat <<EOF > /etc/apparmor.d/k8s-custom-profile
#include <tunables/global>

profile k8s-custom-profile flags=(attach_disconnected) {
  #include <abstractions/base>
  file,
  deny /etc/shadow r,
  deny /proc/** w,
}
EOF

# 3. Load the profile
apparmor_parser -r /etc/apparmor.d/k8s-custom-profile

# 4. Apply to a Pod (pre-1.30 annotation style)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: secured-pod
  annotations:
    container.apparmor.security.beta.kubernetes.io/app: localhost/k8s-custom-profile
spec:
  containers:
  - name: app
    image: nginx:alpine
EOF

P5. Customizing Falco Rules

# /etc/falco/rules.d/custom-rules.yaml
- rule: Detect Shell in Container
  desc: Alert when a shell is spawned in a container
  condition: >
    spawned_process and
    container and
    proc.name in (shell_binaries)
  output: >
    Shell spawned in container
    (user=%user.name container=%container.name
    image=%container.image.repository proc=%proc.name
    parent=%proc.pname cmdline=%proc.cmdline)
  priority: WARNING
  tags: [container, shell, cks]

- rule: Sensitive File Access
  desc: Detect access to sensitive files
  condition: >
    open_read and
    (fd.name in (/etc/shadow, /etc/sudoers) or
     fd.name startswith /root/.ssh)
  output: >
    Sensitive file accessed
    (user=%user.name file=%fd.name
    container=%container.name proc=%proc.name)
  priority: CRITICAL
  tags: [filesystem, sensitive, cks]
# Restart Falco and verify rules
systemctl restart falco
falco --list | grep "Detect Shell"

P6. Configuring Pod Security Admission

# Set PSA labels on a namespace
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/warn-version=latest \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/audit-version=latest

# Pod that complies with Restricted PSS
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: restricted-pod
  namespace: production
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: nginx:alpine
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
    volumeMounts:
    - name: tmp
      mountPath: /tmp
    - name: var-cache
      mountPath: /var/cache/nginx
    - name: var-run
      mountPath: /var/run
  volumes:
  - name: tmp
    emptyDir: {}
  - name: var-cache
    emptyDir: {}
  - name: var-run
    emptyDir: {}
EOF

P7. Scanning Images with Trivy

# Scan for HIGH and CRITICAL only
trivy image --severity HIGH,CRITICAL nginx:latest

# Output as JSON
trivy image -f json -o scan-result.json nginx:latest

# Filesystem scan
trivy fs --security-checks vuln,secret /path/to/project

# Scan an entire Kubernetes cluster
trivy k8s --report summary cluster

# Fail CI/CD pipeline on CRITICAL findings
trivy image --exit-code 1 --severity CRITICAL myapp:latest

P8. Setting Up an Audit Policy

# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  # Do not log get requests for Secrets in kube-system
  - level: None
    resources:
      - group: ''
        resources: ['secrets']
    namespaces: ['kube-system']
    verbs: ['get']

  # Log all Secret access in full detail
  - level: RequestResponse
    resources:
      - group: ''
        resources: ['secrets']

  # Log Pod mutations
  - level: Request
    resources:
      - group: ''
        resources: ['pods']
    verbs: ['create', 'update', 'patch', 'delete']

  # Log metadata only for everything else
  - level: Metadata
    omitStages:
      - RequestReceived
# kube-apiserver flags to add:
# --audit-log-path=/var/log/kubernetes/audit.log
# --audit-policy-file=/etc/kubernetes/audit-policy.yaml
# --audit-log-maxage=30
# --audit-log-maxbackup=10
# --audit-log-maxsize=100

P9. Configuring a gVisor RuntimeClass

# 1. Verify gVisor in containerd config (/etc/containerd/config.toml)
# [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
#   runtime_type = "io.containerd.runsc.v1"

# 2. Create the RuntimeClass
cat <<EOF | kubectl apply -f -
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
EOF

# 3. Deploy a Pod using gVisor
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: sandboxed-pod
spec:
  runtimeClassName: gvisor
  containers:
  - name: app
    image: nginx:alpine
EOF

# 4. Verify sandboxing (gVisor kernel version shown)
kubectl exec sandboxed-pod -- uname -r

P10. Signing and Verifying Images with Cosign

# 1. Generate a key pair
cosign generate-key-pair

# 2. Build and push the image
docker build -t registry.example.com/myapp:v1.0 .
docker push registry.example.com/myapp:v1.0

# 3. Sign the image
cosign sign --key cosign.key registry.example.com/myapp:v1.0

# 4. Verify the signature
cosign verify --key cosign.pub registry.example.com/myapp:v1.0

# 5. Kyverno policy to allow only signed images
cat <<EOF | kubectl apply -f -
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  rules:
  - name: verify-cosign
    match:
      any:
      - resources:
          kinds: ["Pod"]
    verifyImages:
    - imageReferences: ["registry.example.com/*"]
      attestors:
      - entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              <COSIGN_PUBLIC_KEY>
              -----END PUBLIC KEY-----
EOF

5. Exam Tips

  • Exam Environment: The browser terminal provides kubectl, crictl, kubeadm, openssl, falco, trivy, cosign, and more.
  • Context Switching: Always use kubectl config use-context to switch to the correct cluster for each task.
  • Bookmarks: Leverage allowed resources like killer.sh and the official Kubernetes documentation.
  • Prioritize: Attempt high-point tasks first; return to difficult ones later.
  • Verify: After every change, validate with kubectl get and kubectl describe.