How to Secure Kubernetes, the OS of the Cloud
As infrastructures and workloads transition to cloud and teams adopt a CI/CD development process, there is a new paradigm shift: infrastructure is becoming code. This approach of treating infrastructure as code (IaC) is incredibly powerful, brings us many advantages, and enables transformative concepts like immutability. We define infrastructures in a declarative way and version them using the same source code control tools (in particular git) that we use for our application code. Spinning a new instance and deploying an operating system (i.e., spinning up a new container) all happen declaratively in git, and are deployed in the boundaries of the Kubernetes cluster.
This trend change also puts more responsibility in the developers’ hands, as the person who controls the Kubernetes and git controls the infrastructure, application, and policy. And since developers usually own the git and define their services as Yamls, in practice, it has become their responsibility. All that is required is a change of a Yaml in a GitOps repo and the pipeline will take it from there.
However, it also introduces a new category of risks. When our infrastructure is code, it can include bugs and oversights that become vulnerabilities, and can also enable malicious actors to perform dangerous actions. Adopting IaC does not automatically mean more security; in contrast, it could potentially mean a bigger attack surface. As a result, security needs to evolve and take this new paradigm into account.
To start, we need to recognize that protecting our infrastructure definitions is imperative, just like protecting our code. And this requires a “shift left” in how we secure our infrastructures, identifying risks as they enter the git, ideally by forcing a pull request check before it is merged.
Kubernetes Is the Operating System of the Cloud; Security Must Shift Further Right
Another undeniable industry trend is the use of containers and Kubernetes. Organizations big and small are adopting Kubernetes as the platform to run their applications. As the Linux operating system orchestrates processes on a physical or virtual piece of hardware, Kubernetes orchestrates services on a distributed computing pool.
As Linux grew into powering pretty much everything, from tiny IoT devices to supercomputers, we expect Kubernetes to gradually power all of the distributed software applications in the world. And, since the world is going to the cloud, we like to define Kubernetes as the operating system of the cloud.
Kubernetes offers a rich, sophisticated environment that makes scaling applications easy. At the same time, applications running on Kubernetes tend to be composed of tens, hundreds, or sometimes thousands of services that depend not only on each other, but on many different cloud resources.
This increases complexity and, with it, risk. This type of risk is not easily containable with “shift left” security tools that focus on code scanning and image scanning, because these static techniques cannot completely capture the explosion of combinations and the interdependent nature of microservice-based apps. Securing Kubernetes requires deep runtime security and strong runtime service context. It requires that we shift security right.
Shift Left? Shift Right?
So where does this leave us? Trends like IaC point to the need to shift left and validate infrastructure definitions as soon as they are committed to a git repository. The complexity of Kubernetes requires deep visibility and context at runtime. What is the correct approach?
The right answer, of course, is shift left and shift right!
With this approach, you have a single source of truth across IaC and runtime. When we talk about “source,” we are referring to both the physical source file stored in the git repo (Yamls, Terraforms, Helm charts, and/or Kustomizations), and the source for the runtime configurations eventually deployed to the Kubernetes cluster. Securing the former will have the desired direct impact on the latter, resulting in a more secure runtime environment. However, you must have runtime security in place to spot drift from the IaC source configuration file and detect anomalous activity.
Marrying IaC and runtime security creates opportunities to strengthen security even more. The context collected while the application runs (e.g., Which services talk to each other? Which users access the production environment?) can be used to inform policy creation. Policies can be automatically enforced across the infrastructure by leveraging gitops, making the runtime more secure. Manual work and human error are removed, and attack surface is reduced at the same time.
Security from Source Through Production
A truly complete platform for modern secure DevOps must combine these dimensions in a comprehensive and balanced way. Shifting security to the early stages of the development pipeline is a mandatory and widely accepted practice today, and we need to aggressively expand it to IaC. But this must be supported by strong and precise protection at runtime.
This is a virtuous cycle that can only happen when shift left and shift right support each other, which we are convinced is the future of security.