¿Cómo asegurar Docker para el entorno de producción?

Veamos cómo reforzar y proteger Docker para el entorno de producción.

Aunque Docker ha hecho posible que los desarrolladores de software y los ingenieros de DevOps construyan e implementen aplicaciones rápidamente, también viene con una gran superficie de ataque para que los piratas cibernéticos aprovechen.

Veremos cómo proteger un Docker en una plataforma Linux a partir de lo siguiente.

Defectos de configuración Ejecución remota de código Desbordamientos de búfer Falsificación de imágenes, etc.

Haremos uso de las siguientes herramientas, como el servidor notarial de Docker para firmar imágenes y la seguridad de banco de Docker para verificar el host, la configuración del demonio, etc.

Antes de proceder a asegurar, vamos a tocar los conceptos básicos.

¿Qué es una Tecnología de Contenedores?

La tecnología de contenedores permite a los desarrolladores o ingenieros de DevOps empaquetar una aplicación para que pueda ejecutarse con dependencias aisladas de otros procesos.

Hay una serie de tecnologías de contenedores en el mercado, como Apache Mesos, Rocket, lxc y Docker. Aunque caen dentro de la categoría de tecnología de contenedores, funcionan de manera diferente.

Diferencia entre VM y VE

Un host de máquina virtual es completamente diferente de un host de entorno virtual. En las máquinas virtuales, cada aplicación en contenedor viene con su propio conjunto de bibliotecas y sistema operativo, mientras que las aplicaciones, de forma predeterminada, en un host de entorno virtual como lxc y docker comparten el kernel de Linux.

¿Qué es Docker?

Docker es una tecnología de contenedores utilizada por millones para crear una aplicación web e implementarla desde un entorno de prueba a uno de producción.

Motor acoplable

El Docker Engine se compone de tres componentes.

Un servidor: este componente es un proceso o demonio de larga ejecución responsable de administrar imágenes y contenedores. REST API: esta interfaz hace posible que el demonio de Docker y la herramienta de cliente de Docker se comuniquen. Herramienta de cliente de Docker: la herramienta de cliente de Docker utiliza el componente REST API para informar al demonio de Docker que opere una aplicación en contenedores.

Registro de confianza de Docker

Docker Trusted Registry es una solución de almacenamiento de imágenes de Docker para el negocio de plataformas empresariales. Es diferente del docker hub. Mientras que Docker Hub está alojado en la nube, el registro de confianza de Docker es una solución de almacenamiento local para la edición empresarial de Docker.

Confianza de contenido de Docker

Docker Content Trust brinda la capacidad de usar firmas de datos para imágenes enviadas y recibidas hacia y desde registros remotos de Docker, como Docker Hub.

Espacios de nombres de Linux

Los espacios de nombres de Linux son una característica del kernel de Linux que aísla una aplicación o proceso en contenedor que se ejecuta en un host de entorno virtual de otros procesos.

Grupos de control de Linux (Cgroups)

Los grupos de control de Linux son una función del kernel de Linux que le permite asignar recursos, como tiempo de CPU, ancho de banda de red, memoria del sistema, etc., a procesos activos en un host.

Capacidades

En Linux, hay una función de seguridad en el subsistema del kernel que se puede configurar o aplicar para limitar el proceso privilegiado, como un proceso ejecutado por un usuario con UID 1. Aunque los procesos o usuarios privilegiados pueden eludir los permisos de control de acceso discrecional, no pueden eludir reglas de capacidades.

Ahora centrémonos en la seguridad.

Protección del host de Docker

En esta sección, veremos cómo asegurar el host donde reside Docker.

Escaneo del kernel de Linux

Antes de alojar una ventana acoplable en una plataforma Linux, primero debe inspeccionar el kernel. Existen varias herramientas de código abierto, como Lynis y OpenVAS, que puede usar para escanear el kernel de Linux.

Copie o clone el proyecto Lynis desde Github usando el comando git clone.

git clone https://github.com/CISOfy/lynis.git

Luego, use el siguiente comando para navegar al directorio lynis y auditar el sistema Linux.

cd lynis; ./lynis audit system

endurecer el kernel de Linux

Después de escanear el kernel de Linux en busca de vulnerabilidades basadas en el sistema, puede agregar otra capa adicional de protección al kernel a través de grsecurity. Proporciona funciones de seguridad como las siguientes.

Prevención de explotación de desbordamiento de búfer/prevención de vulnerabilidad de carrera tmp/restricciones de proc que no filtran información sobre los propietarios de procesos. Prevención de la ejecución de código arbitrario en el kernel, etc.

Inicialmente, puede descargar parches de forma gratuita desde grsecurity y aplicarlos a su kernel actual. Pero ya no permite parches gratuitos.

Instalar Docker en una máquina virtual

En lugar de instalar Docker directamente en un host Linux, puede agregar una capa adicional de protección al instalarlo dentro de una máquina virtual. Al hacerlo, incluso si hay un problema de vulnerabilidad con el núcleo del host, no afectará a los contenedores acoplables.

Protección de los privilegios de raíz

De forma predeterminada, Docker requiere privilegios de root para crear y administrar contenedores. El script malicioso puede aprovechar esta superficie de ataque para escalar a un superusuario en un host Linux y eventualmente acceder a archivos/carpetas confidenciales, imágenes, certificados, etc.

Para evitarlo, podemos hacer uso del siguiente comando. Podemos decidir descartar capacidades como setgid y setuid para evitar que otros programas o procesos cambien su GID a otro GID, lo que puede resultar en una escalada de privilegios. También puede consultar aquí para obtener una lista de definición de capacidades de Linux.

El siguiente comando ejecuta el contenedor del servidor web apache y descarta las capacidades setgid y setuid a través de –cap-drop para evitar que el contenedor apache cambie su GID y UID a otro UID y GID.

GID y UID en este contexto se refieren a ID de grupo e ID de usuario respectivamente.

docker run -d --cap-drop SETGID --cap-drop SETUID apache

Usuario acoplable

Además de evitar otros programas o procesos, también puede crear un usuario para administrar las operaciones de la ventana acoplable, como la ejecución de la ventana acoplable, en lugar de administrarlo a través de un superusuario.

Puede agregar o crear un usuario de docker a través de lo siguiente:

sudo groupadd docker

El comando anterior crea un grupo llamado ventana acoplable

A continuación, cree un usuario con el siguiente comando:

sudo useradd mike

Finalmente, use el siguiente comando para agregar un usuario mike a la ventana acoplable del grupo para administrar las operaciones de la ventana acoplable.

sudo usermod  -aG docker mike

Gestión de contenedores con Cgroups

En un entorno de producción, puede tener más de un contenedor.

Si no tiene cgroups instalado en su host, puede usar el siguiente comando para instalarlo y luego consultar aquí (para Ubuntu) sobre cómo configurarlo.

sudo apt-get install cgroup-bin cgroup-lite cgroup-tools cgroupfs-mount libcgroup1

Podemos asignar los contenedores a recursos de CPU limitados a través de –cpu-shares y –cpuset-cpus

El siguiente ejemplo de comando muestra que el proceso del contenedor prodnginx se ejecuta solo en el primer núcleo a través de –cpuset-cpus y se asignan 20 CPU a través de –cpu-shares mientras que el proceso del contenedor proxnginx se ejecuta en los primeros dos núcleos de CPU y también se asignan 20 UPC.

docker run -d --name prodnginx --cpuset-cpus=0 --cpu-shares=20 nginx
docker run -d --name testnginx --cpuset-cpus=2 --cpu-shares=20 nginx

Luego escriba el comando docker stats para ver el uso de la CPU por parte de los contenedores prodnginx y testnginx

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O
845bea7263fb        prodnginx            57.69%              1.258MiB / 985.2MiB   0.13%               578B / 0B           1.33MB / 0B 
189ba15e8258        testnginx            55.85%              1.25MiB / 985.2MiB    0.13%               578b / 0B           1.33MB / 0B 

Es una buena idea definir recursos compartidos de CPU para un host docker cuando tiene más de un contenedor ejecutándose en él.

Gestión de contenedores con espacios de nombres

Un espacio de nombres puede evitar que los contenedores se ejecuten como usuarios privilegiados, lo que puede ayudar a evitar ataques de escalada de privilegios.

Podemos habilitar el espacio de nombres en la ventana acoplable haciendo uso de los archivos /etc/subuid y /etc/subgid como se muestra a continuación.

crear un usuario usando el comando adduser

sudo adduser dockremap

Configure un subuid para el usuario dockremap

sudo sh -c 'echo dockremap:400000:65536 > /etc/subuid'

Luego configure subgid para el usuario dockremap

sudo sh -c 'echo dockremap:400000:65536 > /etc/subgid'

Abra el archivo daemon.json y rellénelo con el siguiente contenido para asociar el atributo userns-remap al usuario dockremap

vi   /etc/docker/daemon.json
{ 

 "userns-remap": "dockremap"

}

Presione :wq para guardar y cerrar el archivo daemon.json y finalmente reinicie la ventana acoplable para habilitar los espacios de nombres en un host de la ventana acoplable

sudo  /etc/init.d/docker  restart

Protección del demonio Docker

También es necesario configurar el demonio de Docker para garantizar una comunicación segura entre el cliente de Docker y el demonio de Docker a través de TLS.

Use el siguiente comando para abrir el archivo daemon.json y copie y pegue el siguiente contenido (reemplace la IP con su actual) como se muestra a continuación

vi  daemon.json
{
  "debug": false,
  "tls": true,
  "tlscert": "/var/docker/server.pem",
  "tlskey": "/var/docker/serverkey.pem",
  "hosts": ["tcp://192.168.16.5:2376"]
}

Protección de los componentes de Docker

Veamos cómo hacer uso de herramientas como CodeNotary y notary server para firmar imágenes a fin de evitar la falsificación de imágenes. Además, también es necesario escanear imágenes solo para asegurarse de que las imágenes no estén llenas de vulnerabilidades.

Haremos uso del servidor notarial de Docker para firmar y verificar imágenes y usaremos Anchor Engine para escanear imágenes en busca de vulnerabilidades.

Verificar imágenes con Notario Server

Antes de que podamos utilizar el servidor Notary para firmar imágenes, debemos descargar e instalar docker-compose. Usaremos Docker Compose para configurar un servidor notarial.

Ejecute el siguiente comando para descargar la última versión de Docker Compose

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Aplique permisos ejecutables a docker-compose como se muestra a continuación

sudo chmod 700  /usr/local/bin/docker-compose

Puede probar si ha instalado correctamente docker-compose mediante el siguiente comando

docker-compose  --version

Ahora podemos instalar el servidor notarial a través de docker-compose

git clone https://github.com/theupdateframework/notary.git

El comando anterior clona o copia el servidor notarial del repositorio notarial. Inicie el servidor notarial y el firmante mediante los siguientes comandos:

docker-compose build
docker-compose up -d

Luego, copie los certificados de configuración y prueba en su directorio notarial local usando el siguiente comando

mkdir -p ~/.notary && cp cmd/notary/config.json cmd/notary/root-ca.crt ~/.notary

Ahora ejecute el siguiente comando para conectar el servidor notarial al cliente docker

export   DOCKER_CONTENT_TRUST=1
export  DOCKER_CONTENT_TRUST_SERVER=https://notaryserver:4443

Genere un par de claves de delegación a través del siguiente comando

docker trust key generate mike --dir ~./docker/trust          

Ahora vamos a crear nuevas claves de destino en caso de que el repositorio no exista.

docker trust signer add --key ~/.docker/trust/mike.pub mike mikedem0/whalesay

Luego, puede firmar la imagen de la ventana acoplable con el comando Signo de confianza de la ventana acoplable. Debe extraer la imagen de la ventana acoplable desde el centro de la ventana acoplable y volver a etiquetarla con el comando docker pull y la etiqueta de la ventana acoplable, respectivamente.

docker trust sign mikedem0/nginx:latest

También puede escanear imágenes acoplables en busca de vulnerabilidades y fallas de configuración. Puede consultar aquí para averiguar cómo usar Anchor Engine para buscar vulnerabilidades y Docker Bench Security para verificar fallas de configuración.

Espero que lo anterior le dé una idea sobre la seguridad de Docker para el entorno de producción. También puede consultar este curso de Udemy sobre piratería y protección de contenedores Docker.

Publicaciones relacionadas

Botón volver arriba