Kubernetes: Assigning Pod Security Policies with RBAC
A PodSecurityPolicy is a cluster-level resource for managing security aspects of a pod specification.¹
PSPs allow you to control:
- The ability to run privileged containers and control privilege escalation
- Access to host filesystems
- Usage of volume types
- And a few other aspects including AppArmor, sysctl, and seccomp profiles
A pod security policy is a regular resource accessible via kubectl
.
You can get a rundown of them with:kubectl explain podsecuritypolicy
Creating Pod Security Policies
We are going to create two policies from the k8s docs:
privileged
This policy will be implicitly accessible to cluster admins and chosen by default since they have access to all resources. This policy is the least restrictive you can create.
To create it:
kubectl create -f ./psp/privileged.yaml
restricted
This policy we will explicitly assign to all authenticated users. It denies running as root or escalating to root, requires a security profile, limits volume types, and a few other aspects.
To create it:
kubectl create -f ./psp/restricted.yaml
You should now have (at least) two pod security policies. Runkubectl get psp
and you should see output similar to the following:
Assigning Pod Security Policies
You can assign access to a pod security policy using RBAC. This RBAC configuration will:
- create a cluster wide role named
psp:restricted
(line 4) that canuse
(line 13) the pod security policyrestricted
(line 11). - create a cluster wide role binding giving access to the
psp:restricted
role (line 24) to all authenticated users (system:authenticted
, line 20)
This will effectively make the restricted policy the default for all users and service accounts in the cluster.
To create it:
kubectl create -f ./rbac/psp-restricted.yaml
Meanwhile your privileged policy will automatically be accessible to you as a cluster admin.
Now you may be asking yourself:
If I am a cluster admin and I have access to privileged by default, but I’m also assigned restricted since I am an authenticated user… which one do I actually get?
Well, I’m glad you asked. If multiple policies are applicable to your account, you will be assigned the first one alphabetically.²
Let’s double check that the correct access was assigned.
This will tell you, if you, an admin can use the privileged policy:
kubectl auth can-i use psp/privileged
You should see “yes”.
kubectl
allows you to pose as other users using --as
to perform operations, but you can also use it to inspect permissions.
kubectl auth can-i use psp/privileged --as-group=system:authenticated --as=any-user
You should see “no”.
kubectl auth can-i use psp/restricted --as-group=system:authenticated --as=any-user
You should see “yes”.
Pod security policies in action
Let’s create a namespace and a service account to test out our restricted policy.
kubectl create namespace psp-rbac-demo
kubectl create serviceaccount fake-user -n psp-rbac-demo
kubectl create rolebinding fake-editor --clusterrole=edit --serviceaccount=psp-rbac-demo:fake-user -n psp-rbac-demo
Now we will try to schedule this pod with privileges:
kubectl create -f https://git.io/fNhJX -n psp-rbac-demo \
--as-group=system:authenticated \
--as=system:serviceaccount:psp-rbac-demo:fake-user
You should see:
Error from server (Forbidden): error when creating "https://git.io/fNhJX": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
Clean up the test namespace with: kubectl delete ns psp-rbac-demo
And that’s that. Now any user of your cluster will be bound to the rules set in your restricted policy.
Full source code for this tutorial is available here.
- PSPs need to be enabled via an admissions controller before they will function. You can read more about enabling them here. A note of caution, you should have your policies applied to your cluster before enabling the admission controller otherwise no pods will be able to be scheduled.
- You can read more about policy order here. I generally name my policies with a numeric prefix to make this a little more explicit and easy to reason about the order in which they would be selected. E.g.: 0-privileged and 100-restricted