Use the unprivileged policy

To switch users from the privileged policy to the unprivileged policy, a cluster admin must remove the ClusterRoleBinding that links all users and service accounts to the privileged policy and then create a RoleBinding to link users to the alternate policy. A ClusterRole is already defined but must be assigned to the required users or teams. The procedures in this section apply both to using the unprivileged as well as any custom policy.

Note

When the ClusterRoleBinding is removed, cluster admins can still deploy Pods, and these Pods are deployed with the privileged policy. However, users or service accounts will be unable to deploy pods until the RoleBinding is created, because Kubernetes cannot determine which pod security policy to apply.


To apply the unprivileged policy:

The following steps must be performed by a cluster admin.

  1. Remove the ClusterRoleBinding:

    kubectl delete clusterrolebindings ucp:all:privileged-psp-role
    
  2. List the existing ClusterRoles:

    kubectl get clusterrole | grep psp
    

    Expected output:

    privileged-psp-role                                                    3h47m
    unprivileged-psp-role                                                  3h47m
    
  3. Define the user or team to whom you want to apply the ClusterRole:

    USER=<user-name>
    
  4. Create a RoleBinding that links the ClusterRole to the user or team:

    cat <<EOF | kubectl create -f -
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: unprivileged-psp-role:$USER
      namespace: default
    roleRef:
      kind: ClusterRole
      name: unprivileged-psp-role
      apiGroup: rbac.authorization.k8s.io
    subjects:
    - kind: User
      name: $USER
      namespace: default
    EOF
    

To verify the application of the unprivileged policy:

The following example must be performed by a regular user who is assigned to the unprivileged policy.

  1. Deploy a basic nginx Pod:

    cat <<EOF | kubectl create -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: demopod
    spec:
      containers:
        - name:  demopod
          image: nginx
    EOF
    
  2. Review the status of the Pod:

    kubectl get pods
    

    Example output:

    NAME      READY   STATUS    RESTARTS   AGE
    demopod   1/1     Running   0          10m
    
  3. Review which policy is applied to the Pod using the -o yaml or -o json syntax with kubectl and parse the JSON output with jq:

    kubectl get pods demopod -o json | jq -r '.metadata.annotations."kubernetes.io/psp"'
    

    Expected output:

    unprivileged
    

Use the unprivileged policy in a Deployment

If you have disabled the privileged policy and created a RoleBinding to map a user to a new PSP, Kubernetes objects like Deployments and DaemonSets will not be able to deploy Pods. This is because Kubernetes objects use a ServiceAccount to schedule Pods, instead of the user that created the Deployment.

For this Deployment to be able to schedule Pods, the service account defined within the Deployment specification needs to be associated with a policy.


To review the status of the NGINX Deployment created in the previous section:

  1. List your Deployments:

    kubectl get deployments
    

    Example output:

    NAME    READY   UP-TO-DATE   AVAILABLE   AGE
    nginx   0/1     0            0           88s
    
  2. List your ReplicaSets:

    kubectl get replicasets
    

    Example output:

    NAME              DESIRED   CURRENT   READY   AGE
    nginx-cdcdd9f5c   1         0         0       92s
    
  3. Describe your ReplicaSets:

    kubectl describe replicasets nginx-cdcdd9f5c
    

    Example output:

    Warning  FailedCreate  48s (x15 over 2m10s)  \
    replicaset-controller  Error creating: \
    pods "nginx-cdcdd9f5c-" is forbidden: \
    unable to validate against any pod security policy: []
    

If a service account is not defined within a Deployment specification, the default service account in a namespace is used. This is the case in the Deployment output above. Because there is no service account defined, a Rolebinding is needed to grant the default service account in the default namespace to use the PSP.


To associate the unprivileged policy with the default service account:

The following must be performed by a cluster admin.

Create a RoleBinding to associate the unprivileged policy with the default service account:

cat <<EOF | kubectl create -f -
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: unprivileged-psp-role:defaultsa
  namespace: default
roleRef:
  kind: ClusterRole
  name: unprivileged-psp-role
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
EOF

To verify the application of the unprivileged policy to the default service account:

  1. List your Deployments:

    kubectl get deployments
    

    Example output:

    NAME    READY   UP-TO-DATE   AVAILABLE   AGE
    nginx   1/1     1            1           6m11s
    
  2. List your ReplicaSets:

    kubectl get replicasets
    

    Example output:

    NAME              DESIRED   CURRENT   READY   AGE
    nginx-cdcdd9f5c   1         1         1       6m16s
    
  3. List your Pods:

    kubectl get pods
    

    Example output:

    NAME                    READY   STATUS    RESTARTS   AGE
    nginx-cdcdd9f5c-9kknc   1/1     Running   0          6m17s
    
  4. Review which policy is applied to the default service account. For example:

    kubectl get pod nginx-cdcdd9f5c-9kknc  -o json | jq -r '.metadata.annotations."kubernetes.io/psp"'
    

    Expected output:

    unprivileged
    

Apply the unprivileged PSP to a namespace

A common PSP use case is to apply a particular policy to particular namespace(s). For example, an admin might want to use the privileged policy for all of the infrastructure namespaces and use the unprivileged policy for the end user namespaces.

In the following example, infrastructure workloads are deployed in the kube-system and monitoring namespaces, while end user workloads are deployed in the default namespace.


To apply the privileged and unprivileged PSPs to different namespaces:

The following steps must be performed by a cluster admin.

  1. Delete the ClusterRoleBinding that is applied by default in MKE:

    kubectl delete clusterrolebindings ucp:all:privileged-psp-role
    
  2. Create a new ClusterRoleBinding that will enforce the privileged PSP for all users and service accounts in the kube-system and monitoring namespaces:

    cat <<EOF | kubectl create -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: ucp:infrastructure:privileged-psp-role
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: privileged-psp-role
    subjects:
    - kind: Group
      name: system:authenticated:kube-system
      apiGroup: rbac.authorization.k8s.io
    - kind: Group
      name: system:authenticated:monitoring
      apiGroup: rbac.authorization.k8s.io
    - kind: Group
      name: system:serviceaccounts:kube-system
      apiGroup: rbac.authorization.k8s.io
    - kind: Group
      name: system:serviceaccounts:monitoring
      apiGroup: rbac.authorization.k8s.io
    EOF
    
  3. Create a ClusterRoleBinding to allow all users who deploy Pods and Deployments in the default namespace to use the unprivileged policy.

    cat <<EOF | kubectl create -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: ucp:default:unprivileged-psp-role
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: unprivileged-psp-role
    subjects:
    - kind: Group
      name: system:authenticated:default
      apiGroup: rbac.authorization.k8s.io
    - kind: Group
      name: system:serviceaccounts:default
      apiGroup: rbac.authorization.k8s.io
    EOF
    

To verify the application of the privileged and unprivileged policies:

  1. Create two Deployments, one in the monitoring namespace and the other in the default namespace:

    cat <<EOF | kubectl create -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: demopod
      namespace: monitoring
    spec:
      containers:
        - name:  demopod
          image: nginx
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: demopod
      namespace: default
    spec:
      containers:
        - name:  demopod
          image: nginx
    EOF
    
  2. Review which policy is applied to the monitoring namespace:

    kubectl get pods demopod -n monitoring -o json | jq -r '.metadata.annotations."kubernetes.io/psp"'
    

    Expected output:

    privileged
    
  3. Review which policy is applied to the default namespace:

    kubectl get pods demopod -n default -o json | jq -r '.metadata.annotations."kubernetes.io/psp"'
    

    Expected output:

    unprivileged