Pod Security Standards

This guide describes good practices for security standards in Pods and containers.

Overview

The PodSecurityPolicy API is deprecated and will be removed from Kubernetes in version 1.25. This API is replaced by a new built-in admission controller (KEP-2579: Pod Security Admission Control) which allows cluster admins to enforce Pod Security Standards.

What does that mean?

Pods and containers that are not configured according to the enforced security standards defined globally or on the namespace level will not be admitted. In this way, it will not be possible to run them.

As a best practice, you must ensure that workloads (Operators and Operands) are defined to run under restricted permissions.

How should I configure my Operators and Operands to comply with the criteria?

  • For common cases that do not require escalating privileges: configure all containers to comply with the restricted policy as shown in the following the examples:

IMPORTANT NOTE The seccompProfile field to define that a container is restricted was introduced with K8s 1.19 and might not be supported on some vendors by default. Please, do not use this field if you are looking to build Operators that work on K8s versions < 1.19 or on vendors that do not support this field. Having this field when it is not supported can result in your Pods/Containers not being allowed to run (i.e. On Openshift versions < 4.11 with its default configuration the deployments will fail with errors like Forbidden: seccomp.) However, if you are developing solutions to be distributed on Kubernetes versions => 1.19 and or for example, Openshift versions >= 4.11 it is highly recommended that this field is used to ensure that all your Pods/Containers are restricted unless they require escalated privileges.

In Kubernetes manifests:

    spec:
      securityContext:
        runAsNonRoot: true
        # Please ensure that you can use SeccompProfile and do not use
        # if your project must work on old Kubernetes
        # versions < 1.19 or on vendors versions which
        # do NOT support this field by default (i.e. Openshift < 4.11 )
        seccompProfile:
          type: RuntimeDefault
      ...
      containers:
      - name: controller-manager
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
        ...

On Reconciliations, such as code implementation in Go:

dep:= &appsv1.Deployment{
  ObjectMeta: metav1.ObjectMeta{
  .
  },
  Spec: appsv1.DeploymentSpec{
    
     Template: corev1.PodTemplateSpec{
       .
        Spec: corev1.PodSpec{
           // Ensure restrictive context for the Pod    
           SecurityContext: &corev1.PodSecurityContext{
              RunAsNonRoot: &[]bool{true}[0],
			  // Please ensure that you can use SeccompProfile and do NOT use
			  // this filed if your project must work on old Kubernetes
			  // versions < 1.19 or on vendors versions which 
			  // do NOT support this field by default (i.e. Openshift < 4.11)
              SeccompProfile: &corev1.SeccompProfile{
                 Type: corev1.SeccompProfileTypeRuntimeDefault,
              },
           },
           Containers: []corev1.Container{{
              Image:   "memcached:1.4.36-alpine",
              Name:    "memcached",
              // Ensure restrictive context for the container  
              SecurityContext: &corev1.SecurityContext{
                 RunAsNonRoot:  &[]bool{true}[0],
                 AllowPrivilegeEscalation:  &[]bool{false}[0],
                 Capabilities: &corev1.Capabilities{
                    Drop: []corev1.Capability{
                       "ALL",
                    },
                 },
              },
           }},
        },
     },
  },
}

Note: For Ansible- and Helm-based Operator projects, your Ansible playbooks or Helm charts must create manifests that comply with the requirements.

  • For workloads that need elevated permissions: Ensure the namespace has the appropriate enforcement level label as shown in the following example. You might need include this in the installation documentation for your Operator. While the label syncer should handle this for you in most cases, it is a good practice for Operators to explicitly state its requirements.
  labels:
    ...
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/audit: privileged
    pod-security.kubernetes.io/warn: privileged

You should ensure the configuration is carried to the Pod/Containers on the bundle CSV (install.spec.deployments.containers).

To check an example of CSV which complies with the restrictive policy, see the Golang sample under the testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml