Codifying Kubernetes Security Without PodSecurityPolicy
When the Kubernetes Auth Special Interest Group announced that it would deprecate the PodSecurityPolicy (PSP) in Kubernetes 1.21, and remove the API at version 1.25, a deep sigh was heard by developers and security pros around the world. All dramatics aside, policies are paramount to ensuring the security of your infrastructure and applications – the elimination of PSP has the potential to leave Kubernetes users vulnerable to attack through all too common misconfigurations and excessive permissions.
The original intent of PSP was to offer a built-in policy API that provided granular permissions on pod security settings. It is a cluster-level resource that controls security sensitive aspects of the pod specification. The PSP objects define a set of conditions that a pod must run with in order to be accepted into the system, as well as defaults for the related fields. This is important because not only are pods the basic building blocks of Kubernetes clusters, they’re also the most likely starting point for an attacker to compromise your software.
Although PSP was introduced in Kubernetes 1.3, it never left beta because of a few fundamental design flaws. There are several ways that policies can be applied, and as a result, it is not always clear which policy is applied to what namespace, user, or cluster – so it isn’t an easy task to validate a PSP in CI/CD. At its most granular, PSP applies to a namespace, and it isn’t currently possible to target a deployment, pod, ReplicaSet, etc. Further, it isn’t easy to dry-run or A/B test new policies or services, and PSPs don’t work well with auto-injected sidecars – a necessity for some services meshes or security solutions.
There are several proposals to fill the gap being examined, which generally focus on providing a base security policy that prevents the escalation of privileges while being easy to understand and debug. Rather than trying to satisfy everybody with a one-size-fits-all policy, the community is leaning toward the use of external policy enforcement, applied in development and/or runtime, for customized logic and more granular controls.
Leveraging Policy as Code and Security as Code to Secure Kubernetes
Taking a layered approach to Kubernetes security is important because, the reality is, mistakes happen and requirements change over time. The goal is to manage risk, which can be done by codifying security at every stage of development, starting with the provisioning of infrastructure through production and runtime. The best practice is to think about security before a single line of code is written, and to develop a threat model for the application being built to help guide your security policies.
In cloud native apps, the K8s configurations can be considered a form of Infrastructure as Code (IaC): a codified description of your infrastructure. With this in mind, and your threat model in place, you can begin to leverage Policy as Code (PaC) to codify your policies for improved consistency and automation with tools like the Open Policy Agent (OPA) and Terrascan, and Security as Code to take PaC a step further. PaC can also be leveraged at runtime, and common approaches include cronjobs or sidecar containers that scan the environment periodically, DaemonSets that gracefully ensure every node is running foundational pods such as storage and monitoring, and admission controllers that validate compliance before accepting configuration changes or that mutate requests to comply with policy. OPA Gatekeeper is a popular tool for enforcing PaC at runtime.
Cloud native development typically leverages DevOps approaches, using automation as a way to improve consistency and velocity. IaC and PaC are specifically designed to work well in these environments, enabling programmatic management of these complex, dynamic systems. Going beyond PaC, Security as Code can be leveraged for deep, proactive security assessment before deployment, and it can also be used to enable the runtime to detect and respond to violations in the context of an actual attack.
What's Next for Kubernetes PodSecurityPolicy
While a clear solution for PSP is not yet in sight, there are many ways to ensure the security of your pods – and ultimately, your organization. Options and flexibility are paramount, and including more than one control increases your options, which is why Kubernetes is able to deprecate PSP and rely instead on other available options.
By taking a Policy as Code and Security as Code approach, whether embedded in the K8s specifications as PSP was, or through other means, you have greater control over the configuration and security of your Kubernetes environment.
To learn more about how to apply Policy as Code and Security as Code to your Kubernetes systems in the absence of PSP, download the whitepaper, “4 Steps To Achieving Comprehensive Kubernetes Security.”