Estoy trabajando en un proyecto que implementa simulaciones distribuidas: el código arbitrario se ejecuta en múltiples nodos y los resultados luego se recopilan y se agregan.
Cada nodo es una instancia de una máquina virtual Ubuntu Linux y ejecuta un proceso maestro que se encarga de reenviar el código para que se ejecute a varios procesos de trabajo (1 para cada núcleo).
Esta pregunta trata sobre cómo asegurarse de que cada trabajador opere en un entorno de espacio aislado sin recurrir al uso de una instancia de máquina virtual para cada uno de ellos. Los requisitos exactos para los trabajadores son:
- fs : sin permiso de escritura, permiso de solo lectura limitado a un solo directorio (y subcarpetas)
- net : solo se permiten comunicaciones locales (IPC, TCP, lo que sea ...)
- mem : límite de uso de memoria (sin memoria de intercambio) matar si supera el límite de memoria
- CPU : solo se permite 1 núcleo, matar si se supera el límite de tiempo
No se deben imponer otras limitaciones: el trabajador debe poder cargar bibliotecas dinámicas (desde la carpeta de solo lectura), generar nuevos subprocesos o procesos, llamar a la función del sistema, ecc ecc, pero los límites deben ser heredados por las entidades generadas / cargadas y debe aplicarse de manera sumaria (por ejemplo, no podemos hacer que un trabajador genere dos subprocesos que usan 800 MB cada uno, el límite de memoria para ese trabajador es de 1 GB).
No hace falta decir que no debería haber forma de que el trabajador eleve sus derechos.
Pasé un tiempo considerable revisando las alternativas disponibles (SELinux, AppArmor, cgroups, ulimit, espacios de nombres de Linux, LXC, Docker, ...) para encontrar la solución más simple que satisfaga mis requisitos, pero mi experiencia en el campo es limitada.
Conocimiento actual: LXC y Docker son un poco pesados para mi caso de uso y no son completamente seguros 1 . AppArmor preferible a SELinux debido a una configuración más fácil, utilícelo para fs y restricciones de red; cgroups preferible a ulimit (que opera en un solo proceso), lo usó para restricciones mem y cpu.
¿Es esta la forma más sencilla de lograr mi objetivo? ¿Puedo usar AppArmor o cgroups exclusivamente? ¿Hay algún agujero de seguridad obvio en mi modelo? La directriz debería ser "trabajador autorizado para derribar a sí mismo, pero nada más" .