GNU/Linux >> Linux Esercitazione >  >> Linux

Perché Podman senza root non può estrarre la mia immagine?

Una delle nuove funzionalità più interessanti di Podman sono i contenitori senza radici. Rootless consente a quasi tutti i container di essere eseguiti come utenti normali, senza privilegi elevati e con importanti vantaggi in termini di sicurezza. Tuttavia, l'esecuzione di container senza privilegi di root comporta delle limitazioni.

Un utente ha posto una domanda su uno di questi:perché non potevano estrarre un'immagine specifica con Podman senza root?

La loro immagine generava errori dopo il download, come quello di seguito:

ERRO[0005] Error pulling image ref //testimg:latest: Error committing the finished image: error adding layer with blob "sha256:caed8f108bf6721dc2709407ecad964c83a31c8008a6a21826aa4ab995df5502": Error processing tar file(exit status 1): there might not be enough IDs available in the namespace (requested 4000000:4000000 for /testfile): lchown /testfile: invalid argument

Ho spiegato che il loro problema era che la loro immagine aveva file di proprietà di UID oltre 65536. A causa di quel problema, l'immagine non rientrava nella mappatura UID predefinita di Podman senza root, che limita il numero di UID e GID disponibili.

Le domande successive erano, naturalmente:

  • Perché esiste questa limitazione?
  • Perché non puoi utilizzare alcuna immagine che funzioni su Podman normale in modalità rootless?
  • Perché gli esatti UID e GID in uso sono importanti?

Inizierò spiegando perché è necessario utilizzare UID e GID diversi rispetto all'host, quindi spiegherò perché l'impostazione predefinita è 65536 e come modificare questo numero.

Mappatura dello spazio dei nomi utente

I container senza root vengono eseguiti all'interno di uno spazio dei nomi utente , che è un modo per mappare gli utenti e i gruppi dell'host nel contenitore. Per impostazione predefinita, mappiamo l'utente che ha avviato Podman come UID/GID 0 in contenitori senza root.

Sul mio sistema, il mio utente (mheon ) è UID 1000. Quando lancio un container senza root come mheon con podman run -t -i --rm fedora bash , quindi esegui top all'interno del contenitore, sembro essere UID 0—root.

Tuttavia, sull'host, il bash il processo è ancora di proprietà del mio utente. Puoi vedere questo risultato quando eseguo podman top sul mio sistema host:

mheon@Agincourt code/podman.io (release_blog_1.5.0)$ podman top -l user group huser hgroup

USER GROUP HUSER HGROUP

root root 1000 1000

Il USER e GROUP le opzioni sono l'utente e il gruppo così come appaiono nel contenitore , mentre il HUSER e HGROUP le opzioni sono l'utente e il gruppo così come appaiono sull'host .

Mostriamo un semplice esempio. Monterò /etc/ , che è pieno di file di proprietà di root, in un contenitore senza root. Quindi mostrerò il suo contenuto con ls :

mheon@Agincourt code/libpod (master)$ podman run -t -i -v /etc/:/testdir --rm fedora sh -c 'ls -l /testdir 2> /dev/null | head -n 10'

total 1700

-rw-r--r--. 1 nobody nobody 4664 May 3 14:39 DIR_COLORS

-rw-r--r--. 1 nobody nobody 5342 May 3 14:39 DIR_COLORS.256color

Non ho il permesso di modificare questi file, nonostante sia root nel contenitore. Non riesco nemmeno a vederne molti:nota il 2> /dev/null dopo ls per schiacciare gli errori perché ottengo molti errori di autorizzazione anche cercando di elencarli.

Sull'host, questi file sono di proprietà di root, UID 0, ma nel contenitore sono di proprietà di nobody . Questo è un nome speciale utilizzato dal kernel Linux per dire che l'utente che possiede effettivamente i file non è presente nello spazio dei nomi utente. UID e GID 0 sull'host non sono mappati nel contenitore, quindi invece di file di proprietà di 0:0 , sono di proprietà di nobody:nobody dal punto di vista del contenitore.

Indipendentemente dall'utente che potresti sembrare in un contenitore senza root, stai comunque agendo come il tuo utente e puoi accedere solo ai file a cui può accedere il tuo utente sull'host. Questa configurazione è una parte importante dell'appeal di sicurezza dei container senza root:anche se un utente malintenzionato può evadere da un container, è comunque limitato a un account utente non root.

Assegnazione di UID/GID aggiuntivi

In precedenza ho detto che uno spazio dei nomi utente mappa gli utenti sull'host in utenti nel contenitore e ho descritto un po' come funziona quel processo per il root nel contenitore. Ma i contenitori generalmente hanno utenti diversi dal semplice root, il che significa che Podman ha bisogno di mappare in UID extra per consentire agli utenti uno e superiori di esistere nel contenitore.

In altre parole, qualsiasi utente richiesto dal contenitore deve essere mappato. Questo problema ha causato l'errore originale sopra perché l'immagine utilizzava un UID/GID che non era definito nel suo spazio dei nomi utente.

La newuidmap e newgidmap eseguibili, solitamente forniti da shadow-utils o uidmap pacchetti, vengono utilizzati per mappare questi UID e GID nello spazio dei nomi utente del contenitore. Questi strumenti leggono le mappature definite in /etc/subuid e /etc/subgid e usali per creare spazi dei nomi utente nel contenitore. Questi setuid i binari usano privilegi aggiuntivi per dare ai nostri container senza root l'accesso a UID e GID extra, qualcosa per cui normalmente non abbiamo il permesso. Ogni utente che esegue Podman senza root deve avere una voce in questi file se deve eseguire container con più di un UID. Ogni contenitore utilizza tutti gli UID disponibili per impostazione predefinita, sebbene le mappature esatte possano essere modificate con --uidmap e --gidmap .

Un normale utente non root in Linux di solito ha accesso solo al proprio utente, un UID. L'utilizzo di UID e GID aggiuntivi in ​​un contenitore senza root ti consente di agire come un utente diverso, cosa che normalmente richiede i privilegi di root (o di accedere come quell'altro utente con la propria password). Gli eseguibili di mappatura newuidmap e newgidmap utilizzare i loro privilegi elevati per concederci l'accesso a UID e GID aggiuntivi in ​​base alle mappature configurate in /etc/subuid e /etc/subgid senza essere root o avere il permesso di accedere come utenti.

Ogni utente che esegue Podman senza root deve avere una voce in questi file se deve eseguire container con più di un UID al loro interno.

Modifica del numero predefinito di ID

Passiamo ora alla questione del numero predefinito di UID e GID disponibili in un contenitore:65536. Questo numero non è un limite rigido e può essere modificato in alto o in basso utilizzando il summenzionato /etc/subuid e /etc/subgid file.

Ad esempio, sul mio sistema:

mheon@Agincourt code/libpod (master)$ cat /etc/subuid
mheon:100000:65536

Questo file è formattato come <username>:<start_uid>:<size> , dove start_uid è il primo UID o GID disponibile per l'utente e size è il numero di UID/GID disponibili (a partire da start_uid e termina con start_uid + size - 1 ).

Se dovessi sostituire quel 65536 con, diciamo, 123456, avrei 123456 UID disponibili all'interno dei miei contenitori rootless.

"Perché scegliere 65536 per impostazione predefinita?" è una domanda per i manutentori dello strumento per la creazione di utenti Linux, useradd , poiché le impostazioni predefinite iniziali vengono popolate quando viene creato un utente e non da Podman. Tuttavia, azzarderò a indovinare che questa impostazione è sufficiente per mantenere la maggior parte delle applicazioni funzionanti senza modifiche (versioni Linux molto vecchie avevano solo UID/GID a 16 bit e valori più alti sono ancora piuttosto rari).

Nota: Il /etc/subuid e /etc/subgid i file servono per regolare gli utenti già esistenti. Le impostazioni predefinite per i nuovi utenti vengono modificate altrove.

L'impostazione predefinita 65536 che i nuovi utenti ricevono non è hardcoded. Tuttavia, ciò non influirà sugli utenti esistenti. È impostato in /etc/login.defs file, con il SUB_UID_COUNT e SUB_GID_COUNT opzioni. In realtà abbiamo discusso per spostare il valore predefinito più in basso, dal momento che sembra che la maggior parte dei contenitori probabilmente funzionerà bene con poco più di 1000 UID/GID, e altri dopo andranno sprecati.

L'importante è che questo valore rappresenti un tratto di UID/GID allocati sull'host che sono disponibili per un utente specifico per eseguire container senza root. Se dovessi aggiungere un altro utente a questo sistema, otterrebbero un altro tratto di UID, probabilmente a partire da 165536, di nuovo 65536 di larghezza per impostazione predefinita.

Il root ha le autorizzazioni per modificare questi limiti, ma gli utenti normali no. Altrimenti, potrei cambiare un po' la mappatura in mheon:0:65536 e mappare il vero utente root sul sistema nei miei container rootless, che possono quindi essere facilmente convertiti in un accesso root a livello di sistema.

Prevenire la sovrapposizione di UID e GID

Come regola generale per la sicurezza, evitare di inserire in un contenitore qualsiasi UID/GID di sistema (di solito numerato sotto 1000) e idealmente qualsiasi UID/GID in uso sul sistema host. Questa pratica impedisce agli utenti di accedere ai file di sistema sull'host quando creano container senza root.

Vogliamo anche che ogni utente abbia un intervallo univoco di UID/GID rispetto ad altri utenti:potrei aggiungere un utente alice al mio /etc/subuid con la stessa identica mappatura del mio utente (alice:100000:65536 ), ma poi Alice avrebbe accesso ai miei container rootless e io ai suoi.

È possibile aumentare la dimensione dell'allocazione dell'utente, come discusso in precedenza, ma è necessario seguire queste regole per la sicurezza. Li elencherò di nuovo:

  • Nessun UID/GID inferiore a 1000.
  • Nessun UID o GID entra nel contenitore se è in uso sull'host.
  • Non sovrapporre le mappature tra utenti.

L'ultimo è il motivo principale per cui non vogliamo mappare in allocazioni UID e GID più elevate. Potremmo potenzialmente offrire a un utente una vasta gamma, compreso tutto da 100.000 fino a UID_MAX e rendi disponibili poco più di 4,2 milioni di UID, ma non ne rimarrebbero più per gli altri utenti.

Conclusione

Con Podman 1.5.0 e versioni successive, abbiamo aggiunto una nuova opzione sperimentale (--storage-opt ignore_chown_errors ) per ridurre tutti gli UID e i GID, eseguendo così i contenitori come un singolo utente (l'utente che ha avviato il contenitore). Questa impostazione risolve il problema iniziale dell'articolo, ma pone una serie di restrizioni aggiuntive sul contenitore:è meglio lasciare i dettagli in un articolo diverso.

Le restrizioni UID e GID poste sui contenitori senza root possono essere scomode, ma raramente ti imbatterai in esse. La maggior parte delle immagini e dei contenitori utilizza molto meno dei 65536 UID e GID disponibili. Queste limitazioni sono alcuni dei compromessi dei container senza radici, in cui sacrifichiamo un po' di praticità e usabilità per importanti miglioramenti della sicurezza.


Linux
  1. Utilizzo di file e dispositivi in ​​contenitori Podman rootless

  2. Perché non posso usare Cd in uno script Bash??

  3. Cosa c'è all'interno di un'immagine/contenitore Docker?

  4. Perché setuid viene ignorato nelle directory?

  5. Quale sistema operativo è in esecuzione nel mio container Docker?

Velocizzare le build di immagini del contenitore con Buildah

In che modo Cirrus CLI utilizza Podman per ottenere build senza root

Contenitore Openldap in 4 fasi Podman Easy

1 contenitore del server DNS Podman sporco facile

Perché un utente normale non può "chown" un file?

Commit dati in un contenitore mysql