<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=521127644762074&amp;ev=PageView&amp;noscript=1">

Kubernetes Basics Tutorial: Ensure Containers Do Not Run As Root

A container is a unit of software that brings code and all of its dependencies together, making it possible to run the application quickly and reliably in different computing environments. Docker containers are standalone, lightweight software packages that include everything you need to run an app, including code, system tools, system libraries, runtime, and settings. Container images become containers at runtime, and containerized software runs the same way in any infrastructure. They’re called containers because they’re contained — they isolate the software from the environment, and they’re designed to run uniformly. Kubernetes, of course, is an open-source container orchestration system. It automates software deployment, scaling, and management. Kubernetes uses pods as the smallest deployable unit, but every pod must contain one or more containers. In other words, you can’t really have Kubernetes without containers.

That’s why it’s so important to understand container security and how the permissions of your containers can impact your Kubernetes workloads. The National Security Agency’s Kubernetes Hardening Guide specifically advises organizations to use containers that have been built to run applications as non-root users. Frequently (and by default), many container services run as the privileged root user, even though these apps don’t require privileged execution. As you’re working to harden your Kube environment, you need to spend some time investigating which containers are running as root and then make changes to prevent root execution so you can limit the impact of a container compromise.

Detecting containers allowed to run as root

Polaris is an open source project that validates Kubernetes configuration. It includes a built-in check specifically for detecting containers that are allowed to run as root. You can use Polaris to help you ensure that your containers are running with minimal privileges. Polaris policies can help you avoid privilege escalation and make sure that you are using read only file systems wherever possible.

Remediating the issue

To remediate the issue of containers running as root, you need to set securityContext.runAsNonRoot=true.

This can be set at either the container level (in which case it needs to be set for all containers) or at the pod level (where it will become the default for all containers).

If the corresponding container is currently running as the root user, you will also need to do one of the following to change it to run as a non-root user:

  • set securityContext.runAsUser to a non-zero integer
  • add a line to your Dockerfile setting the user, for example: USER 1000

Examples

At the pod level

apiVersion: v1
kind: Pod
metadata:
 name: security-context-demo
spec:
 securityContext:
   runAsNonRoot: true
   runAsUser: 1000

At the container level


apiVersion: v1
kind: Pod
metadata:
 name: security-context-demo
spec:
 containers:
 - name: busybox
   image: busybox
   securityContext:
     runAsNonRoot: true
     runAsUser: 1000

To add the security context parameter, you usually need to go to the source of your resource definition. This may be a Helm values file or a flat manifest file that you have in your repo, depending on how you deploy things in your environment.

If there are no non-root users in the Docker image, you may also need to create one in the Dockerfile, with:

RUN useradd nonroot -u 1000 --user-group

If you're changing from a root user to a non-root user, be on the lookout for issues with things like file permissions; you may need to user chown and chmod in your Dockerfile to get things running properly.

How do you fix the container?

If you have a container that can't run in your cluster you need to know how you can fix it. In your Docker file, you will probably want to create your own user and/or group and switch to that entity before you run your entrypoint or command arguments.This will make the container run as the user specified in your Dockerfile.

Alternatively, you can use the RunAsUser directive in your container specification. The value for this key must be a user ID, and the user ID also needs to be a user that exists in the container. Keep in mind that when you run your container as NonRoot you will want to make sure that the user you create has the right permissions to run the processes within your container.

Regardless of where you define the alternate non-root user, the recommendation is still to set the security context to RunasNonRootto increase the security of the container. If you're having trouble figuring out how to make your Kubernetes clusters more secure, reach out! We've built, secured, and managed hundreds of clusters for our clients.

Explore Managed Kubernetes

Originally published February 14, 2023.