Containers are lightweight and efficient, but by design, they are limited in terms of access and control compared to traditional virtual machines or full Linux systems. This restricted environment enhances security, but sometimes, you may need more advanced control or permissions for specific operations inside a container. In this article, we will explore ways to elevate container capabilities, manage user privileges, and interact with security contexts in Kubernetes, while maintaining a secure environment.

Limitations of Containers

Containers isolate applications from the host system, but they also come with certain limitations. For example, basic operations like changing the hostname of a container or performing low-level system operations are restricted by default. These restrictions are part of the container's security model to prevent accidental or malicious actions from affecting the host system or other containers.

Using --privileged for Elevated Permissions

To bypass these limitations and perform operations such as altering the hostname or managing system configurations, you can run a container with elevated privileges using the --privileged flag. This flag grants the container access to all devices on the host and removes all limitations imposed by cgroups, enabling it to perform various operations that are otherwise restricted.

podman run --privileged -it <IMAGE>

This command launches the container with root-like access to the system, allowing full control over operations that require elevated privileges.

Running a Container as Root

By default, containers run as non-root users to enhance security. However, in some cases, you might need to run a container as the root user, especially when performing system-level tasks inside the container. You can specify the root user by using the --user=0 flag when launching a container.

podman run --user=0 -it <IMAGE>

This command ensures that the container runs with the root user (user ID 0), enabling full administrative capabilities within the container.

Dropping and Adding Capabilities in Containers

Linux capabilities are a fine-grained access control mechanism that allows users to execute certain privileged operations without granting full root access. By default, containers come with a limited set of capabilities to prevent over-privilege. However, you can drop or add specific capabilities to control what the container can or cannot do.

For example, to drop all capabilities except for NET_BIND_SERVICE (allowing the container to bind to privileged ports like 80 and 443), use the following command:

podman run --cap-drop all --cap-add NET_BIND_SERVICE -it httpd

This command removes all capabilities except for the one needed to bind to ports typically reserved for root.

Capabilities in Linux Systems

The concept of capabilities is not exclusive to containers; it is also fundamental in Linux systems. Every command that interacts with system resources requires specific capabilities. You can use the strace tool to inspect what system calls and capabilities are required by any command. For example, the following command will trace the ping command and show the required capabilities:

strace ping -c 1 8.8.8.8

This will display system calls and the necessary privileges for executing the command, providing insights into which capabilities are needed to perform various tasks.

Managing Security Context in Kubernetes Pods

In Kubernetes, containers run within pods, and the security context of the pod dictates what privileges the containers within it will have. You can adjust the security context to drop or add specific capabilities, allowing more fine-grained control over the operations allowed within the pod.

For example, to view and edit the security capabilities of a pod, you can use:

kubectl edit pod <POD_NAME>

This will open the pod's configuration, where you can modify the security context and specify additional capabilities or drop unwanted ones.

Script to Create a Pod with Custom Capabilities

Below is a script to create a Kubernetes pod and customize its security capabilities:

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  containers:
  - name: app-container
    image: nginx:latest
    securityContext:
      capabilities:
        add: ["NET_ADMIN", "SYS_TIME"]  # Adding required capabilities
        drop: ["ALL"]                   # Dropping all other capabilities
    ports:
    - containerPort: 80

This script creates a pod running the nginx web server while allowing only the NET_ADMIN and SYS_TIME capabilities. All other capabilities are dropped to minimize the security risk.

Viewing Pod Security Capabilities

To check the security capabilities of an existing pod, you can use the following command:

kubectl get pod <POD_NAME> -o yaml

This will show the pod's complete configuration, including its security context and any added or dropped capabilities.

Final Thoughts

Containers, by design, offer limited permissions to improve security. However, in some cases, you may need to adjust these permissions to perform advanced operations or ensure your application runs correctly. By understanding and managing container capabilities, both at the individual container and Kubernetes pod levels, you can strike a balance between functionality and security.

To further secure your containers, it is recommended to carefully manage the use of privileged flags and root accounts, drop unnecessary capabilities, and leverage Kubernetes' security contexts for fine-grained control.

For more information, refer to the official Kubernetes documentation on Pod Security Context.