CIS Benchmark Kubernetes - PSP
The CIS document provides prescriptive guidance for establishing a secure configuration posture for Kubernetes. The Pod Security Policies (PSP) enable fine-grained authorization of pod creation and updates. In this article, we'll review the CIS benchmark items for Pod Security Policies and provide implementation details on how to enforce them on Kubernetes cluster. Let us first review the CIS benchmark guidance for Pod Security Policies.
CIS Benchmark Overview
The following items are checked for this benchmark item:
- 1.7 PodSecurityPolicies
- 1.7.1 Do not admit privileged containers
- 1.7.2 Do not admit containers wishing to share the host process ID namespace
- 1.7.3 Do not admit containers wishing to share the host IPC namespace
- 1.7.4 Do not admit containers wishing to share the host network namespace
- 1.7.5 Do not admit containers with allowPrivilegeEscalation
- 1.7.6 Do not admit root containers
- 1.7.7 Do not admit containers with dangerous capabilities
In practical terms, these best practices may not apply to each and every pod being deployed in the system. When deployed on our Kubernetes cluster, we will use this as the default policy across the cluster, and will selectively grant permissions on a targeted basis.
Design Overview
This benchmark requires that Kubernetes PodSecurityPolicies be enforced for all pods running in the system. The following diagram shows the basic pod security policy configuration data model:
Practically, we may have some pods that will require some elevated permissions, but most will not. To cater to the requirements, let us define two basic pod security policies:
- restricted
- privileged
restricted. This is a policy that simply prevents the creation of privileged pods.
kind: PodSecurityPolicy
metadata:
name: restricted
annotations:
seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'
seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
labels:
kubernetes.io/cluster-service: 'true'
addonmanager.kubernetes.io/mode: Reconcile
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
forbiddenSysctls:
privileged. This is a policy that allows the creation of privileged pods.
kind: PodSecurityPolicy
metadata:
name: privileged
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
spec:
privileged: true
allowPrivilegeEscalation: true
allowedCapabilities:
- '*'
volumes:
- '*'
hostNetwork: true
hostPorts:
- min: 0
max: 65535
hostIPC: true
hostPID: true
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
# This will fail if allowed-unsafe-sysctls is not set accordingly in kubelet flags
allowedUnsafeSysctls:
- '*'
kube-apiserver
pod and search for enabled admission plugins as shown below.Enforcement is performed whenever a new pod is created, usually by a Deployment, ReplicaSet, or some other templated controller. The authorization for the pod creation action is configured using RBAC Roles (or ClusterRoles) which are bound to a User or ServiceAccount. Thus PodSecurityPolicy enforcement can be configured and enforced at either a cluster or namespace granularity.
Next, let us create the following two ClusterRoles that have verb use
granted on the PodSecurityPolicy created above respectively.
- psp:privileged. This ClusterRole is granted the verb
use
on PodSecurityPolicyprivileged
created earlier.
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:name: psp:privilegedrules:- apiGroups:- policyresourceNames:- privilegedresources:- podsecuritypoliciesverbs:- use
- psp:restricted. This ClusterRole is granted the verb
use
on PodSecurityPolicyrestricted
created earlier.
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:name: psp:restrictedrules:- apiGroups:- policyresourceNames:- restrictedresources:- podsecuritypoliciesverbs:- use
Enforce Policy Use Cases
Now that we have created PodSecurityPolicies with different privileges and ClusterRoles that can use those policies, let us enforce these policies for different use cases outlined below.
Restrict system:authenticated subjects by default
To enforce restricted
PodSecurityPolicy on all authenticated users by default, we will bind the psp:restricted
ClusterRole on system:authenticated
subjects.
kind: ClusterRoleBinding
metadata:
name: psp:any:restricted
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:restricted
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:authenticated
Allow nodes to create privileged pods
Here the user kubelet
is allowed to create privileged pod by creating a RoleBinding object with the role psp:privileged
.
kind: RoleBinding
metadata:
name: psp:nodes:privileged
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:privileged
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:nodes
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kubelet
Allow kube-system namespace subjects to create privileged pods
To enforce a PodSecurityPolicy on all subjects in a namespace kube-system
, we can bind a ClusterRole that we created earlier to all the serviceaccounts in that namespace as shown below.
kind: RoleBinding
metadata:
name: psp:kube-system:privileged
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:privileged
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:masters
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:kube-system
With above PSP in place, services that are run in there own namespace will be started with restricted permissions. If those services require higher privileges, we will see two kinds of PSP enforcement errors:
- container has runAsNonRoot and image has non-numeric user (e.g., kibana), cannot verify user is non-root
- container has runAsNonRoot and image will run as root
Ideally, we would define a custom PSP for use in the services namespace.
Allow kube-system namespace subjects to create privileged pods
To allow services to run with increased privileges in a namespace svc-namespace
, create a RoleBinding as shown below.
kind: RoleBinding
metadata:
name: psp:svc-namespace:cs-restricted
namespace: svc-namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:privileged
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts
Conclusion
We reviewed CIS Kubernetes Benchmark, especially the guidance for Pod Security Policies. We created PSP to enforce those guidance. Practically, all services may not run with these restrictions. Some services may need to define a more relaxed pod security policy. We provided configurations for these different use cases.
Comments
Post a Comment