Condividi tramite


Proteggi l'accesso ai contenitori alle risorse per i carichi di lavoro del servizio Azure Kubernetes (AKS) utilizzando funzionalità di sicurezza Linux integrate.

Questo articolo illustra come proteggere l'accesso ai contenitori alle risorse per i carichi di lavoro del servizio Azure Kubernetes usando gli spazi dei nomi utente, AppArmor e le funzionalità di sicurezza Linux predefinite di Seccomp .

Panoramica della sicurezza dell'accesso ai contenitori

Allo stesso modo in cui è necessario concedere agli utenti o ai gruppi i privilegi minimi necessari, è anche necessario limitare i contenitori solo alle azioni e ai processi necessari. Per ridurre al minimo il rischio di attacco, evitare di configurare applicazioni e contenitori che richiedono privilegi di escalation o accesso radice.

È possibile usare contesti di sicurezza dei pod Kubernetes integrati per definire altre autorizzazioni, ad esempio utente o gruppo da eseguire, le funzionalità Linux da esporre o impostare allowPrivilegeEscalation: false nel manifesto del pod. Per altre procedure consigliate, vedere Proteggere l'accesso dei pod alle risorse.

Per migliorare l'isolamento dell'host e ridurre lo spostamento laterale in Linux, è possibile usare gli spazi dei nomi utente. Per un controllo ancora più granulare delle azioni dei contenitori, è possibile usare funzionalità di sicurezza predefinite di Linux, come AppArmor e seccomp. Queste funzionalità consentono di limitare le azioni che i contenitori possono eseguire definendo le funzionalità di sicurezza linux a livello di nodo e implementandole tramite un manifesto del pod.

Le funzionalità di sicurezza Linux predefinite sono disponibili solo nei nodi e nei pod Linux.

Note

Attualmente, gli ambienti Kubernetes non sono sicuri per l'utilizzo multi-tenant ostile. Altre funzionalità di sicurezza, ad esempio Microsoft Defender per contenitori, AppArmor, seccomp, spazi dei nomi utente, ammissione di sicurezza dei pod o Kubernetes Role-Based controllo di accesso (RBAC) per i nodi, bloccano in modo efficiente gli exploit.

Per una vera sicurezza quando si eseguono carichi di lavoro multi-tenant ostili, considerare attendibile solo un hypervisor. Il dominio di sicurezza per Kubernetes diventa l'intero cluster, non un singolo nodo.

Per questi tipi di carichi di lavoro multi-tenant ostili è consigliabile usare cluster fisicamente isolati.

Prerequisiti per gli spazi dei nomi utente

Limitazioni per gli spazi dei nomi utente

Panoramica dei namespace utente

Per impostazione predefinita, i pod Linux vengono eseguiti usando diversi spazi dei nomi: uno spazio dei nomi di rete per isolare l'identità di rete e uno spazio dei nomi PID per isolare i processi. Uno spazio dei nomi utente (user_namespace) isola gli utenti all'interno del contenitore dagli utenti dell'host. Limita anche l'ambito delle funzionalità e le interazioni del pod con il resto del sistema.

Gli UID e i GID all'interno del contenitore vengono mappati negli utenti senza privilegi sull'host, quindi tutte le interazioni con il resto dell'host avvengono come quelle UID e GID senza privilegi. Ad esempio, la radice all'interno del contenitore (UID 0) può essere mappata nell'utente 65536 sull'host. Kubernetes crea il mapping per garantire che non si sovrapponga ad altri pod usando spazi dei nomi utente nel sistema.

L'implementazione di Kubernetes presenta alcuni vantaggi chiave. Per altre informazioni, vedere la documentazione relativa agli spazi dei nomi utente di Kubernetes.

Abilitare gli spazi dei nomi utente

  1. Creare un file denominato mypod.yaml e copiarlo nel manifesto seguente. Per usare gli spazi dei nomi utente, YAML deve avere il campo hostUsers: false.

    apiVersion: v1
    kind: Pod
    metadata:
      name: userns
    spec:
      hostUsers: false
      containers:
      - name: shell
        command: ["sleep", "infinity"]
        image: debian
    
  2. Distribuire l'applicazione usando il comando kubectl apply e specificare il nome del manifesto YAML.

    kubectl apply -f mypod.yaml
    
  3. Controllare lo stato dei pod distribuiti usando il comando kubectl get pods.

    kubectl get pods
    
  4. Accedere al pod usando il comando kubectl exec.

    kubectl exec -ti userns -- bash
    
  5. All'interno del pod, controllare /proc/self/uid_map utilizzando il comando seguente:

    cat /proc/self/uid_map
    

    L'output deve avere 65536 nell'ultima colonna. Per esempio:

    0  833617920      65536
    

    Questo output indica che l'utente root all'interno del contenitore (UID 0) è mappato all'utente 65536 sul host.

Vulnerabilità ed esposizioni comuni (CVE) attenuate dagli spazi dei nomi degli utenti

La tabella seguente illustra alcune vulnerabilità ed esposizioni comuni (CVE) parzialmente o completamente attenuate tramite user_namespaces:

CVE Punteggio di gravità Livello di gravità
CVE-2019-5736 8.6 High
CVE 2024-21262 8.6 High
CVE 2022-0492 7,8 High
CVE-2021-25741 8.1 / 8.8 Alto/Alto
CVE-2017-1002101 9.6 / 8.8 Critico/Alto

Tenere presente che questo elenco non è esaustivo. Per altre informazioni, vedere Kubernetes v1.33: spazi dei nomi utente abilitati per impostazione predefinita.

Prerequisiti di AppArmor

Note

Azure Linux 3.0 supporta AppArmor a partire dal rilascio VHD del 7 novembre 2025.

Panoramica di AppArmor

Per limitare le azioni del contenitore, è possibile usare il modulo di sicurezza del kernel AppArmor Linux. AppArmor è disponibile come parte del sistema operativo (OS) del nodo AKS sottostante di Azure Kubernetes Service ed è abilitato di default. È possibile creare profili AppArmor che limitano le azioni di lettura, scrittura o esecuzione o funzioni di sistema come il montaggio di file system. I profili AppArmor predefiniti limitano l'accesso a vari percorsi /proc e /sys e consentono di isolare logicamente i contenitori dal nodo sottostante. AppArmor funziona non solo per i pod Kubernetes ma per qualsiasi applicazione in esecuzione su Linux.

Note

Prima di Kubernetes v1.30, AppArmor è stato specificato tramite annotazioni. A partire dalla versione 1.30, il campo securityContext viene utilizzato per specificare AppArmor nella specifica del pod. Per altre informazioni, vedere la documentazione di Kubernetes AppArmor.

Profili AppArmor in uso in un cluster del servizio Azure Kubernetes per limitare le azioni dei contenitori

Proteggere i pod con AppArmor

È possibile specificare i profili AppArmor a livello di pod o contenitore. Il profilo AppArmor del contenitore ha la precedenza sul profilo AppArmor del pod. In assenza di parametri specificati, il contenitore viene eseguito senza restrizioni. Per altre informazioni sui profili AppArmor, vedere la documentazione relativa alla protezione di un pod con AppArmor Kubernetes.

Configurare un profilo AppArmor personalizzato

Nell'esempio seguente viene creato un profilo che impedisce la scrittura nei file all'interno di un contenitore.

  1. Connettersi tramite SSH a un nodo del servizio Azure Kubernetes.

  2. Creare un file denominato deny-write.profile e incollarlo nel contenuto seguente:

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

    # This example assumes that node names match host names, and are reachable via SSH.
    NODES=($( kubectl get node -o jsonpath='{.items[*].status.addresses[?(.type == "Hostname")].address}' ))
    
    for NODE in ${NODES[*]}; do ssh $NODE 'sudo apparmor_parser -q <<EOF
    #include <tunables/global>
    
    profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
      #include <abstractions/base>
    
      file,
    
      # Deny all file writes.
      deny /** w,
    }
    EOF'
    done
    

Distribuire un pod con il profilo AppArmor personalizzato

  1. Distribuire un pod "Hello AppArmor" con il profilo deny-write.

    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-apparmor
    spec:
      securityContext:
        appArmorProfile:
          type: Localhost
          localhostProfile: k8s-apparmor-example-deny-write
      containers:
      - name: hello
        image: busybox:1.28
        command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
    
  2. Applicare il manifesto del pod usando il kubectl apply comando .

    kubectl apply -f hello-apparmor.yaml
    
  3. Accedere al pod e verificare che il contenitore sia in esecuzione con il profilo AppArmor.

    kubectl exec hello-apparmor -- cat /proc/1/attr/current
    

    L'output dovrebbe mostrare il profilo AppArmor in uso. Per esempio:

    k8s-apparmor-example-deny-write (enforce)
    

Prerequisiti di Seccomp

Registrare il flag di funzionalità KubeletDefaultSeccompProfilePreview

Importante

Le funzionalità di anteprima del servizio Azure Kubernetes sono disponibili in modalità self-service e con consenso esplicito. Le anteprime vengono fornite "così come sono" e "come disponibili" e sono escluse dai contratti di servizio e dalla garanzia limitata. Le anteprime del servizio Azure Kubernetes sono parzialmente coperte dal supporto clienti con la massima diligenza possibile. Di conseguenza, queste funzionalità non sono destinate all'uso in ambienti di produzione. Per altre informazioni, vedere gli articoli di supporto seguenti:

  1. Registrare il flag della funzionalità KubeletDefaultSeccompProfilePreview usando il comando az feature register.

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

    Sono necessari alcuni minuti per visualizzare lo stato Registered.

  2. Verificare lo stato della registrazione usando il comando az feature show.

    az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    
  3. Quando lo stato riflette Registrato, aggiornare la registrazione del provider di risorse Microsoft.ContainerService usando il comando az provider register.

    az provider register --namespace Microsoft.ContainerService
    

Limitazioni di Seccomp

  • AKS supporta solo i profili seccomp predefiniti (RuntimeDefault e Unconfined). I profili seccomp personalizzati non sono supportati.
  • SeccompDefault non è un parametro supportato per i pool di nodi Windows.

Panoramica dei profili seccomp predefiniti (anteprima)

Mentre AppArmor funziona per qualsiasi applicazione Linux, seccomp (o secure computing) funziona a livello di processo. Seccomp è anche un modulo di sicurezza kernel Linux. Il containerd runtime usato dai nodi del servizio Azure Kubernetes fornisce il supporto nativo per seccomp. Con seccomp, è possibile limitare le chiamate di sistema di un contenitore. Seccomp stabilisce un ulteriore livello di protezione da vulnerabilità comuni delle chiamate di sistema sfruttate da attori malintenzionati e consente di specificare un profilo predefinito per tutti i carichi di lavoro nel nodo.

È possibile applicare profili seccomp predefiniti usando configurazioni di nodo personalizzate durante la creazione di un nuovo pool di nodi Linux. AKS supporta i valori RuntimeDefault e Unconfined. Alcuni carichi di lavoro potrebbero richiedere un numero inferiore di restrizioni per le chiamate di sistema rispetto ad altri. Ciò significa che possono ritrovarsi in errore durante il runtime con il profilo RuntimeDefault. Per attenuare un errore di questo tipo, è possibile specificare il profilo Unconfined. Se il carico di lavoro richiede un profilo personalizzato, vedere Configurare un profilo seccomp personalizzato.

Limitare le chiamate di sistema dei contenitori con seccomp

  1. Seguire la procedura per applicare un profilo seccomp nella configurazione di kubelet specificando "seccompDefault": "RuntimeDefault".
  2. Connettersi all'host.
  3. Verificare che la configurazione sia stata applicata ai nodi.

Risolvere gli errori del carico di lavoro con seccomp

Quando SeccompDefault è abilitata, il profilo seccomp predefinito del runtime del contenitore viene usato per tutti i carichi di lavoro pianificati nel nodo, il che può causare errori nei carichi di lavoro a causa di chiamate di sistema bloccate. Se si verifica un errore del carico di lavoro, è possibile che vengano visualizzati errori come:

  • Il carico di lavoro si interrompe in modo imprevisto dopo l'abilitazione della funzionalità, con l'errore "autorizzazione negata".
  • I messaggi di errore seccomp possono essere visualizzati anche in auditd o syslog sostituendo SCMP_ACT_ERRNO con SCMP_ACT_LOG nel profilo predefinito.

Se si verificano questi errori, è consigliabile modificare il profilo seccomp in Unconfined. Unconfined non applica restrizioni alle chiamate di sistema, consentendo l'esecuzione di tutte le chiamate di sistema.

Panoramica dei profili seccomp personalizzati

Con un profilo seccomp personalizzato, è possibile avere un controllo più granulare sulle chiamate di sistema limitate per i contenitori. È possibile creare profili seccomp personalizzati in base a:

  • Uso dei filtri per specificare le azioni da consentire o negare.
  • Annotazione all'interno di un manifesto YAML del pod da associare al filtro seccomp.

Note

Per informazioni sulla risoluzione dei problemi del profilo seccomp, vedere Risolvere i problemi di configurazione del profilo seccomp nel servizio Azure Kubernetes.

Configurare un profilo seccomp personalizzato

Per una dimostrazione di seccomp in azione, creare un filtro che impedisce di cambiare le autorizzazioni su un file.

  1. Connettersi tramite SSH a un nodo del servizio Azure Kubernetes.

  2. Creare un filtro seccomp denominato /var/lib/kubelet/seccomp/prevent-chmod.

  3. Copiare e incollare il contenuto seguente:

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

    Nella versione 1.19 e successive è necessario configurare:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "names": ["chmod","fchmodat","chmodat"],
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    
  4. Dal computer locale creare un manifesto pod denominato aks-seccomp.yaml e incollare il contenuto seguente. Questo manifesto definisce un'annotazione per seccomp.security.alpha.kubernetes.io e fa riferimento al filtro prevent-chmod esistente.

    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
    

    Nella versione 1.19 e successive è necessario configurare:

    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. Distribuire il pod di esempio usando il kubectl apply comando :

    kubectl apply -f ./aks-seccomp.yaml
    
  6. Visualizzare lo stato del pod usando il kubectl get pods comando .

    kubectl get pods
    

    Nell'output, dovresti vedere che il pod segnala un errore. Come illustrato nell'output di esempio, il filtro seccomp impedisce l'esecuzione del comando chmod:

    NAME                      READY     STATUS    RESTARTS   AGE
    chmod-prevented           0/1       Error     0          7s
    

Opzioni del profilo di sicurezza Seccomp

I profili di sicurezza Seccomp sono un set consentito o limitato di syscall definite. La maggior parte dei runtime di contenitori ha un profilo seccomp predefinito simile se non uguale a quello usato da Docker. Per ulteriori informazioni sui profili disponibili, consultare i profili seccomp predefiniti di Docker o containerd.

AKS utilizza il profilo seccomp predefinito di containerd per RuntimeDefault quando configuri seccomp usando la configurazione del nodo personalizzata.

Syscall significativi bloccati dal profilo predefinito

Sia Docker che containerd gestiscono gli elenchi di chiamate di sistema (syscall) sicure. Quando vengono apportate modifiche a Docker e containerd, AKS aggiorna la configurazione predefinita in modo che corrisponda. Gli aggiornamenti a questo elenco potrebbero causare un errore del carico di lavoro. Per gli aggiornamenti delle versioni, vedere Note sulla versione del servizio Azure Kubernetes.

La tabella seguente elenca le chiamate di sistema significative effettivamente bloccate perché non incluse nella lista di autorizzazione. Questo elenco non è esaustivo. Se il carico di lavoro richiede una delle chiamate di sistema bloccate, non usare il profilo seccomp RuntimeDefault.

Syscall bloccato Descrizione
acct Chiamata di sistema di contabilità, che potrebbe consentire ai contenitori di disabilitare i propri limiti di risorse o i conteggi processi. Gestito anche da CAP_SYS_PACCT.
add_key Impedire ai contenitori di usare il keyring del kernel, che non è spazio dei nomi.
bpf Negare il caricamento di programmi bpf potenzialmente persistenti nel kernel, già controllato da CAP_SYS_ADMIN.
clock_adjtime L'ora e la data non sono spazi dei nomi. Gestito anche da CAP_SYS_TIME.
clock_settime L'ora e la data non sono spazi dei nomi. Gestito anche da CAP_SYS_TIME.
clone Negare la clonazione di nuovi spazi dei nomi. Anche gestito da flag CAP_SYS_ADMIN for CLONE_*, ad eccezione di CLONE_NEWUSER.
create_module Nega manipolazione e funzioni sui moduli del kernel. Obsoleto. Gestito anche da CAP_SYS_MODULE.
delete_module Nega manipolazione e funzioni sui moduli del kernel. Gestito anche da CAP_SYS_MODULE.
finit_module Nega manipolazione e funzioni sui moduli del kernel. Gestito anche da CAP_SYS_MODULE.
get_kernel_syms Nega il recupero dei simboli del kernel e del modulo esportati. Obsoleto.
get_mempolicy Syscall che modifica le impostazioni di memoria del kernel e NUMA. Già controllato da CAP_SYS_NICE.
init_module Nega manipolazione e funzioni sui moduli del kernel. Gestito anche da CAP_SYS_MODULE.
ioperm Impedire ai contenitori di modificare i livelli dei privilegi di I/O del kernel. Già controllato da CAP_SYS_RAWIO.
iopl Impedire ai contenitori di modificare i livelli dei privilegi di I/O del kernel. Già controllato da CAP_SYS_RAWIO.
kcmp Limitare le funzionalità di ispezione dei processi, già bloccate eliminando CAP_SYS_PTRACE.
kexec_file_load Famiglia syscall di kexec_load che fa la stessa cosa, argomenti leggermente diversi. Gestito anche da CAP_SYS_BOOT.
kexec_load Negare il caricamento di un nuovo kernel per un'esecuzione successiva. Gestito anche da CAP_SYS_BOOT.
keyctl Impedire ai contenitori di usare il keyring del kernel, che non è spazio dei nomi.
lookup_dcookie Traccia/profilatura syscall, che potrebbe causare perdite di informazioni sull'host. Gestito anche da CAP_SYS_ADMIN.
mbind Syscall che modifica le impostazioni di memoria del kernel e NUMA. Già controllato da CAP_SYS_NICE.
mount Negare montaggio, già gestito da CAP_SYS_ADMIN.
move_pages Syscall che modifica le impostazioni di memoria del kernel e NUMA.
nfsservctl Negare l'interazione con il daemon nfs del kernel. Obsoleto a partire da Linux 3.1.
open_by_handle_at Causa di un'interruzione del contenitore precedente. Gestito anche da CAP_DAC_READ_SEARCH.
perf_event_open Traccia/profilatura syscall, che potrebbe causare perdite di informazioni sull'host.
personality Impedire al contenitore di abilitare l'emulazione BSD. Non intrinsecamente pericoloso, ma scarsamente testato, potenziale per vulns del kernel.
pivot_root Negare pivot_root, deve essere un'operazione con privilegi.
process_vm_readv Limitare le funzionalità di ispezione dei processi, già bloccate eliminando CAP_SYS_PTRACE.
process_vm_writev Limitare le funzionalità di ispezione dei processi, già bloccate eliminando CAP_SYS_PTRACE.
ptrace Traccia/profilatura syscall. Bloccato nelle versioni del kernel Linux precedenti a 4.8 per evitare il bypass seccomp. La traccia o la profilatura di processi arbitrari è già bloccata rimuovendo CAP_SYS_PTRACE, perché potrebbe causare la perdita di informazioni sull'host.
query_module Nega manipolazione e funzioni sui moduli del kernel. Obsoleto.
quotactl Chiamata di sistema quota, che potrebbe consentire ai contenitori di disabilitare i propri limiti di risorse o i conteggi processi. Gestito anche da CAP_SYS_ADMIN.
reboot Non consentire ai contenitori di riavviare l'host. Gestito anche da CAP_SYS_BOOT.
request_key Impedire ai contenitori di usare il keyring del kernel, che non è spazio dei nomi.
set_mempolicy Syscall che modifica le impostazioni di memoria del kernel e NUMA. Già controllato da CAP_SYS_NICE.
setns Negare l'associazione di un thread a uno spazio dei nomi. Gestito anche da CAP_SYS_ADMIN.
settimeofday L'ora e la data non sono spazi dei nomi. Gestito anche da CAP_SYS_TIME.
stime L'ora e la data non sono spazi dei nomi. Gestito anche da CAP_SYS_TIME.
swapon Negare avvio/arresto dello scambio in file/dispositivo. Gestito anche da CAP_SYS_ADMIN.
swapoff Negare avvio/arresto dello scambio in file/dispositivo. Gestito anche da CAP_SYS_ADMIN.
sysfs Syscall obsoleto.
_sysctl Obsoleto, sostituito da /proc/sys.
umount Deve essere un'operazione con privilegi. Gestito anche da CAP_SYS_ADMIN.
umount2 Deve essere un'operazione con privilegi. Gestito anche da CAP_SYS_ADMIN.
unshare Negare la clonazione di nuovi spazi dei nomi per i processi. Anch'esso controllato da CAP_SYS_ADMIN (tranne unshare --user).
uselib Syscall precedente correlata alle librerie condivise, non utilizzata per molto tempo.
userfaultfd Gestione dell’errore di pagina nello spazio utente, in gran parte necessaria per la migrazione dei processi.
ustat Syscall obsoleto.
vm86 Nella macchina virtuale in modalità reale x86 del kernel. Gestito anche da CAP_SYS_ADMIN.
vm86old Nella macchina virtuale in modalità reale x86 del kernel. Gestito anche da CAP_SYS_ADMIN.

Per altre informazioni sulla protezione del cluster del servizio Azure Kubernetes, vedere gli articoli seguenti: