Freigeben über


Sicherheitscontainerzugriff auf Ressourcen mithilfe integrierter Linux-Sicherheitsfeatures

In diesem Artikel erfahren Sie, wie Sie den Containerzugriff auf Ressourcen für Ihre Azure Kubernetes Service (AKS)-Workloads sichern.

Übersicht

Nicht nur Benutzern und Gruppen sollten lediglich die erforderlichen Mindestberechtigungen gewährt werden, auch Container sollten auf die Aktionen und Prozesse beschränkt werden, die unbedingt erforderlich sind. Konfigurieren Sie zur Minimierung des Angriffsrisikos nach Möglichkeit keine Anwendungen und Container, die ausgeweitete Berechtigungen oder Root-Zugriff benötigen.

Sie können integrierte Pod-Sicherheitskontexte in Kubernetes verwenden, um weitere Berechtigungen zu definieren, z. B. den Benutzer oder die Gruppe, die ausgeführt werden soll, die Linux-Funktionen, die verfügbar gemacht werden sollen, oder das Festlegen von allowPrivilegeEscalation: false im Pod-Manifest. Weitere Best Practices finden Sie unter Absichern des Podzugriffs auf Ressourcen.

Wenn Sie die Steuerungsmöglichkeiten für Containeraktionen noch feiner abstimmen möchten, können Sie dazu integrierte Linux-Sicherheitsfeatures wie AppArmor und seccomp verwenden.

  1. Definieren Sie Linux-Sicherheitsfeatures auf Knotenebene.
  2. Implementieren Sie Features über ein Podmanifest.

In Linux integrierte Sicherheitsfunktionen sind nur auf Linux-Knoten und -Pods verfügbar.

Hinweis

Derzeit sind Kubernetes-Umgebungen für die Verwendung feindlicher Workloads mit mehreren Mandanten nicht vollständig sicher. Mithilfe zusätzlicher Sicherheitsfeatures wie Microsoft Defender for Containers, AppArmor, seccomp, Pod Security Admission oder Kubernetes RBAC für Knoten können Exploits effizient blockiert werden.

Um echte Sicherheit bei der Ausführung feindlicher Workloads mit mehreren Mandanten zu erzielen, vertrauen Sie nur einem Hypervisor. Die Sicherheitsdomäne für Kubernetes wird zum gesamten Cluster und nicht zu einem einzelnen Knoten.

Für diese Art von feindlichen Workloads mit mehreren Mandanten sollten Sie physisch isolierte Cluster verwenden.

AppArmor

Mit dem Kernelsicherheitsmodul AppArmor von Linux können Sie Containeraktionen einschränken. AppArmor ist als Teil des zugrunde liegenden AKS Knotens des Betriebssystems verfügbar und standardmäßig aktiviert. Sie erstellen AppArmor-Profile, die Aktionen wie „Lesen“, „Schreiben“ oder „Ausführen“ oder Systemfunktionen wie das Einbinden von Dateisystemen beschränken. Standardprofile von AppArmor beschränken den Zugriff auf verschiedene /proc- und /sys-Speicherorte und ermöglichen es, Container logisch vom zugrunde liegenden Knoten zu isolieren. AppArmor funktioniert nicht nur mit Kubernetes-Pods, sondern zusammen mit jeder Anwendung, die auf Linux ausgeführt werden kann.

Verwendete AppArmor-Profile in einem AKS-Cluster, um Containeraktionen zu beschränken

In der folgenden Beispielverwendung von AppArmor wird ein Profil erstellt, das den Schreibzugriff auf Dateien verhindert.

  1. Stellen Sie eine SSH-Verbindung mit einem AKS-Knoten her.

  2. Erstellen Sie eine Datei mit dem Namen deny-write.profile.

  3. Kopieren Sie den folgenden Inhalt, und fügen Sie ihn ein:

    #include <tunables/global>
    profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
      #include <abstractions/base>
    
      file,
      # Deny all file writes.
      deny /** w,
    }
    

AppArmor-Profile werden mithilfe des apparmor_parser-Befehls hinzugefügt.

  1. Fügen Sie das Profil zu AppArmor hinzu.

  2. Geben Sie den Namen des im vorherigen Schritt erstellten Profils an:

    sudo apparmor_parser deny-write.profile
    

    Wenn das Profil ordnungsgemäß analysiert und auf AppArmor angewendet wurde, wird keine Ausgabe angezeigt, und Sie befinden sich wieder an der Eingabeaufforderung.

  3. Erstellen Sie auf Ihrem lokalen Computer ein Podmanifest namens aks-apparmor.yaml. Für dieses Manifest gilt Folgendes:

    • Es definiert eine Anmerkung für container.apparmor.security.beta.kubernetes.
    • Es verweist auf das Profil deny-write, das in den vorherigen Schritten erstellt wurde.
    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-apparmor
      annotations:
        container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
    spec:
      containers:
      - name: hello
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
    
  4. Führen Sie nach der Podbereitstellung den folgenden Befehl aus, und überprüfen Sie, ob der Pod hello-apparmor den Status Wird ausgeführt anzeigt:

    kubectl get pods
    
    NAME             READY   STATUS    RESTARTS   AGE
    aks-ssh          1/1     Running   0          4m2s
    hello-apparmor   0/1     Running   0          50s
    

Weitere Informationen zu AppArmor finden Sie im Kubernetes-Artikel AppArmor.

Sicheres Computing (seccomp)

AppArmor ist für jede Linux-Anwendung geeignet. Seccomp (Secure Computing, sicheres Computing) arbeitet dagegen auf Prozessebene. seccomp ist ebenfalls ein Kernelsicherheitsmodul von Linux und wird nativ von der containerd-Runtime unterstützt, die für AKS-Knoten verwendet wird. Mit seccomp können Sie die Systemaufrufe eines Containers einschränken. seccomp stellt eine zusätzliche Schutzebene vor gängigen Systemanrufrisiken her, die von böswilligen Akteuren ausgenutzt werden, und ermöglicht es Ihnen, ein Standardprofil für alle Workloads im Knoten anzugeben.

Konfigurieren eines standardmäßigen seccomp-Profils (Vorschau)

Sie können standardmäßige seccomp-Profile mit benutzerdefinierten Knotenkonfigurationen anwenden, wenn Sie einen neuen Linux-Knotenpool erstellen. Für AKS werden zwei Werte unterstützt: RuntimeDefault und Unconfined. Einige Workloads erfordern möglicherweise eine geringere Anzahl von Syscall-Einschränkungen als andere. Dies bedeutet, dass sie während der Laufzeit mit dem Profil „RuntimeDefault“ fehlschlagen können. Um einen solchen Fehler zu vermeiden, können Sie das Unconfined-Profil angeben. Wenn Ihre Workload ein benutzerdefiniertes Profil erfordert, lesen Sie Konfigurieren eines benutzerdefinierten seccomp-Profils.

Begrenzungen

  • SeccompDefault ist kein unterstützter Parameter für Windows-Knotenpools.
  • SeccompDefault ist ab 2024-09-02-Preview-API verfügbar.

Wichtig

AKS-Previewfunktionen stehen gemäß dem Self-Service- und Aktivierungsprinzip zur Verfügung. Vorschauversionen werden „wie besehen“ und „wie verfügbar“ bereitgestellt und sind von Service Level Agreements und der Herstellergarantie ausgeschlossen. AKS-Vorschauversionen werden teilweise vom Kundensupport auf Grundlage der bestmöglichen Leistung abgedeckt. Daher sind diese Funktionen nicht für die Verwendung in der Produktion vorgesehen. Weitere Informationen finden Sie in den folgenden Supportartikeln:

Registrieren des KubeletDefaultSeccompProfilePreview-Featureflags

  1. Registrieren Sie das Featureflag KubeletDefaultSeccompProfilePreview mithilfe des Befehls az feature register.

    az feature register --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    

    Es dauert einige Minuten, bis der Status Registered (Registriert) angezeigt wird.

  2. Überprüfen Sie den Registrierungsstatus mithilfe des Befehls az feature show.

    az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    
  3. Wenn der Zustand Registered (Registriert) lautet, aktualisieren Sie die Registrierung des Ressourcenanbieters Microsoft.ContainerService mithilfe des Befehls az provider register.

    az provider register --namespace Microsoft.ContainerService
    

Einschränken der Systemaufrufe Ihres Containers mit seccomp

1. Führen Sie die Schritte aus, um ein seccomp-Profil in Ihrer Kubelet-Konfiguration anzuwenden, indem Sie "seccompDefualt": "RuntimeDefault" angeben.

RuntimeDefault verwendet das seccomp-Standardprofil von containerD und schränkt bestimmte Systemaufrufe ein, um die Sicherheit zu verbessern. Eingeschränkte syscalls führen zu Fehlern. Weitere Informationen finden Sie im containerD-Standardprofil für seccomp.

2. Überprüfen Sie, ob die Konfiguration angewendet wurde.

Sie können bestätigen, dass die Einstellungen auf die Knoten angewendet werden, indem Sie eine Verbindung mit dem Host herstellen und überprüfen, ob Konfigurationsänderungen im Dateisystem vorgenommen wurden.

3. Behandeln von Workloadfehlern.

Wenn SeccompDefault aktiviert ist, wird das seccomp-Standardprofil der Containerruntime standardmäßig für alle Workloads verwendet, die auf dem Knoten geplant sind. Dies kann dazu führen, dass Workloads aufgrund blockierter Syscalls fehlschlagen. Wenn ein Workloadfehler aufgetreten ist, werden möglicherweise Fehler angezeigt, wie:

  • Die Workload ist unerwartet vorhanden, nachdem das Feature mit dem Fehler „Berechtigung verweigert“ aktiviert wurde.
  • Seccomp-Fehlermeldungen können auch in Überwachung oder Syslog angezeigt werden, indem SCMP_ACT_ERRNO durch SCMP_ACT_LOG im Standardprofil ersetzt wird.

Wenn die oben genannten Fehler auftreten, empfehlen wir, Ihr seccomp-Profil in Unconfined zu ändern. Unconfined legt keine Einschränkungen für Syscalls fest, sodass alle Systemaufrufe zugelassen werden, wodurch die Sicherheit reduziert wird.

Konfigurieren eines benutzerdefinierten seccomp-Profils

Mit einem benutzerdefinierten seccomp-Profil können Sie genauere Kontrolle über eingeschränkte Syscalls haben. Es empfiehlt sich, dem Container nur minimale Berechtigungen für die Ausführung zu erteilen. Gehen Sie dazu wie folgt vor:

  • Definieren Sie mithilfe von Filtern, welche Aktionen zugelassen oder verweigert werden sollen.
  • Verwenden Sie Anmerkungen innerhalb eines YAML-Podmanifests für die Zuordnung zum entsprechenden seccomp-Filter.

In der folgenden Beispielverwendung von Seccomp erstellen Sie einen Filter, der verhindert, dass Berechtigungen für eine Datei geändert werden können.

  1. Stellen Sie eine SSH-Verbindung mit einem AKS-Knoten her.

  2. Erstellen Sie einen seccomp-Filter mit dem Namen /var/lib/kubelet/seccomp/prevent-chmod.

  3. Kopieren Sie den folgenden Inhalt, und fügen Sie ihn ein:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "name": "chmod",
          "action": "SCMP_ACT_ERRNO"
        },
        {
          "name": "fchmodat",
          "action": "SCMP_ACT_ERRNO"
        },
        {
          "name": "chmodat",
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    

    Ab Version 1.19 muss Folgendes konfiguriert werden:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "names": ["chmod","fchmodat","chmodat"],
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    
  4. Erstellen Sie auf Ihrem lokalen Computer ein Podmanifest namens aks-seccomp.yaml, und fügen Sie den folgenden Inhalt ein. Für dieses Manifest gilt Folgendes:

    • Es definiert eine Anmerkung für seccomp.security.alpha.kubernetes.io.
    • Es verweist auf den Filter prevent-chmod, der im vorherigen Schritt erstellt wurde.
    apiVersion: v1
    kind: Pod
    metadata:
      name: chmod-prevented
      annotations:
        seccomp.security.alpha.kubernetes.io/pod: localhost/prevent-chmod
    spec:
      containers:
      - name: chmod
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command:
          - "chmod"
        args:
         - "777"
         - /etc/hostname
      restartPolicy: Never
    

    Ab Version 1.19 muss Folgendes konfiguriert werden:

    apiVersion: v1
    kind: Pod
    metadata:
      name: chmod-prevented
    spec:
      securityContext:
        seccompProfile:
          type: Localhost
          localhostProfile: prevent-chmod
      containers:
      - name: chmod
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command:
          - "chmod"
        args:
         - "777"
         - /etc/hostname
      restartPolicy: Never
    
  5. Stellen Sie den Beispielpod mithilfe des Befehls kubectl apply bereit:

    kubectl apply -f ./aks-seccomp.yaml
    
  6. Sehen Sie sich mithilfe des Befehls kubectl get pods den Podstatus an.

    • Der Pod gibt eine Fehlermeldung zurück.
    • Wie in der Beispielausgabe ersichtlich wird, wird das Ausführen des chmod-Befehls vom seccomp-Filter verhindert:
    kubectl get pods
    
    NAME                      READY     STATUS    RESTARTS   AGE
    chmod-prevented           0/1       Error     0          7s
    

Sicherheitsprofiloptionen für seccomp

seccomp-Sicherheitsprofile sind eine Reihe definierter Syscalls, die zulässig oder eingeschränkt sind. Die meisten Containerruntimes verfügen über ein seccomp-Standardprofil, das ähnlich, wenn nicht sogar gleich ist, wie das von Docker verwendete. Weitere Informationen zu verfügbaren Profilen finden Sie unter Docker- oder containerD-seccomp-Standardprofilen.

AKS verwendet das containerD-seccomp-Standardprofil für unsere RuntimeDefault, wenn Sie seccomp mithilfe der benutzerdefinierten Knotenkonfiguration konfigurieren.

Signifikante Syscalls, die durch das Standardprofil blockiert werden

Sowohl Docker als auch containerD pflegen Ausnahmelisten sicherer Syscalls. In dieser Tabelle sind die signifikanten (aber nicht alle) Syscalls aufgeführt, die effektiv blockiert werden, da sie nicht in der Ausnahmeliste enthalten sind. Wenn einer der blockierten Syscalls von Ihrer Workload benötigt wird, verwenden Sie nicht das seccomp-Profil RuntimeDefault.

Wenn Änderungen an Docker und containerD vorgenommen werden, aktualisiert AKS ihre Standardkonfiguration entsprechend. Aktualisierungen dieser Liste können zu Workloadfehlern führen. Versionsupdates finden Sie in den AKS-Versionshinweisen.

Blockierter Syscall Beschreibung
acct Rechnungssyscall, mit dem Container ihre eigenen Ressourcenbeschränkungen oder Prozessrechnungen deaktivieren können. Auch durch CAP_SYS_PACCT abgegrenzt.
add_key Verhindern Sie, dass Container den Kernel-Keyring verwenden, der keinem Namespace zugeordnet ist.
bpf Verweigern des Ladens potenziell persistenter bpf-Programme in Kernel, die bereits von CAP_SYS_ADMIN abgegrenzt werden.
clock_adjtime Uhrzeit/Datum ist keinem Namespace zugeordnet. Auch durch CAP_SYS_TIME abgegrenzt.
clock_settime Uhrzeit/Datum ist keinem Namespace zugeordnet. Auch durch CAP_SYS_TIME abgegrenzt.
clone Das Klonen neuer Namespaces verweigern. Auch durch CAP_SYS_ADMIN for CLONE_*-Flaggen mit Ausnahme von CLONE_NEWUSER abgegrenzt.
create_module Manipulation und Funktionen für Kernelmodule verweigern. Veraltet. Auch durch CAP_SYS_MODULE abgegrenzt.
delete_module Manipulation und Funktionen für Kernelmodule verweigern. Auch durch CAP_SYS_MODULE abgegrenzt.
finit_module Manipulation und Funktionen für Kernelmodule verweigern. Auch durch CAP_SYS_MODULE abgegrenzt.
get_kernel_syms Abrufen exportierter Kernel- und Modulsymbole verweigern. Veraltet.
get_mempolicy Syscall, der Kernelspeicher und NUMA-Einstellungen ändert. Bereits durch CAP_SYS_NICE abgegrenzt.
init_module Manipulation und Funktionen für Kernelmodule verweigern. Auch durch CAP_SYS_MODULE abgegrenzt.
ioperm Verhindern, dass Container Kernel-E/A-Berechtigungsstufen ändern. Bereits durch CAP_SYS_RAWIO abgegrenzt.
iopl Verhindern, dass Container Kernel-E/A-Berechtigungsstufen ändern. Bereits durch CAP_SYS_RAWIO abgegrenzt.
kcmp Einschränken der Prozessüberprüfungsfunktionen, die bereits durch Ablegen von CAP_SYS_PTRACE blockiert wurden.
kexec_file_load Schwester-Syscall von kexec_load, der dasselbe tut, aber etwas andere Argumente hat. Auch durch CAP_SYS_BOOT abgegrenzt.
kexec_load Verweigern Sie das Laden eines neuen Kernels für die spätere Ausführung. Auch durch CAP_SYS_BOOT abgegrenzt.
keyctl Verhindern Sie, dass Container den Kernel-Keyring verwenden, der keinem Namespace zugeordnet ist.
lookup_dcookie Syscall zur Ablaufverfolgung/Profilerstellung, der Informationen auf dem Host durchsickern lassen kann. Auch durch CAP_SYS_ADMIN abgegrenzt.
mbind Syscall, der Kernelspeicher und NUMA-Einstellungen ändert. Bereits durch CAP_SYS_NICE abgegrenzt.
mount Ablehnen des Mounting, das bereits durch CAP_SYS_ADMIN abgegrenzt wurde.
move_pages Syscall, der Kernelspeicher und NUMA-Einstellungen ändert.
nfsservctl Die Interaktion mit dem Kernel nfs-Daemon verweigern. Veraltet seit Linux 3.1.
open_by_handle_at Ursache für einen alten Containerausbruch. Auch durch CAP_DAC_READ_SEARCH abgegrenzt.
perf_event_open Syscall zur Ablaufverfolgung/Profilerstellung, der Informationen auf dem Host durchsickern lassen kann.
personality Verhindern, dass Container die BSD-Emulation aktiviert. Nicht inhärent gefährlich, aber schlecht getestet; Potenzial für Kernel-Schwachstelle.
pivot_root pivot_root verweigern, sollte ein privilegierter Vorgang sein.
process_vm_readv Einschränken der Prozessüberprüfungsfunktionen, die bereits durch Ablegen von CAP_SYS_PTRACE blockiert wurden.
process_vm_writev Einschränken der Prozessüberprüfungsfunktionen, die bereits durch Ablegen von CAP_SYS_PTRACE blockiert wurden.
ptrace Syscall zur Ablaufverfolgung/Profilerstellung. Blockiert in Linux-Kernelversionen vor 4.8, um die Umgehung von seccomp zu vermeiden. Die Ablaufverfolgung/Profilerstellung beliebiger Prozesse wird bereits durch Ablegen von CAP_SYS_PTRACE blockiert, da es Informationen auf dem Host durchsickern lassen könnte.
query_module Manipulation und Funktionen für Kernelmodule verweigern. Veraltet.
quotactl Kontingent-Syscall, mit dem Container ihre eigenen Ressourcenbeschränkungen oder Prozessrechnungen deaktivieren können. Auch durch CAP_SYS_ADMIN abgegrenzt.
reboot Container dürfen den Host nicht neu starten. Auch durch CAP_SYS_BOOT abgegrenzt.
request_key Verhindern Sie, dass Container den Kernel-Keyring verwenden, der keinem Namespace zugeordnet ist.
set_mempolicy Syscall, der Kernelspeicher und NUMA-Einstellungen ändert. Bereits durch CAP_SYS_NICE abgegrenzt.
setns Verweigern der Zuordnung eines Threads zu einem Namespace. Auch durch CAP_SYS_ADMIN abgegrenzt.
settimeofday Uhrzeit/Datum ist keinem Namespace zugeordnet. Auch durch CAP_SYS_TIME abgegrenzt.
stime Uhrzeit/Datum ist keinem Namespace zugeordnet. Auch durch CAP_SYS_TIME abgegrenzt.
swapon Verweigerung des Start-/Stopp-Swappings auf Datei/Gerät. Auch durch CAP_SYS_ADMIN abgegrenzt.
swapoff Verweigerung des Start-/Stopp-Swappings auf Datei/Gerät. Auch durch CAP_SYS_ADMIN abgegrenzt.
sysfs Veralteter Syscall.
_sysctl Veraltet, ersetzt durch /proc/sys.
umount Sollte ein privilegierter Vorgang sein. Auch durch CAP_SYS_ADMIN abgegrenzt.
umount2 Sollte ein privilegierter Vorgang sein. Auch durch CAP_SYS_ADMIN abgegrenzt.
unshare Das Klonen neuer Namespaces für Prozesse verweigern. Auch abgegrenzt von CAP_SYS_ADMIN, mit Ausnahme von „nicht teilen --user“.
uselib Älterer Syscall im Zusammenhang mit freigegebenen Bibliotheken, die lange nicht verwendet wurden.
userfaultfd Fehlerbehandlung von Userspace-Seiten, die größtenteils für die Prozessmigration erforderlich sind.
ustat Veralteter Syscall.
vm86 Virtueller Computer im Kernel x86-Realmodus. Auch durch CAP_SYS_ADMIN abgegrenzt.
vm86old Virtueller Computer im Kernel x86-Realmodus. Auch durch CAP_SYS_ADMIN abgegrenzt.

Nächste Schritte

Entsprechende bewährte Methoden finden Sie unter Best Practices für Clustersicherheit und Upgrades in Azure Kubernetes Service (AKS) und Best Practices für Podsicherheit in Azure Kubernetes Service (AKS).