Container mit AppArmor schützen

AppArmor ist ein Kernel-Sicherheitsmodul unter Linux, mit dem Sie den Funktionsumfang von Prozessen beschränken können, die auf dem Host-Betriebssystem ausgeführt werden. Für jeden Prozess kann ein eigenes Sicherheitsprofil angelegt werden. Das Sicherheitsprofil erlaubt oder unterbindet bestimmte Funktionen, wie zum Beispiel den Netzwerkzugriff oder die Lese-/Schreib-/Ausführberechtigungen für Dateien.

AppArmor kann mit den Docker-Containern verwendet werden, die auf Ihren Container-Optimized OS-Instanzen laufen. Sie können für jeden Container wählen, ob Sie das standardmäßig in Docker enthaltene Sicherheitsprofil für AppArmor verwenden oder ein benutzerdefiniertes Sicherheitsprofil zur Verfügung stellen möchten.

Standardmäßiges AppArmor-Sicherheitsprofil von Docker verwenden

Wenn Sie einen Container auf Ihrer Container-Optimized OS-Instanz starten, wendet das System automatisch das AppArmor-Sicherheitsprofil docker-default an. Mit dem folgenden Beispielbefehl wird ein Container mit dem Sicherheitsprofil docker-default ausgeführt:

docker run --rm -it debian:jessie bash -i

Zum Testen des Sicherheitsprofils docker-default können Sie die Datei /proc/sysrq-trigger mit dem Befehl cat folgendermaßen lesen:

root@88cef496c1a5:/# cat /proc/sysrq-trigger

Daraufhin sollte eine "Zugriff verweigert"-Fehlermeldung ähnlich der Folgenden ausgegeben werden:

cat: /proc/sysrq-trigger: Permission denied

Benutzerdefiniertes Sicherheitsprofil verwenden

Wenn Sie ein anderes Sicherheitsprofil anwenden möchten, verwenden Sie beim Ausführen des Containers die Befehlszeilenoption apparmor=<profile-name>. Mit dem folgenden Beispielbefehl wird ein Container mit einem Sicherheitsprofil namens no-ping ausgeführt:

docker run --rm -i --security-opt apparmor=no-ping debian:jessie bash -i

Weitere Informationen zum Erstellen des im Beispiel angegebenen no-ping-Profils finden Sie unter Benutzerdefiniertes Sicherheitsprofil erstellen weiter unten.

Sie können unconfined auch mit der Option apparmor angeben, um anzugeben, dass der Container mit keinem Sicherheitsprofil ausgeführt werden soll, wie im folgenden Beispiel:

docker run --rm -it --security-opt apparmor=unconfined debian:jessie bash -i

Aktive AppArmor-Sicherheitsprofile anzeigen

Sie können sehen, welches AppArmor-Profil, falls zutreffend, auf die Prozesse in Ihrer Container-Optimized OS-instanz angewendet wird, indem Sie die Datei /proc/<pid>/attr/current überprüfen, wobei <pid> die Prozess-ID ist.

Angenommen, auf der Instanz werden die folgenden Prozesse ausgeführt (angezeigt durch den Befehl ps -ef | grep '[b]ash -i'):

root      1903  1897  0 21:58 pts/3    00:00:00 docker run --rm -it debian:jessie bash -i
root      1927  1913  0 21:58 pts/4    00:00:00 bash -i
root      1978  1001  0 22:01 pts/0    00:00:00 docker run --rm -it --security-opt apparmor=unconfined debian:jessie bash -i
root      2001  1988  0 22:01 pts/2    00:00:00 bash -i

Wenn Sie /proc/1927/attr/current prüfen, sollten Sie die folgende Ausgabe sehen, die angibt, dass der Prozess (pid 1927) mit dem standardmäßigen Docker-Sicherheitsprofil ausgeführt wurde:

# cat /proc/1927/attr/current
docker-default (enforce)

Wenn Sie /proc/2001/attr/current überprüfen, sollte die folgende Ausgabe angezeigt werden, die angibt, dass der Prozess (pid 2001) mit keinem Sicherheitsprofil ausgeführt wurde (dh mit der Option apparmor=unconfined):

# cat /proc/2001/attr/current
unconfined

Benutzerdefiniertes Sicherheitsprofil erstellen

Wenn für den Prozess ein anderes Sicherheitsprofil als docker-default erforderlich ist, können Sie Ihr eigenes benutzerdefiniertes Profil schreiben. Um es zu verwenden, erstellen Sie die Profildatei und laden diese dann in AppArmor hoch.

Nehmen wir an, Sie möchten beispielsweise ein Sicherheitsprofil, das den gesamten primären Netzwerkverkehr blockiert. Das folgende Skript erstellt eine Datei für ein Sicherheitsprofil mit der Bezeichnung no-ping unter /etc/apparmor.d/no_raw_net:

cat > /etc/apparmor.d/no_raw_net <<EOF
#include <tunables/global>

profile no-ping flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>

  network inet tcp,
  network inet udp,
  network inet icmp,

  deny network raw,
  deny network packet,
  file,
  mount,
}
EOF

Nachdem Sie die Sicherheitsprofildatei erstellt haben, können Sie das Profil mit apparmor_parser in AppArmor laden:

/sbin/apparmor_parser --replace --write-cache /etc/apparmor.d/no_raw_net

Nach dem Laden können Sie das no-ping-Profil folgendermaßen testen:

$ docker run --rm -i --security-opt apparmor=no-ping debian:jessie ping -c3 8.8.8.8

Der Befehl erstellt einen Container mit dem Sicherheitsprofil no-ping und versucht, ping innerhalb des Containers auszuführen. Das Sicherheitsprofil sollte den Datenverkehr unterbinden, was zu einem Fehler wie diesem führt:

ping: Lacking privilege for raw socket.

Damit Ihr benutzerdefiniertes Sicherheitsprofil beim Start der Container-Optimized OS-Instanz vorhanden ist und auch nach einem Neustart beibehalten wird, können Sie das Profil mit cloud-init in /etc/apparmor.d installieren. Fügen Sie dazu den Metadaten Ihrer Instanz ein cloud-config-Skript als Wert des Schlüssels user-data hinzu.

Mit dem folgenden cloud-config-Skript wird /etc/apparmor.d das Profil no-ping hinzugefügt:

#cloud-configs

write_files:
- path: /etc/apparmor.d/no_raw_net
  permissions: 0644
  owner: root
  content: |
    #include <tunables/global>

    profile no-ping flags=(attach_disconnected,mediate_deleted) {
      #include <abstractions/base>

      network inet tcp,
      network inet udp,
      network inet icmp,

      deny network raw,
      deny network packet,
      file,
      mount,
    }

Sie können sicherstellen, dass die Datei das benutzerdefinierte Profil in AppArmor lädt und Docker anweist, es zu benutzen, indem Sie die folgenden Befehle auf Ihrer Instanz ausführen:

ExecStartPre=/sbin/apparmor_parser -r -W /etc/apparmor.d/no_raw_net
ExecStart=/usr/bin/docker run --security-opt apparmor=no-ping ...

Starten Sie die Instanz neu, nachdem Sie die Befehle ausgeführt haben, damit Sie anschließend den Container mit den Beschränkungen des benutzerdefinierten AppArmor-Profils ausführen können.