Mi viene chiesto continuamente delle diverse misure di sicurezza utilizzate per controllare cosa possono fare i processi di container su un sistema. La maggior parte di questi l'ho trattata in articoli precedenti su Opensource.com:
- I container Docker sono davvero sicuri?
- Introdurre nuove funzionalità di sicurezza in Docker
- Sicurezza Docker in futuro
Quasi tutti gli articoli precedenti riguardano il controllo di ciò che un processo privilegiato su un sistema può fare in un contenitore. Ad esempio:come faccio a eseguire root in un contenitore e non permettere che si rompa?
Contenitori Linux
- Cosa sono i container Linux?
- Un'introduzione alla terminologia dei contenitori
- Download:Primer sui contenitori
- Operatori Kubernetes:automatizzare la piattaforma di orchestrazione dei container
- eBook:modelli Kubernetes per la progettazione di app cloud native
- Cos'è Kubernetes?
Lo spazio dei nomi utente riguarda l'esecuzione di processi privilegiati nei contenitori, in modo tale che se si rompono, non sarebbero più privilegiati all'esterno del contenitore. Ad esempio, nel contenitore il mio UID è 0 (zero), ma al di fuori del contenitore il mio UID è 5000. A causa di problemi con la mancanza di supporto per il file system, lo spazio dei nomi utente non è stato la panacea che è stato risolto. Fino ad ora.
OpenShift è la piattaforma container di Red Hat, costruita su container Kubernetes, Red Hat Enterprise Linux e OCI, e ha un'ottima funzionalità di sicurezza:per impostazione predefinita, nessun container può essere eseguito come root. Un amministratore può sovrascriverlo, altrimenti tutti i contenitori utente vengono eseguiti senza essere mai root. Ciò è particolarmente importante nei cluster OpenShift Kubernetes multi-tenant, in cui un singolo cluster può servire più applicazioni e più team di sviluppo. Non è sempre pratico o addirittura consigliabile che gli amministratori eseguano cluster separati per ciascuno. Purtroppo una delle maggiori lamentele su OpenShift è che gli utenti non possono eseguire facilmente tutte le immagini del contenitore della community disponibili su docker.io. Questo perché la stragrande maggioranza delle immagini container nel mondo oggi richiede root.
Perché tutte queste immagini richiedono il root?
Se esamini effettivamente i motivi per essere root, su un sistema, sono piuttosto limitati.
Modifica il sistema host:
- Uno dei motivi principali per essere root sul sistema è modificare le impostazioni predefinite del sistema, come modificare la configurazione del kernel.
- In Fedora, CentOS e Red Hat Enterprise Linux abbiamo il concetto di contenitori di sistema , che sono contenitori privilegiati che possono essere installati su un sistema utilizzando
atomic
comando. Possono essere eseguiti con privilegi completi e sono autorizzati a modificare il sistema e il kernel. Nel caso di contenitori di sistema stiamo usando l'immagine del contenitore come sistema di consegna del contenuto, non cercando realmente la separazione del contenitore. I contenitori di sistema sono più destinati ai servizi host del sistema operativo principale rispetto ai servizi delle app degli utenti eseguiti dalla maggior parte dei contenitori. - Nei contenitori delle applicazioni, non vogliamo quasi mai che i processi all'interno del contenitore modifichino il kernel. Questo non è assolutamente richiesto per impostazione predefinita.
Tradizione Unix/Linux:
- I fornitori e gli sviluppatori di software per sistemi operativi sanno da molto tempo che i processi in esecuzione sono pericolosi, quindi il kernel ha aggiunto molte funzionalità Linux per consentire a un processo di avviarsi come root e quindi rilasciare i privilegi il più rapidamente possibile. La maggior parte delle funzionalità UID/GID consente a processi come un servizio Web di iniziare come root, quindi diventare non root. Questo viene fatto per collegarsi a porte inferiori a 1024 (ne parleremo più avanti).
- I runtime del contenitore possono avviare le applicazioni come non root per cominciare. A dire il vero, lo può fare anche systemd, ma la maggior parte del software che è stato creato negli ultimi 20 anni presume che inizi come root e abbandoni i privilegi.
Lega alle porte <1024
- Negli anni '60 e '70, quando c'erano pochi computer, l'impossibilità degli utenti senza privilegi di collegarsi alle porte di rete <1024 era considerata una caratteristica di sicurezza. Poiché solo un amministratore può farlo, puoi fidarti delle applicazioni in ascolto su queste porte. Le porte> 1024 potrebbero essere vincolate da qualsiasi utente sul sistema in modo che non possano essere considerate attendibili. I vantaggi in termini di sicurezza sono in gran parte scomparsi, ma conviviamo ancora con questa restrizione.
- Il problema più grande con questa restrizione sono i servizi Web in cui le persone amano avere i loro server Web in ascolto sulla porta 80. Ciò significa che il motivo principale per cui apache o nginx iniziano a funzionare come root è che possono collegarsi alla porta 80 e quindi diventa non root.
- I runtime dei container, utilizzando il port forwarding, possono risolvere questo problema. Puoi configurare un contenitore per l'ascolto su qualsiasi porta di rete, quindi fare in modo che il runtime del contenitore esegua la mappatura della porta alla porta 80 dell'host.
In questo comando, il runtime podman eseguirà un apache_unpriv
container sulla tua macchina in ascolto sulla porta 80 sull'host, mentre il processo Apache all'interno del container non era mai root, iniziato come apache
utente e gli è stato detto di ascoltare sulla porta 8080.
podman run -d -p 80:8080 -u apache apache_unpriv
In alternativa:
docker run -d -p 80:8080 -u apache apache_unpriv
Installazione del software in un'immagine contenitore
- Quando Docker ha introdotto la creazione di container con
docker build
, il contenuto nei contenitori era solo un pacchetto software standard per le distribuzioni. Il software di solito arrivava tramite pacchetti rpm o pacchetti Debian. Bene, il software del pacchetto di distribuzione deve essere installato da root. Un pacchetto si aspetta di essere in grado di fare cose come manipolare il/etc/passwd
file aggiungendo utenti e per inserire il contenuto nel file system con diversi UID/GID. Gran parte del software prevede anche di essere avviato tramite il sistema init (systemd) e di essere avviato come root e quindi rilasciare i privilegi dopo l'avvio. - Purtroppo, a cinque anni dall'inizio della rivoluzione dei container, questo è ancora lo status quo. Alcuni anni fa, ho tentato di far sapere al pacchetto httpd quando viene installato da un utente non root e di avere una configurazione diversa. Ma ho lasciato cadere la palla su questo. Abbiamo bisogno che i packager e i sistemi di gestione dei pacchetti inizino a capire la differenza, e quindi potremmo creare dei bei contenitori che funzionino senza richiedere il root.
- Una cosa che possiamo fare ora per risolvere questo problema è separare i sistemi di compilazione dai sistemi di installazione. Uno dei miei problemi con #nobigfatdaemons è che il demone Docker ha portato i contenitori in esecuzione con gli stessi privilegi per l'esecuzione di un contenitore come per la creazione di un'immagine del contenitore.
- Se cambiamo il sistema o utilizziamo strumenti diversi, ad esempio Buildah, per creare un container con vincoli più flessibili e CRI-O/Kubernetes/OpenShift per eseguire i container in produzione, allora possiamo costruire con privilegi elevati, ma poi eseguire il container con vincoli molto più stretti o, si spera, come non root utente.
Linea inferiore
Quasi tutto il software in esecuzione nei container non richiedono radice. Le tue applicazioni web, i database, i bilanciatori di carico, i cruncher numerici, ecc. non deve essere eseguito sempre come root. Quando facciamo in modo che le persone inizino a creare immagini di container che non richiedono affatto il root e ad altri di basare le loro immagini su immagini di container non privilegiate, vedremmo un passo da gigante nella sicurezza dei container.
C'è ancora molto da educare sull'esecuzione di root all'interno dei contenitori. Senza istruzione, gli amministratori intelligenti possono prendere decisioni sbagliate.