Basic Kubernetes Security: A Hands-On Approach
In a continuation of the previous article, we explore the implementation of these different examples. Specifically, we will be covering workload separation, authentication, and other hardedning techniques. This article will have an example followed by a short explanation of what and why we should do that. We assume that the reader has a basic understanding of Kubernetes topics such as pods, service accounts, and secrets.
Read Only File-Systems
This will ensure that the root file system is only readable. However, if you wanted to create an area where a program is able to write to, you can do the following:
Where programs can utilize this mounted path to write during the container’s lifespan1.
Network Segmentation
Another layer of security you can add to your Kubernetes workload is controlling the boundaries of what pods can talk to each other. In order to accomplish this, you can use the built in NetworkPolicies
. However, this may differ based on whatever networking interface you are using. For now, we will use built in Kubernetes objects.
We will first start at the namespace level. For example, if you had your API servers in a namespace called api
and a front end server running in the namespace called fe
, you can create those as follows:
kubectl create namespace api
and kubectl create namespace fe
. We can achieve a similar result with a file:
and then running kubectl apply -f <namespace.yaml>
. Now that we have our two namespaces, we can utilize a NetworkPolicy
to restrict communications:
Note that this only handles any communication from frontend’s side. You would have to apply a similar set of rules to the api
side as well to get the expected behavior. You are also able to blanket deny ingress or egress on a namespace too:
However, that is not all. Say you need more fine grained access control such as restricting pod to pod communication, then you can use labels and NetworkPolicies
to accomplish that. We assume that there are two pods, labelled with app=frontend
and app=backend
. Down below, we create the specification for a frontend pod to allow communication with a backend pod. You will do something similar in the inverse scenario too.
Finally, if you wanted to add one more layer, you are able to restrict based on the port number too–only allowing communication on certain ports:
A Primer into Roles
Roles can get fairly complicated with its functionality extending far beyond the traditional Kubernetes primitives. In this article, we only go over a short brief overview of Roles with a simple example.
Roles in Kubernetes can be broken down into two main categories (with definitions coming from the official documentation):
- Roles: A Role always sets permissions within a particular namespace; when you create a Role, you have to specify the namespace it belongs in.
- Cluster Roles: A Cluster Role has the same functionality as a Role, however, it is not restricted to a single namespace.
In this tutorial, we will only cover roles. Let us first create a basic role that allows anyone assuming that role to read secrets inside of Kubernetes:
In order for a role to be assumed by an entity, we need to create something known as a RoleBinding
(or a ClusterRoleBinding
)2:
A RoleBinding
is a Kubernetes resource that connects (or “binds”) a Role or ClusterRole
to specific users, groups, or service accounts within a particular namespace.In the example above, we want to bind the test-user permission to read a secret (the secret-reader
role).
However, RoleBindings
are not limited to just users, you are also able to bind them to workloads as well. Let us assume we have a pod that needs to read a secret. We can allow the pod to do so by first creating a service account:
We can then create a RoleBinding
for the service account:
Just like that, any pod that has assumed the service account is able to read that secret.
Conclusion
In this article, we covered topics such as creating read-only file systems in pods, segmenting networks, and basic roles. While this is only a brief overview, there remains so much more in securing and hardening Kubernetes workloads.