Enforcing Pod Security Standards
As discussed in the introduction for Pod Security Standards (PSS) section, there are three pre-defined policy levels: Privileged, Baseline, and Restricted. While implementing a Restricted PSS is recommended, it can cause unintended behavior at the application level unless properly configured. To get started, it's recommended to set up a Baseline Policy that will prevent known privileged escalations such as containers accessing HostProcess, HostPath, HostPorts, or allowing traffic snooping. Individual policies can then be set up to restrict or disallow these privileged accesses to containers.
A Kyverno Baseline Policy helps restrict all known privileged escalations under a single policy. It also allows for regular maintenance and updates to incorporate the latest discovered vulnerabilities into the policy.
Privileged containers can perform almost all actions that the host can do and are often used in CI/CD pipelines to allow building and publishing container images. With the now fixed CVE-2022-23648, a malicious actor could escape the privileged container by exploiting the Control Groups release_agent functionality to execute arbitrary commands on the container host.
In this lab, we will create a Deployment with a privileged container on our EKS cluster. Without a policy in place, a Deployment can be freely created and its pod template patched to add privileged access:
deployment.apps/privileged-deploy created
deployment.apps/privileged-deploy patched
deployment.apps "privileged-deploy" deleted
The kubectl patch command uses a JSON patch to add a securityContext to the first container in the pod template, setting privileged: true. This grants the container nearly unrestricted access to the host. To prevent such escalated privileged capabilities and avoid unauthorized use of these permissions, it's recommended to set up a Baseline Policy using Kyverno.
The baseline profile of the Pod Security Standards is a collection of the most fundamental and crucial steps that can be taken to secure Pods. Starting from Kyverno 1.8, an entire profile can be assigned to the cluster through a single rule. To learn more about the privileges blocked by the Baseline Profile, please refer to the Kyverno documentation.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: baseline-policy
spec:
background: true
validationFailureAction: Enforce
rules:
- name: baseline
match:
any:
- resources:
kinds:
- Deployment
validate:
allowExistingViolations: false
podSecurity:
level: baseline
version: latest
background: true applies the policy to existing resources in addition to new ones
validationFailureAction: Enforce blocks non-compliant Deployments from being created or updated
match.any.resources.kinds: [Deployment] applies the policy to all Deployment resources cluster-wide
allowExistingViolations: false ensures updates to already-violating Deployments are also blocked
validate.podSecurity enforces Kubernetes Pod Security Standards at the baseline level against the Deployment's pod template, using the latest standards version
Go ahead and apply the Baseline Policy:
clusterpolicy.kyverno.io/baseline-policy created
Now, try to create a Deployment with a privileged container. First create the Deployment, then patch it to add privileged: true to the pod template:
deployment.apps/privileged-deploy created
Now try to patch it to add a privileged security context:
Error from server: admission webhook "validate.kyverno.svc-fail" denied the request:
resource Deployment/default/privileged-deploy was blocked due to the following policies
baseline-policy:
baseline: 'Validation rule ''baseline'' failed. It violates PodSecurity "baseline:latest":
(Forbidden reason: privileged, field error list: [spec.template.spec.containers[0].securityContext.privileged
is forbidden, forbidden values found: true])'
As you can see, the patch that adds privileged: true to the pod template is blocked because it doesn't comply with our Baseline Policy set on the cluster.
Clean up the Deployment:
deployment.apps "privileged-deploy" deleted