Protecting Containers with ZeroLock®

The following document describes how the ZeroLock® agent interacts with containers running on Linux® systems. This document addresses a deployment model where ZeroLock agents are deployed on a baremetal Linux OS or Linux VM that has containers running inside of it. In this scenario, a single ZeroLock agent is responsible for protecting a single OS or VM and all containers running on it. This protection extends to containers managed in an orchestrated environment, such as Kubernetes, as well.


Linux Container Basics

Figure 1: ps -e output
Figure 1: ps -e output

Basic knowledge of how containers are implemented on Linux is helpful to understand how ZeroLock interacts with containers. Every executable that is instantiated on a Linux system runs as a process. Processes are actively running executables that have their own virtual address space. Figure 1 shows how processes can be listed on a Linux system using the command ps.

Additionally, Linux has a concept, namespaces, that allows processes to have unique, restricted views of OS resources. Resources that can be restricted by namespaces include but are not limited to the filesystem, network stack, and active processes. Figure 2 shows an example listing of namespaces on a Linux system using the command lsns.

Namespaces with the type “mnt” are mount namespaces that provide processes with unique views of the filesystem, namespaces with the type “net” are network namespaces that restrict what ports and IP addresses a process may use, and namespaces with the type “pid” are process namespaces that restrict what other processes a process can see.

In Linux, containers are implemented using namespaces. Thus, containers are collections of processes that belong to a namespace which provides them with a special, restricted view of OS resources.

Figure 2: lsns output
Figure 2: lsns output

ZeroLock and Containers

The ZeroLock agent consist of two major components: Tyr and Baldur. Baldur is where all the detection and response intelligence is located. Tyr is responsible for ensuring Baldur is healthy, sending commands to Baldur, and receiving telemetry from Baldur.

Baldur detects threats by monitoring the processes running on a system. Baldur is capable of monitoring processes on a Linux system because it injects code into their address space that installs hooks which trigger when certain system calls are executed. Example system calls that Baldur monitors include execve, open, and connect. Baldur also monitors the assembly instructions executed by processes on a Linux system. Containers are simply collections of processes that have special namespaces, so Baldur takes the same approach to monitoring them as any other process running on a Linux system.

Processes are constantly starting up and shutting down on Linux systems. Baldur monitors when processes are instantiated and exit. Because containers are just collections of processes, the ephemeral nature of containers does not have adverse effects on Baldur or alerts produced by Baldur.

Figure 3: ZeroLock Agent Architecture

Figure 3: ZeroLock Agent Architecture

Figure 4: Container and Image Filesystems Located in /var/lib/docker/overlay2
Figure 4: Container and Image Filesystems Located in /var/lib/docker/overlay2

Baldur is “container-aware” meaning that when it monitors processes in containers, it takes note of their container ID and where the root of the container’s filesystem is located. For example, the filesystems for Docker containers and Docker container images are stored in the directory /var/ lib/docker/overlay2. Baldur uses this filesystem information when it remediates threats and can restore the filesystem of an attacked container to its clean pre-attack state.

This container-specific data is aggregated and presented to users in the ZeroLock UI. If an attack occurs inside a container, the container ID is listed at the top of the alert details page.

Figure 5: Container ID in Alert Details Header

Figure 5: Container ID in Alert Details Header

If a specific process in an alert’s process tree is selected by a user, detailed information about that process is provided. This detail includes the container ID if one is present.

Figure 6: Container ID in Alert Details

Figure 6: Container ID in Alert Details

ZeroLock includes a container-aware agent that works seamlessly alongside containerized workloads. ZeroLock provides frictionless container support because, ultimately, containers are just collections of normal Linux processes that have a few special attributes provided by Linux namespaces. ZeroLock tracks those attributes and displays relevant data, such as container IDs, to users in an easy-to-understand format.

ZeroLock and Container Orchestration

“Does ZeroLock work with Kubernetes?” is one of the most common questions when discussing how ZeroLock protects containers. To answer that question, it is important to understand the relationship between containers and orchestration tools, such as Kubernetes, RedHat OpenShift, Rancher/SUSE, VMWare Tanzu, and other similar orchestration tools. For the purposes of this example Docker and Kubernetes will be used.

Think of containers as standardized packaging for microservices with all the needed application code and dependencies inside. Creating these containers is the domain of a tool such as Docker. A container can run anywhere, on a laptop, in the cloud, on local servers, and even on edge devices. Docker tools integrate with code repositories and continuous integration and continuous delivery (CI/CD) pipeline tools to make container operations repeatable and accessible.

A modern application typically consists of many containers potentially allocated across different hardware, networks, or physical locations. Operating containers in production is the job of the orchestration tools, such as Kubernetes. Since containers are easy to replicate, they allow applications to auto-scale: expand or contract processing capacities to match demands made on the application.

Kubernetes is responsible for deploying and managing containerized applications. An application can consist of a few to hundreds of containers that all work together, talk to each other, and must handle increases and decreases in demand. These multiple containers run on multiple hosts (or clouds) called nodes, and multiple nodes are connected to form a cluster. To be successful, Kubernetes needs to manage these aspects of an application:

  • Container deployment: retrieving container images and deploying it on a node, recreating failed containers, manage the lifecycle of the container
  • Scaling: adding more containers, or reducing the number of containers within clusters based on available resources to meet the demands placed on the application
  • Networking: ensuring all the containers that make up an application can communicate securely, services that require external access are properly exposed, distribute traffic across multiple nodes
  • Observability: track and report on the health of the containers, nodes, clusters, and overall application
  • Security: encrypting traffic, secret stores, integration into a comprehensive DevSecOps approach

Kubernetes is responsible for managing containers within an environment. ZeroLock protects containers as they are deployed, either from the nodes the containers run on, or from within the containers themselves. ZeroLock’s container protection capabilities allow it to seamlessly protect containers running in Kubernetes clusters. After all, a container running in a Kubernetes cluster is still just a container!