Docker und nix-shell als Sandbox

20. March 2022 Andreas Peters

In Zeiten wo es immer wieder vorkommt, dass Software Entwickler ihre Politischen Ansichten mithilfe von Vulnerablen Packages ausdrücken, muss man sich Gedanken darüber machen, wie die eigene Arbeit ab zusichern ist. Hierbei wäre es zu kurz gedacht, zu behaupten oder zu erwarten, sich jede einzelne Librarie anzuschauen und sicherheitstechnisch zu bewerten. Dies ist aufgrund der schieren Masse gar nicht möglich. Aus diesen Grund, wäre es sinnvoll den ggfs. auftretenden Schaden auf das Projekt zu begrenzen, was aktuell in Arbeit ist, so das der Arbeitsrechner und die darauf befindlichen Dokumente nicht betroffen sind. Mir schien hierbei eine Sandbox Umgebung mit Hilfe von Docker und nix-shell sehr sinnvoll. Mit den folgenden Schritten möchte ich kurz aufzeigen wie dies umzusetzen ist.

Docker Image mit nix-shell

Erstellen wir uns ein einfaches Dockerfile welches “nix” erstellt und den User mit genau der User ID anlegt, welchen wir auch für unsere Entwicklung unter Linux verwenden.

FROM almalinux:8.4

# Get curl.
RUN dnf install -y dnf-plugins-core
RUN dnf install -y epel-release
RUN dnf config-manager --set-enabled powertools
RUN yum install -y              \
      curl                      \
      xz                        

ENV USER <myusername>
ENV USERGRP <myusergrp>
ENV USERID <myuserid>

RUN groupadd -g $USERID $USER
RUN groupadd nixbld
RUN useradd -g $USERGRP -G nixbld -u $USERID $USER
RUN mkdir -m 0755 /nix && chown $USER /nix

USER $USER

RUN curl -L https://nixos.org/nix/install | sh

COPY run.sh /run.sh

ENTRYPOINT ["/run.sh"]

Das “run.sh” bash file sieht wie folgt aus:

#!/bin/bash

source /home/$USER/.nix-profile/etc/profile.d/nix.sh

cd /data
$@

Dies dient zum laden der “nix” Umgebung.

Fehlt nur noch das builden des Images.

docker build -t docker-nix .

Initialisieren der Sandbox

Nun wo wir das Image gebaut haben, können wir dies einmal initial starten. Da die nix-shell noch nicht funktionsfähig ist, starten wir den Container mit “/bin/bash”.

sudo mkdir /nix
sudo chown <myusername>: /nix
docker run -v `pwd`:/data -v /nix:/nix --net host -it docker-nix /bin/bash

Im Container müssen wir nun einmalig “nix-shell” ein weiteres mal installieren. Dieser Schritt ist notwendig, da wir mit dem obigen “docker run”, dass im Image vorhandene “/nix” Verzeichnis “übermounten”.

curl -L https://nixos.org/nix/install | sh

Arbeiten mit der Sandbox

Um nun mit der Sandbox zu arbeiten, legen wir uns ein Shell Script im “.local/bin” Verzeichnis mit dem folgenden Inhalt an.

#!/bin/bash
docker run -v `pwd`:/data -u 1000:1000 -v /nix:/nix --net host -it docker-nix nix-shell

Nehmen wir an, wir haben ein Golang Projekt. Im entsprechenden Projektverzeichnis erstellen wir nun eine Datei namens “shell.nix”:

{ pkgs ? import <nixpkgs> { } }:

with pkgs;

mkShell {
  buildInputs = [
      go
    ];
}

Führen wir nun unser zuvor angelegtes Shell Script aus. Anschließend wird unser Docker Container gestartet, “nix-shell” ausgeführt welches wiederum Golang installiert.

Je nach benötigten Paketen, erstellen wir Projekt abhängig eine “shell.nix”. So installieren wir in “ansible” oder “python37” Projekten nur die dafür benötigten Pakete mittels nix. Wird nun eines der verwendeten Libraries vulnerable, betrifft es lediglich das über “docker run” gemountete Projekt.