Háčky, které běží bez chyby a přesto hlásí chybějící soubor, obvykle hledají na špatném místě, ne že by selhávaly ve své práci. Relativní cesty ve skriptu se řeší vůči pracovnímu adresáři procesu a služba startuje s pracovním adresářem, který jste nezvolili. Soubor vedle skriptu a soubor, který proces otevře, jsou totéž jen tehdy, když je něco ukotví. Ten rozdíl vysvětluje velkou část selhání háčků, která se chybně čtou jako problémy s oprávněními.

Zkontrolujte cestu dřív než oprávnění, protože chyba oprávnění u špatného souboru je pořád špatný soubor.

Relativní cesta se řeší vůči procesu, ne vůči souboru

Když skript zavolá open("policy.json"), jádro vyřeší jméno vůči aktuálnímu pracovnímu adresáři procesu. Na umístění samotného skriptu v tomto hledání nic nezáleží. OpenVPN spouští háčky z adresáře, který si sám zvolí, a volba cd ho může změnit, takže skript testovaný ručně ze své vlastní složky se chová jinak, jakmile ho spustí démon. Ruční test projde, spuštění služby selže a řádek v logu zmíní jen chybějící jméno.

Python vystavuje umístění skriptu jako __file__, a právě to ukotvení umožňuje. Path(__file__).resolve().parent / "policy.json" sestaví cestu ze souboru, ne z procesu. Ten jediný řádek odstraní závislost na pracovním adresáři, aniž by změnil cokoli na oprávněních.

Ukotvěte cestu záměrně a pak zkontrolujte, co resolve dělá

resolve() sleduje symbolické odkazy, takže instalace, která háček propojí na místo, se ukotví na cíl odkazu, ne na adresář, který odkaz drží. To je obvykle to, co u verzovaného nasazení chcete, a je to špatně pro uspořádání, které očekává data vedle symbolického odkazu. Rozhodněte, co nasazení znamená, a napište kód podle toho, místo abyste rozdíl objevili v produkci. Path(__file__).parent bez resolve() zachová vlastní adresář odkazu.

Pokud data patří instanci, a ne programu, vezměte absolutní cestu z konfigurace. Natvrdo zapsané umístění váže háček na jedno uspořádání hostitele.

Projděte čtyři hranice popořadě

Začněte pracovním adresářem: porovnejte WorkingDirectory, volbu cd OpenVPN a jakýkoli obal, který mění adresář před exec. Pak potvrďte vyřešené umístění, protože soubor podobného jména v jiném nasazení může hledání odpovědět a chybu skrýt. Následuje pohled na souborový systém: chroot nebo mount jmenný prostor služby mohou absolutní cestu hostitele prostě učinit nepřítomnou. Nakonec identita přístupu, což je otázka oddělená od viditelnosti.

ProtectHome a PrivateTmp skrývají různá umístění a ani jedno se neobjeví ve výpisu adresáře pořízeném z hostitele. Cesta, která pro root v shellu existuje, může být uvnitř jmenného prostoru jednotky neviditelná, a proto testování stejného příkazu mimo službu dokazuje tak málo.

Opravte hledání bez rozšíření služby

Ukotvení cesty řeší jen první hranici. Neodhalí adresář, který služba skrývá, a nedá neprivilegovanému účtu přístup k souboru jen pro root. Zvýšení script-security mění, které skripty OpenVPN spustí; na to, kde se relativní jméno řeší, nemá vliv. Změna pracovního adresáře pro celou službu je širší než problém, protože každá další relativní cesta k certifikátu, logu nebo pomocníku se s ní posune.

Dejte přednost úzké opravě: deterministická cesta ve skriptu, explicitní konfigurační hodnota pro data instance a vlastnictví souborů odpovídající účtu, pod kterým háček skutečně běží.

Zaznamenejte důkazy, které pojmenují hranici

Užitečná zpráva o selhání obsahuje tři věci: přesnou cestu, kterou háček zkusil, prostředí, které ji vytvořilo, a která hranice odmítla. Vypište vyřešenou cestu a výjimku, aniž byste vylili obsah souboru. Ta trojice odděluje špatné ukotvení od skrytého mountu a od odmítnutí oprávnění, což jsou tři různé opravy.

Tvrzení, že root může soubor přečíst z terminálu, odpovídá na jednu z těch otázek a na žádnou jinou. Testujte místo toho z vlastního kontextu služby.

Související články