Accesso ai contenitori di sicurezza alle risorse tramite funzionalità di sicurezza Linux predefinite
Questo articolo illustra come proteggere l'accesso dei contenitori alle risorse per i carichi di lavoro servizio Azure Kubernetes (servizio Azure Kubernetes).
Panoramica
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 predefiniti per definire altre autorizzazioni, ad esempio l'utente o il gruppo da eseguire come, 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 un controllo ancora più granulare delle azioni dei contenitori, è possibile usare funzionalità di sicurezza Linux predefinite, ad esempio AppArmor e seccomp.
- Definire le funzionalità di sicurezza di Linux a livello di nodo.
- Implementare le funzionalità tramite un manifesto del pod.
Le funzionalità di sicurezza Linux predefinite sono disponibili solo nei nodi e nei pod Linux.
Nota
Attualmente, gli ambienti Kubernetes non sono completamente sicuri per l'utilizzo multi-tenant ostile. Funzionalità di sicurezza aggiuntive, ad esempio Microsoft Defender per contenitori, AppArmor, seccomp, ammissione di sicurezza dei pod o Controllo degli accessi in base al ruolo di Kubernetes 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.
AppArmor
Per limitare le azioni del contenitore, è possibile usare il modulo di sicurezza del kernel AppArmor Linux. AppArmor è disponibile come parte del sistema operativo del nodo del servizio Azure Kubernetes sottostante ed è abilitato per impostazione predefinita. È 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 varie /proc
posizioni e /sys
forniscono un mezzo per isolare logicamente i contenitori dal nodo sottostante. AppArmor funziona non solo per i pod Kubernetes ma per qualsiasi applicazione in esecuzione su Linux.
Per una dimostrazione di AppArmor in azione, l'esempio seguente crea un profilo che impedisce la scrittura nei file.
Connettersi tramite SSH a un nodo del servizio Azure Kubernetes.
Creare un file denominato deny-write.profile.
Copiare e incollare il contenuto seguente:
#include <tunables/global> profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { #include <abstractions/base> file, # Deny all file writes. deny /** w, }
Per aggiungere profili AppArmor occorre usare il comando apparmor_parser
.
Aggiungere il profilo ad AppArmor.
Specificare il nome del profilo creato nel passaggio precedente:
sudo apparmor_parser deny-write.profile
Se il profilo viene analizzato correttamente e applicato ad AppArmor, non verrà visualizzato alcun output e si tornerà al prompt dei comandi.
Dal computer locale creare un manifesto del pod denominato aks-apparmor.yaml. Questo manifesto:
- Definisce un'annotazione per
container.apparmor.security.beta.kubernetes
. - Fa riferimento al profilo di deny-write creato nei passaggi precedenti.
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" ]
- Definisce un'annotazione per
Con il pod distribuito, eseguire il comando seguente e verificare che il pod hello-apparmor mostri uno stato di In esecuzione:
kubectl get pods NAME READY STATUS RESTARTS AGE aks-ssh 1/1 Running 0 4m2s hello-apparmor 0/1 Running 0 50s
Per altre informazioni su AppArmor, vedere AppArmor nella documentazione di Kubernetes.
Secure computing (seccomp)
Mentre AppArmor funziona con qualsiasi applicazione Linux, seccomp (secure computing, elaborazione sicura) funziona a livello di processo. Seccomp è anche un modulo di sicurezza del kernel Linux ed è supportato in modo nativo dal runtime usato dai nodi del containerd
servizio Azure Kubernetes. 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.
Configurare un profilo seccomp predefinito (anteprima)
È possibile applicare profili seccomp predefiniti usando configurazioni di nodo personalizzate durante la creazione di un nuovo pool di nodi Linux. Sono supportati due valori nel servizio Azure Kubernetes: 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 avere esito negativo durante il runtime con il profilo 'RuntimeDefault'. Per attenuare un errore di questo tipo, è possibile specificare il Unconfined
profilo. Se il carico di lavoro richiede un profilo personalizzato, vedere Configurare un profilo seccomp personalizzato.
Limiti
- SeccompDefault non è un parametro supportato per i pool di nodi windows.
- SeccompDefault è disponibile a partire dall'API 2024-09-02-preview.
Importante
Le funzionalità di anteprima del servizio Azure Kubernetes sono disponibili in modalità self-service e opzionale. 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 produzione. Per altre informazioni, vedere gli articoli di supporto seguenti:
Registrare il flag di funzionalità KubeletDefaultSeccompProfilePreview
Registrare il flag di funzionalità
KubeletDefaultSeccompProfilePreview
usando il comandoaz feature register
.az feature register --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
Sono necessari alcuni minuti per visualizzare lo stato Registered.
Verificare lo stato della registrazione usando il comando
az feature show
.az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
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
Limitare le chiamate di sistema del contenitore con seccomp
1. Seguire i passaggi per applicare un profilo seccomp nella configurazione di kubelet specificando "seccompDefault": "RuntimeDefault"
.
RuntimeDefault
usa il profilo seccomp predefinito di containerd, limitando determinate chiamate di sistema per migliorare la sicurezza. Le chiamate di sistema con restrizioni avranno esito negativo. Per altre informazioni, vedere il profilo seccomp predefinito containerD.
2. Verificare che la configurazione sia stata applicata.
È possibile verificare che le impostazioni vengano applicate ai nodi connettendosi all'host e verificando che nel file system siano state apportate modifiche alla configurazione.
3. Risolvere gli errori del carico di lavoro.
Quando SeccompDefault è abilitato, il profilo seccomp predefinito del runtime del contenitore viene usato per impostazione predefinita per tutti i carichi di lavoro pianificati nel nodo. Ciò potrebbe causare un errore dei carichi di lavoro a causa di chiamate di sistema bloccate. Se si è verificato un errore del carico di lavoro, è possibile che vengano visualizzati errori come:
- Il carico di lavoro è esistente in modo imprevisto dopo l'abilitazione della funzionalità, con 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 gli errori precedenti, è consigliabile modificare il profilo seccomp in Unconfined
. Unconfined
non applica restrizioni alle chiamate di sistema, consentendo tutte le chiamate di sistema, riducendo così la sicurezza.
Configurare un profilo seccomp personalizzato
Con un profilo seccomp personalizzato, è possibile avere un controllo più granulare sulle chiamate di sistema con restrizioni. Allineare alla procedura consigliata di concedere al contenitore l'autorizzazione minima solo per l'esecuzione da:
- Definizione con filtra le azioni da consentire o negare.
- Annotazione all'interno di un manifesto YAML del pod da associare al filtro seccomp.
Per una dimostrazione di seccomp in azione, creare un filtro che impedisce di cambiare le autorizzazioni su un file.
Connettersi tramite SSH a un nodo del servizio Azure Kubernetes.
Creare un filtro seccomp denominato /var/lib/kubelet/seccomp/prevent-chmod.
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" } ] }
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
. - Fa riferimento al filtro di prevent-chmod creato nel passaggio precedente.
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
- Definisce un'annotazione per
Distribuire il pod di esempio usando il comando kubectl apply:
kubectl apply -f ./aks-seccomp.yaml
Visualizzare lo stato del pod usando il comando kubectl get pods.
- Il pod segnala un errore.
- Il
chmod
comando non può essere eseguito dal filtro seccomp, come illustrato nell'output di esempio:
kubectl get pods 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 di chiamate di sistema definite consentite o limitate. La maggior parte dei runtime di contenitori ha un profilo seccomp predefinito simile se non uguale a quello usato da Docker. Per altre informazioni sui profili disponibili, vedere Profili seccomp predefiniti Docker o containerD .
Il servizio Azure Kubernetes usa il profilo seccomp predefinito containerD per RuntimeDefault quando si configura seccomp usando la configurazione personalizzata dei nodi.
Syscall significativi bloccati dal profilo predefinito
Sia Docker che containerD mantengono elenchi consentiti di chiamate syscall sicure. Questa tabella elenca le chiamate di sistema significative (ma non tutte) bloccate in modo efficace perché non sono presenti nell'elenco elementi consentiti. Se una delle chiamate di sistema bloccate è richiesta dal carico di lavoro, non usare il RuntimeDefault
profilo seccomp.
Quando vengono apportate modifiche a Docker e containerD, il servizio Azure Kubernetes aggiorna la configurazione predefinita in modo che corrisponda. Gli aggiornamenti a questo elenco possono causare un errore del carico di lavoro. Per gli aggiornamenti delle versioni, vedere Note sulla versione del servizio Azure Kubernetes.
Syscall bloccato | Descrizione |
---|---|
acct |
Syscall contabilità che potrebbe consentire ai contenitori di disabilitare i propri limiti di risorse o di elaborare la contabilità. 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à controllata 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 gated by CAP_SYS_ADMIN for CLONE_* flags, ad eccezione CLONE_NEWUSER di . |
create_module |
Nega manipolazione e funzioni nei moduli del kernel. Obsoleta. Gestito anche da CAP_SYS_MODULE . |
delete_module |
Nega manipolazione e funzioni nei moduli del kernel. Gestito anche da CAP_SYS_MODULE . |
finit_module |
Nega manipolazione e funzioni nei moduli del kernel. Gestito anche da CAP_SYS_MODULE . |
get_kernel_syms |
Nega il recupero dei simboli del kernel e del modulo esportati. Obsoleta. |
get_mempolicy |
Syscall che modifica le impostazioni di memoria del kernel e NUMA. Già controllata da CAP_SYS_NICE . |
init_module |
Nega manipolazione e funzioni nei 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à controllata da CAP_SYS_RAWIO . |
iopl |
Impedire ai contenitori di modificare i livelli dei privilegi di I/O del kernel. Già controllata da CAP_SYS_RAWIO . |
kcmp |
Limitare le funzionalità di ispezione dei processi, già bloccate eliminando CAP_SYS_PTRACE . |
kexec_file_load |
Sorella 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 |
Chiamare syscall di traccia/profilatura, 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à controllata da CAP_SYS_NICE . |
mount |
Nega 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 |
Chiamare syscall di traccia/profilatura, 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 glivulni 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 |
Chiamare syscall di traccia/profilatura. Bloccato nelle versioni del kernel Linux precedenti alla 4.8 per evitare il bypass seccomp. I processi arbitrari di traccia/profilatura sono già bloccati eliminando CAP_SYS_PTRACE, perché potrebbero perdere informazioni sull'host. |
query_module |
Nega manipolazione e funzioni nei moduli del kernel. Obsoleta. |
quotactl |
Quota syscall che potrebbe consentire ai contenitori di disabilitare i propri limiti di risorse o di elaborare la contabilità. 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à controllata 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 |
Nega avvio/arresto dello scambio in file/dispositivo. Gestito anche da CAP_SYS_ADMIN . |
swapoff |
Nega 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. Gestito anche da CAP_SYS_ADMIN , ad eccezione di unshare --user. |
uselib |
Chiamata di sistema precedente correlata alle librerie condivise, inutilizzata per molto tempo. |
userfaultfd |
Gestione degli errori delle pagine 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 . |
Passaggi successivi
Per le procedure consigliate associate, vedere Procedure consigliate per la sicurezza e gli aggiornamenti del cluster nel servizio Azure Kubernetes e Procedure consigliate per la sicurezza dei pod nel servizio Azure Kubernetes.
Azure Kubernetes Service