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…
Question
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 ClusterRole | ClusterRole --resource-name references a non-existent PSP |
| ClusterRole before ClusterRoleBinding | Binding references non-existent role - error on creation |
| SA before ClusterRoleBinding | Binding references non-existent SA subject |
| PSP admission not enabled in cluster | All 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 (
useverb) 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 likepod-security.kubernetes.io/enforce: restricted. Know which version the exam uses.
Topics
Community Discussion
No community discussion yet for this question.