Skip to content

Practice Questions -- Domain 3: Minimize Microservice Vulnerabilities

Highest Weight Domain (20%)

This domain has the highest weight on the CKS exam. These 25 questions cover all major topics: SecurityContexts, Secrets, OPA/Gatekeeper, RuntimeClass, Admission Controllers, mTLS, and Container Hardening. Practice until you can solve each in under 5 minutes.

How to Use These Questions

  1. Set up a practice cluster (kubeadm, kind, or minikube)
  2. Time yourself -- aim for 4-5 minutes per question
  3. Do NOT look at the solutions until you have attempted each question
  4. Focus on questions you find difficult -- those are the ones you will learn the most from

Question 1 -- SecurityContext: Non-Root Enforcement

Difficulty: Easy

A pod named legacy-app is running in the production namespace with the following specification. It currently runs as root.

Modify the pod to:

  • Run as user ID 1000 and group ID 1000
  • Enforce non-root execution
  • Prevent privilege escalation
  • Drop all Linux capabilities

The pod uses the image nginx:1.25 with a single container named app.


Question 2 -- SecurityContext: Read-Only Filesystem

Difficulty: Medium

Create a pod named secure-nginx in the default namespace that:

  • Uses the nginx:1.25 image
  • Has a read-only root filesystem
  • Still functions correctly (nginx needs to write to /var/cache/nginx, /var/run, and /tmp)
  • Runs as user 101 (nginx user)
  • Uses a seccomp profile of type RuntimeDefault

Question 3 -- SecurityContext: Pod vs Container Precedence

Difficulty: Easy

Create a pod named multi-user-pod in the default namespace with the following requirements:

  • Pod-level: runAsUser: 1000, runAsGroup: 3000, fsGroup: 2000
  • Container writer (image busybox:1.36, command sh -c "id > /data/user.txt && sleep 3600"): should run as user 2000 (override pod-level)
  • Container reader (image busybox:1.36, command sh -c "sleep 3600"): should inherit pod-level user
  • Both containers share a volume mounted at /data

After creation, verify the user IDs and file ownership in /data.


Question 4 -- Secrets: Encryption at Rest

Difficulty: Hard

Secrets in the cluster are currently stored unencrypted in etcd. Configure encryption at rest for secrets:

  1. Generate a 32-byte encryption key
  2. Create an EncryptionConfiguration using the aescbc provider at /etc/kubernetes/enc/encryption-config.yaml
  3. Configure the API server to use the encryption configuration
  4. Verify that the API server restarts successfully
  5. Create a test secret named encrypted-secret in the default namespace with key password and value SuperSecret123
  6. Verify the secret is encrypted in etcd

Question 5 -- Secrets: Environment Variables to Volume Mounts

Difficulty: Medium

A pod named insecure-app in the security namespace currently exposes secrets through environment variables:

yaml
env:
- name: DB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: db-credentials
      key: password

The secret db-credentials exists with keys username and password.

Refactor the pod to:

  • Mount the secret as a volume at /etc/secrets instead of using environment variables
  • Set volume mount to read-only
  • Set file permissions to 0400
  • Remove the environment variable references

Question 6 -- Secrets: Verify etcd Encryption

Difficulty: Medium

A colleague claims that encryption at rest has been configured for secrets in the cluster. Verify this claim:

  1. Check if the API server has the --encryption-provider-config flag set
  2. Inspect the EncryptionConfiguration file to identify the encryption provider
  3. Create a test secret named enc-test with value verify-me
  4. Read the secret directly from etcd and confirm it is encrypted
  5. Confirm you can still read the secret normally through kubectl

Question 7 -- OPA/Gatekeeper: Require Labels

Difficulty: Hard

Gatekeeper is installed in the cluster. Create a policy that:

  1. Creates a ConstraintTemplate named k8srequiredlabels that requires specified labels on resources
  2. Creates a Constraint named require-team-label that enforces all Pods in the production namespace must have a team label
  3. The enforcement action should be deny
  4. Exclude the kube-system namespace

Test by attempting to create a pod without the team label in the production namespace.


Question 8 -- OPA/Gatekeeper: Deny Privileged Containers

Difficulty: Hard

Create an OPA/Gatekeeper policy that:

  1. Creates a ConstraintTemplate named k8sdenyprivileged that denies pods with privileged containers
  2. The Rego policy should check both regular containers and init containers
  3. Creates a Constraint named no-privileged-pods that applies to all pods
  4. Excludes the kube-system and gatekeeper-system namespaces

Verify by attempting to create a privileged pod.


Question 9 -- OPA/Gatekeeper: Enforce Image Registry

Difficulty: Hard

Create an OPA/Gatekeeper policy that:

  1. Creates a ConstraintTemplate named k8sallowedrepos with a parameter for a list of allowed repository prefixes
  2. Creates a Constraint named restrict-image-repos that only allows images from:
    • docker.io/library/
    • gcr.io/my-company/
  3. Apply to all pods in the production namespace
  4. Use dryrun enforcement action first, then change to deny after verifying

Question 10 -- OPA/Gatekeeper: Audit Mode

Difficulty: Medium

An existing Gatekeeper Constraint named require-resource-limits is currently in deny mode and is blocking deployments. The development team needs time to add resource limits to their pods.

  1. Change the enforcement action from deny to dryrun (audit mode)
  2. Verify the constraint is now in audit mode
  3. Check the audit results to see which existing pods violate the policy
  4. Document the namespace and pod names of violating resources

Question 11 -- RuntimeClass: gVisor Configuration

Difficulty: Medium

Configure container sandboxing with gVisor:

  1. Create a RuntimeClass named gvisor with handler runsc
  2. Create a pod named sandboxed-app in the default namespace that:
    • Uses the nginx:1.25 image
    • Uses the gvisor RuntimeClass
    • Has a container named web

Question 12 -- RuntimeClass: Multiple Runtimes

Difficulty: Medium

Create two RuntimeClass resources and assign pods to them:

  1. RuntimeClass gvisor with handler runsc
  2. RuntimeClass kata with handler kata-runtime and a pod overhead of memory: 160Mi and cpu: 250m
  3. Create a pod named gvisor-pod using the gvisor RuntimeClass with image busybox:1.36 running sleep 3600
  4. Create a pod named kata-pod using the kata RuntimeClass with image busybox:1.36 running sleep 3600

Question 13 -- Admission Controllers: Enable ImagePolicyWebhook

Difficulty: Hard

Configure the ImagePolicyWebhook admission controller:

  1. The webhook service endpoint is at https://image-bouncer.default.svc:1323/image_policy
  2. The required certificates are at:
    • CA: /etc/kubernetes/admission/ca.crt
    • Client cert: /etc/kubernetes/admission/api-server-client.crt
    • Client key: /etc/kubernetes/admission/api-server-client.key
  3. Create the admission configuration at /etc/kubernetes/admission/admission-config.yaml
  4. Create the kubeconfig at /etc/kubernetes/admission/kubeconfig.yaml
  5. Enable the ImagePolicyWebhook admission controller
  6. Set defaultAllow to false (deny images if webhook is unreachable)
  7. Ensure the API server restarts successfully

Question 14 -- Admission Controllers: ValidatingWebhookConfiguration

Difficulty: Medium

A validating webhook service pod-validator is running in the webhook-system namespace on port 443 with path /validate.

Create a ValidatingWebhookConfiguration named pod-security-webhook that:

  • Intercepts CREATE and UPDATE operations on Pods
  • Uses the in-cluster service as the webhook endpoint
  • Has a failure policy of Fail (fail closed)
  • Excludes the kube-system namespace
  • Sets a timeout of 10 seconds
  • The CA bundle is available at /etc/kubernetes/webhook/ca.crt

Question 15 -- Admission Controllers: Troubleshooting

Difficulty: Medium

Pods cannot be created in the production namespace. The error message indicates an admission webhook is denying requests. Investigate and fix the issue:

  1. Identify which webhook configuration is causing the rejection
  2. Check if the webhook service is healthy
  3. The webhook service pod in webhook-system namespace has crashed. Determine the most appropriate immediate fix to restore pod creation ability
  4. Apply the fix while maintaining security

Question 16 -- Container Hardening: Non-Root with Read-Only FS

Difficulty: Medium

Harden the following pod specification. Apply ALL of these security measures:

  • Run as non-root user (UID 10001)
  • Read-only root filesystem
  • Drop all capabilities
  • Prevent privilege escalation
  • Set resource limits (128Mi memory, 250m CPU)
  • Use RuntimeDefault seccomp profile
  • Do not mount the service account token
  • Provide writable /tmp directory

The pod uses image python:3.12-slim with container name api and command ["python", "-m", "http.server", "8080"].


Question 17 -- Container Hardening: Identify and Fix Vulnerabilities

Difficulty: Medium

Examine the pod vulnerable-app in the audit namespace. Identify and fix all security issues:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: vulnerable-app
  namespace: audit
spec:
  containers:
  - name: app
    image: ubuntu:latest
    command: ["sh", "-c", "apt-get update && apt-get install -y curl && sleep 3600"]
    securityContext:
      privileged: true
    env:
    - name: DB_PASSWORD
      value: "plaintext-password-123"
    ports:
    - containerPort: 8080

List all vulnerabilities and create a hardened version.


Question 18 -- Combined: SecurityContext + Secrets

Difficulty: Medium

Create a pod named secure-db-client in the production namespace that:

  • Uses image postgres:16-alpine
  • Container name db-client
  • Mounts the existing secret pg-credentials (keys: PGUSER, PGPASSWORD) as a volume at /etc/db-secrets with permissions 0400
  • Runs as user 70 (postgres user), group 70
  • Has a read-only root filesystem
  • Provides writable /tmp and /var/run/postgresql directories
  • Drops all capabilities, prevents privilege escalation
  • Command: ["sleep", "3600"]

Question 19 -- Combined: RuntimeClass + SecurityContext

Difficulty: Hard

Create a high-security pod that combines sandboxing with security contexts:

  1. Ensure a RuntimeClass named gvisor with handler runsc exists
  2. Create a pod named high-security-pod in the restricted namespace that:
    • Uses the gvisor RuntimeClass
    • Image: gcr.io/distroless/static:nonroot
    • Container name: app, command: ["/bin/sleep", "3600"]
    • Runs as user 65532, group 65532
    • Read-only root filesystem
    • Drops all capabilities
    • No privilege escalation
    • RuntimeDefault seccomp profile
    • No service account token mount
    • Memory limit: 64Mi, CPU limit: 100m

Question 20 -- Combined: Gatekeeper + SecurityContext

Difficulty: Hard

Create a Gatekeeper policy and demonstrate compliance:

  1. Create a ConstraintTemplate named k8srequirereadonlyfs that denies pods where containers do not have readOnlyRootFilesystem: true
  2. Create a Constraint named require-readonly-fs that applies to pods in the production namespace
  3. Demonstrate a pod that is rejected by the policy
  4. Create a compliant pod named compliant-app that passes the policy with image nginx:1.25

Question 21 -- Secrets: Key Rotation

Difficulty: Hard

The cluster currently uses encryption at rest with an aescbc key named key1. Perform a key rotation:

  1. Generate a new 32-byte encryption key
  2. Update the EncryptionConfiguration to use the new key (key2) as the primary encryption key while keeping key1 for decryption of old secrets
  3. Restart the API server
  4. Re-encrypt all existing secrets with the new key
  5. Verify that newly created secrets use the new key

Question 22 -- Admission Controllers: Mutating vs Validating Order

Difficulty: Easy

Answer the following questions about admission controller ordering:

  1. A MutatingWebhookConfiguration adds a label validated: true to all pods. A ValidatingWebhookConfiguration rejects pods without the label validated: true. Will a pod creation request succeed? Explain the order of operations.
  2. What is the reinvocationPolicy field in MutatingWebhookConfiguration, and when would you set it to IfNeeded?
  3. What happens when failurePolicy: Fail is set and the webhook service is down?

Create the MutatingWebhookConfiguration and ValidatingWebhookConfiguration YAML files (no need to deploy the actual webhook services).


Question 23 -- mTLS: PeerAuthentication

Difficulty: Medium

Istio is installed in the cluster. Configure mTLS:

  1. Create a mesh-wide PeerAuthentication policy in the istio-system namespace that sets mTLS mode to STRICT
  2. Create a namespace-level PeerAuthentication for the legacy namespace that sets mTLS mode to PERMISSIVE (to allow non-mesh services to communicate)
  3. Create an AuthorizationPolicy in the production namespace named allow-frontend-only that:
    • Applies to pods with label app: api-server
    • Only allows traffic from the frontend service account in the production namespace
    • Only allows GET and POST methods on paths starting with /api/

Question 24 -- Combined: Full Pod Hardening

Difficulty: Hard

You are given a Deployment named web-app in the production namespace. Apply the maximum security hardening:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web
        image: nginx:latest
        ports:
        - containerPort: 80

Apply ALL of the following:

  • Pin the image to a specific tag (not latest)
  • Non-root user (UID 101 for nginx)
  • Read-only root filesystem with necessary writable volumes
  • Drop all capabilities, add only NET_BIND_SERVICE
  • Prevent privilege escalation
  • Resource limits (256Mi memory, 500m CPU)
  • RuntimeDefault seccomp profile
  • Do not automount service account token
  • Add fsGroup: 101

Question 25 -- Combined: Multi-Layer Security

Difficulty: Hard

Implement a comprehensive multi-layer security configuration:

  1. Secret encryption: Verify encryption at rest is configured. If not, set it up using secretbox provider.

  2. OPA Policy: Create a Gatekeeper policy (ConstraintTemplate + Constraint) that ensures all pods in production namespace:

    • Must have runAsNonRoot: true at pod level OR container level
  3. RuntimeClass: Create a RuntimeClass gvisor with handler runsc

  4. Secure Pod: Create a pod named fortress in production namespace that:

    • Uses the gvisor RuntimeClass
    • Mounts a secret named app-secret (create it with key api-key, value sk-12345) at /etc/secrets
    • Has all security hardening applied (non-root, read-only FS, drop caps, no escalation)
    • Passes the OPA policy you created

This question tests your ability to combine all Domain 3 concepts into a cohesive security architecture.

Released under the MIT License.