nerdexam
Linux_Foundation

CKS · Question #21

Create a PSP that will only allow the persistentvolumeclaim as the volume type in the namespace restricted. Create a new PodSecurityPolicy named prevent-volume-policy which prevents the pods which…

Pod Security Policy (PSP) - Restricting Volume Types Overall Goal The objective is to enforce that pods in the cluster can only mount PersistentVolumeClaims as volumes - no Secrets, ConfigMaps, hostPath, emptyDir, etc. This is a defense-in-depth measure: if an attacker…

Submitted by mike_84· May 4, 2026Cluster Hardening

Question

Create a PSP that will only allow the persistentvolumeclaim as the volume type in the namespace restricted. Create a new PodSecurityPolicy named prevent-volume-policy which prevents the pods which is having different volumes mount apart from persistentvolumeclaim. Create a new ServiceAccount named psp-sa in the namespace restricted. Create a new ClusterRole named psp-role, which uses the newly created Pod Security Policy prevent-volume-policy Create a new ClusterRoleBinding named psp-role-binding, which binds the created ClusterRole psp-role to the created SA psp-sa. Hint: Also, Check the Configuration is working or not by trying to Mount a Secret in the pod maifest, it should get failed.

Explanation

Pod Security Policy (PSP) - Restricting Volume Types

Overall Goal

The objective is to enforce that pods in the cluster can only mount PersistentVolumeClaims as volumes - no Secrets, ConfigMaps, hostPath, emptyDir, etc. This is a defense-in-depth measure: if an attacker compromises a pod, they cannot mount a Secret volume to exfiltrate sensitive data.

PSPs work through RBAC authorization - a PSP does nothing by itself. A pod can only use a PSP if the ServiceAccount running the pod has RBAC permission to use that policy. That's why all four objects (PSP + SA + ClusterRole + ClusterRoleBinding) are required.


Step-by-Step Breakdown

Step 1 - Create the PodSecurityPolicy

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: prevent-volume-policy
spec:
  privileged: false
  volumes:
    - 'persistentVolumeClaim'   # ONLY this volume type is allowed
  runAsUser:
    rule: RunAsAny
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny

Why: The volumes whitelist is the core restriction. Every volume type NOT listed is denied. If a pod spec requests a secret volume, the API server rejects it at admission time.

If skipped: Nothing to enforce - all subsequent RBAC objects would bind to nothing meaningful.


Step 2 - Create the ServiceAccount in namespace restricted

kubectl create serviceaccount psp-sa -n restricted

Why: Pods run under a ServiceAccount's identity. PSP enforcement checks whether the pod's ServiceAccount has permission to use the applicable PSP. You need a dedicated SA so you can scope the RBAC binding precisely.

If skipped: You'd have no identity to bind the ClusterRole to, or you'd be forced to bind to default, which grants the restriction (or permission) too broadly/incorrectly.


Step 3 - Create the ClusterRole

kubectl create clusterrole psp-role \
  --verb=use \
  --resource=podsecuritypolicies \
  --resource-name=prevent-volume-policy

Why: A ClusterRole with use verb on the specific PSP prevent-volume-policy is the RBAC object that grants permission to "use" the policy. Without this, even if a PSP exists, no pod can be admitted under it.

Key detail: The verb is use (not get, list, etc.) - this is Kubernetes-specific and controls PSP admission, not normal API access.

If skipped: The ClusterRoleBinding has no ClusterRole to reference, so no SA ever gets permission to use the PSP.


Step 4 - Create the ClusterRoleBinding

kubectl create clusterrolebinding psp-role-binding \
  --clusterrole=psp-role \
  --serviceaccount=restricted:psp-sa

Why: This is the wire that connects the SA (psp-sa in namespace restricted) to the ClusterRole (psp-role). Without it, the SA has no permission to use the PSP, and any pod using psp-sa that tries to mount any volume will be rejected - or will fall through to a more permissive default PSP if one exists.

Note the format: --serviceaccount=<namespace>:<sa-name> - the namespace prefix is required.


Verification (the Hint)

Test by creating a pod under psp-sa that mounts a Secret volume:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: restricted
spec:
  serviceAccountName: psp-sa
  containers:
  - name: test
    image: nginx
    volumeMounts:
    - name: secret-vol
      mountPath: /etc/secret
  volumes:
  - name: secret-vol
    secret:             # <-- NOT persistentVolumeClaim
      secretName: some-secret

Expected result: Error from server: pods "test-pod" is forbidden: unable to validate against any pod security policy

This confirms the PSP is being enforced. A pod requesting only a PVC volume would succeed.


Order Matters

If you skip/reverse...What breaks
PSP before ClusterRoleClusterRole --resource-name references a non-existent PSP
ClusterRole before ClusterRoleBindingBinding references non-existent role - error on creation
SA before ClusterRoleBindingBinding references non-existent SA subject
PSP admission not enabled in clusterAll PSPs are silently ignored

Memory Tip

Think of it as a locked door analogy:

PSP = the lock mechanism (defines the rules) ClusterRole = a key that fits that lock (use verb) ServiceAccount = the person who needs to get through the door ClusterRoleBinding = handing that key to the person

All four are needed. A lock with no key holder, or a key with no lock - neither achieves security.


Important exam note: PSP was deprecated in Kubernetes 1.21 and removed in 1.25. If the exam cluster is 1.25+, look for the replacement: Pod Security Admission (PSA) using namespace labels like pod-security.kubernetes.io/enforce: restricted. Know which version the exam uses.

Topics

#PodSecurityPolicy#RBAC#Volume restrictions#Cluster hardening

Community Discussion

No community discussion yet for this question.

Full CKS Practice