I'm trying to deploy a restricted psp which should disable the use of the root user in a pod:
kind: PodSecurityPolicy
metadata:
name: unprivilegedpolicy
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
- 'persistentVolumeClaim'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'MustRunAsNonRoot'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
fsGroup:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
readOnlyRootFilesystem: false
I've added this psp to a ClusterRole and binded it to the namespace hello-world:
Name: UnPrivilegedClusterRole
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
podsecuritypolicies.policy [] [unprivilegedpolicy] [use]
[root@master01 ~]# kubectl describe clusterrolebindings.rbac.authorization.k8s.io HelloWorldRoleBinding
Name: HelloWorldRoleBinding
Labels: <none>
Annotations: <none>
Role:
Kind: ClusterRole
Name: UnPrivilegedClusterRole
Subjects:
Kind Name Namespace
---- ---- ---------
Group system:serviceaccounts hello-world
BUT if I try to run a ngnix container ```kubectl run --name=nginx hello-world" the containers succesfully runs as root user. The deployment is deployed via a ServiceAccount. I also enabled the PodSecurityPolicy at the admission-controller.
Does anybody has a solution for this?
First of all:
$ kubectl run --name=nginx hello-world
You did not specify image name of the pod. Correct syntax should be:
$ kubectl run --image=nginx NAME_OF_DEPLOYMENT
As said above commands will try to create a deployment.
The issue you are encountering is most probably connected with:
On newly created Kubernetes cluster with pod security policy turned on you should not be able to spawn any pod regardless of your privileges.
Pod security policy control is implemented as an optional (but recommended) admission controller. PodSecurityPolicies are enforced by enabling the admission controller, but doing so without authorizing any policies will prevent any pods from being created in the cluster.
Admission controller as well as pod security policy and RBAC are strongly connected with solutions you are working with. You should refer to documentation specific to your case.
For example:
PSP
configured will not create pods. It will display a message: Unable to validate against any pod security policy: []
Warning: If you enable the PodSecurityPolicy controller without first defining and authorizing any actual policies, no users, controllers, or service accounts can create or update Pods. If you are working with an existing cluster, you should define and authorize policies before enabling the controller.
kubespray
(with pod security policy variable set to true when provisioning and running on Ubuntu) will have a restrictive PSP
created and it will have a MustRunAsNonRoot
parameter inside the PSP
.There is another issue with NGINX
pod. NGINX
image will try to run as root
user inside of the pod. Admission controller with PSP
configured with:
runAsUser:
rule: MustRunAsNonRoot
will deny that with message: Error: container has runAsNonRoot and image will run as root
with accordance to PSP
.
To run NGINX
pod with this policy you would need to either:
PSP
(which will allow to run as root user inside a pod) with: runAsUser:
rule: RunAsAny
NGINX
image configured in a way that allows running NGINX
as non root user.Example of such pod below:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: non-root-nginx
name: non-root-nginx
spec:
securityContext:
runAsUser: 101
fsGroup: 101
containers:
- image: nginx
name: non-root-nginx
volumeMounts:
- mountPath: /var/cache/nginx
name: edir
- mountPath: /var/run
name: varun
- mountPath: /etc/nginx/conf.d/default.conf
name: default-conf
subPath: default.conf
dnsPolicy: ClusterFirst
restartPolicy: Never
volumes:
- name: edir
emptyDir: {}
- name: varun
emptyDir: {}
- name: default-conf
configMap:
name: nginx8080
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx8080
namespace: default
data:
default.conf: |+
server {
listen 8080;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}