Přístupová práva k souborům pro podřízeného uživatele

Ahoj,

po nedávném článku o sandboxingu pomocí systemd jsem se vrátil k řešení jednoho staršího problému s přístupovými právy na linuxovém filesystému (dále FS). Pro tuto diskusi to ještě o něco zjednoduším:

  • na serveru má účet uživatel Pepa (pepa), klidně s plnohonotným přístupem přes SSH, domovský adresář /home/pepa,
  • Pepa provozuje na serveru www stránky, celou webovou aplikaci má třeba v /home/pepa/www,
  • provoz té aplikace zajišťuje nějaký HTTP server (Apache atd.) běžící pod účtem www-data,
  • Pepa chce uvnitř adresáře nastavit přístupová práva pro HTTP server (přesněji: pro uživatele www-data, dále už jen "uživatel Webdata"), a to odlišně pro různé soubory/složky: k některým souborům nemá Webdata přístup vůbec, některé může jen číst, některé i zapisovat atd.,
  • kromě Pepy a Webdata nemá do /home/pepa/www nikdo jiný přístup.

Výše uvedené lze obecně zajistit i pomocí "obyčejných" práv FS, nejjenoduššeji asi tak, že se uživateli www-data přidá doplňková skupina (supplementary group) pepa a uživatel Pepa si ve své složce www ohlídá přístupová práva pro skupinu.

Problém ale nastává v případě, že chceme uživateli Webdata povolit vytvářet soubory (třeba ve složce /home/pepa/www/upload). Povolit to lze, ale Pepa tím ztratí kontrolu nad touto složkou. Vlastníkem nově vytvořených souborů pak bude uživatel www-data a ten si jako vlastník může dělat se svými soubory cokoliv, včetně toho, že k nim Pepovi zamezí přístup (vytvoří složku /home/pepa/www/upload/not-for-pepa, uloží do ní nějaký soubor a zakáže k ní přístup všem kromě vlastníka - Pepa pak se složkou už nic neudělá.

Proti tomu nepomohou třeba ani posixové ACL, protože ať je na /home/pepa/www vytvoříme libovolně včetně těch default,  tak jakmile v nich povolíme uživateli Webdata vytvářet soubory, může si on (Webdata) se svými nově vytvořenými soubory jako vlastník dělat co chce, včetně toho, že všechna ACL odstraní.

Jediný, kdo dokáže takto vytvořené soubory obecně odstranit (nebo aspoň zpřístupnit), je uživatel root. Jenže původní myšlenka byla umožnit Pepovi správu svého domovského adresáře včetně jeho webové aplikace.

Napadá vás, jak to řešit? V Linuxu je v tomto jen dvoúrovňová hierarchie: uživatel root je nadřazený všem ostatním. Já bych potřeboval, aby byl Pepa nějak "nadřazen" uživateli Webroot. Neuniklo mi nějaké jiné řešení? Vlastníka souboru při jeho vytváření podle mne nelze nijak ovlivnit (na rozdíl od skupiny - set-gid).

Dalo by se to nějak hezky řešit právě přes systemd a jeho sandboxing? Třeba takový Docker to vlastně umí (hierarchie: root na fyzickém serveru -> root v kontejneru -> ostatní uživatelé v kontejneru) a stačí mu na to jen jmenné prostory jádra.

Příklad jsem původně zjednodušil pro lepší vysvětlení. Ve skutečnosti to ale většina z nás provozuje na serverech složitěji: například běží jeden Nginx (uživatel www-data, jediný Nginx je zde např. kvůli sdílení jedné IP adresy pomocí TLS SNI) a ten komunikuje s několika dalšími "aplikačními" procesy (třeba WSGI, CGI), z nich by měl idálně každý běžet pod odděleným uživatelem (app1, app2, ...), aby se co nejméně ovlivňovaly (čti: aby si vzájemně neviděly do svých dat). A kód/data těch několika webů spravuje jeden nebo více uživatelů jako byl Pepa (ještě se dá zjednodušit, že jeden Pepa administruje jednu aplikaci, ale i té musí umět omezit třeba zápis do souborů, které na server Pepa sám zapsal, tj. Pepa nemůže být přímo uživatelem app). Další zjednodušení může být v tom, že uživateli www-data nebude potřeba povolit vytváření souborů, to budou smět jen (dle nastavení) uživatelé app.


Re:Přístupová práva k souborům pro podřízeného uživatele
« Odpověď #1 kdy: 26. 01. 2022, 13:41:58 »
Bez kontejnerizace je to jednoduche.

Nginx root slozka pro daneho uzivatele prava 2750, user:www-data.
Nastavit php(etc), aby bezelo pod danym uzivatelem.

Vysledek: do daneho rootu se dostane jen uzivatel a www-data. Uzivatel smi zapisovat, www-data jen cist. Jakkakoliv data vlozena skrz web budou zase user:www-data. Web server tedy nebude mit vubec prava zapsat kdekoli (pokud to nejaky tatar nezmeni), o zmeny na disku se bude starat ten php(etc) modul.

Re:Přístupová práva k souborům pro podřízeného uživatele
« Odpověď #2 kdy: 26. 01. 2022, 14:21:35 »
Citace
Nginx root slozka pro daneho uzivatele prava 2750, user:www-data.
Nastavit php(etc), aby bezelo pod danym uzivatelem.

Díky za návrh, ale to je řešení "level 1", tak to mám v podstatě teď. Problém, že by aplikační uživatel (pod kterým je třeba to PHP) mohl při zapisování vytvořit soubory, které nebudou přístupny programátorovi (Pepa), to řeší tak, že oba uživatele sloučí do jednoho - PHP běží pod účtem Pepa. Ale já jsem nechtěl, aby aplikace (PHP) měla stejná práva jako programátor. Nechci, aby aplikace mohla třeba modifikovat sama sebe:

Citace
... že jeden Pepa administruje jednu aplikaci, ale i té musí umět omezit třeba zápis do souborů, které na server Pepa sám zapsal, tj. Pepa nemůže být přímo uživatelem app

Re:Přístupová práva k souborům pro podřízeného uživatele
« Odpověď #3 kdy: 26. 01. 2022, 15:29:17 »
Ptate se na komplexitu, ktera vyplyva z navrhu a pozadavku aplikace na funkcionality.

Napr, co znamena administrace? Pouze zevnitr aplikace, nebo i ze serveru (typicky, ssh pristup)? Atd.

Nekdo to resi oddelenim dat od aplikace. At uz v ramci serveru, nebo sitove pristupnych sluzeb - rozsirene acl, db, fileshare, overlay, etc etc.

Na tahle obecny dotaz nelze moc konkretne odpovedet...

Re:Přístupová práva k souborům pro podřízeného uživatele
« Odpověď #4 kdy: 26. 01. 2022, 16:06:16 »
Na linuxu pro jednu úroveň tohle řeší sgid bit na adresáři – zařídí, že vlastnická skupina nově vytvořených souborů a adresářů bude shodná se skupinou adresáře, nikoli primární skupinou uživatele. Takže by existovala třeba skupina www-pepa, ve které by byl uživatel pepa i www-data. Tahle skupina by vlastnila adresář ~pepa/www. Na adresáři, kam má mít www-data právo zapisovat (třeba ~pepa/www/upload), pak bude nastaven sgid bit (a bude ho vlastnit také www-pepa), takže soubory v něm vytvořené bude také vlastnit skupina www-pepa. Nicméně nic nebrání uživateli www-data tu skupinu dodatečně změnit na nějakou jinou.

Na druhou stranu, pokud nemá adresář nastaven sticky bit, mazání souborů se neřídí právy souboru, ale právy nadřazeného adresáře – protože smazání souboru ve skutečnosti znamená „smazání záznamu o souboru v obsahu adresáře“. Takže neplatí vaše věta, že by uživatel pepa ztratil moc nad vytvořenými soubory v adresáři upload – bez sgid bitu by pepa sice třeba nemohl číst soubory v adresáři upload, ale smazat by je mohl. (Řeč je teď o situaci bez sgid bitu, nebo když uživatel www-data dodatečně skupinu změní.)

Komplikovanější to bude, pokud v tom adresáři upload bude webová aplikace vytvářet i podadresáře. Protože pak by bylo potřeba, aby i těmto podadresářům nastavovala sgid bit.

Unixová práva jsou neintuitivní a obvykle jakmile někde může jiný uživatel vytvářet adresáře, ztrácíte nad tou adresářovou strukturou kontrolu – máte totiž v ruce jenom defaulty, které může jiný uživatel ignorovat a které se často ani nepropisují automaticky do podřízených složek. Něco se dá obejít pomocí ACL, ale i tak je spoustu neřešitelných situací. Obecně unixová práva fungují tak, že brání, aby se uživatel nedostal k souborům, ke kterým přístup mít nemá. Nedokáží ale obecně zabránit tomu, aby uživatel sebral přístup někomu jinému k něčemu, k čemu přístup mít má. Což má svou logiku – když uživatel může ten soubor přepsat nulami nebo zkrátit na nulovou délku, jeho obsah může znehodnotit tak jako tak. Takže nedává smysl bránit mu ve znehodnocení souboru tím, že k němu odebere práva ostatním. Nicméně reálně ten případ, kdy odeberu práva ostatním, nastává v drtivé většině případů nechtěně, kdy prostě při vytváření nebo kopírování souboru či adresáře zůstanou práva nastavená nějak a nikdo neřeší, že by měl po té ještě správně nastavit práva.

Podle mého názoru jsou mnohem silnější hierarchická práva, jaká má třeba NTFS nebo je měl Novell. Na druhou stranu jsou náročnější na implementaci, zejména v prostředí, kdy můžete jeden adresář připojit kam je libo.