Kuke koje rade bez greške, a ipak prijave nedostajuću datoteku, obično gledaju na pogrešno mjesto, a ne podbacuju u svom poslu. Relativne putanje u skripti rješavaju se prema radnom direktoriju procesa, a servis se pokreće s radnim direktorijem koji niste odabrali. Datoteka pored skripte i datoteka koju proces otvori ista su stvar samo kad ih nešto usidri. Taj jaz objašnjava velik dio kvarova kuka koji se pogrešno čitaju kao problemi s dozvolama.

Provjerite putanju prije dozvola, jer greška dozvole na pogrešnoj datoteci ipak je pogrešna datoteka.

Relativna putanja rješava se prema procesu, a ne prema datoteci

Kad skripta pozove open("policy.json"), jezgra rješava ime prema trenutnom radnom direktoriju procesa. Ništa iz vlastite lokacije skripte ne sudjeluje u tom traženju. OpenVPN pokreće kuke iz direktorija koji sam odabere, a opcija cd može ga promijeniti, pa se skripta testirana ručno iz vlastite mape ponaša drukčije kad je pokrene daemon. Ručni test prolazi, pokretanje servisa pada, a linija dnevnika spominje samo ime koje nedostaje.

Python izlaže lokaciju skripte kao __file__, i to omogućuje sidrenje. Path(__file__).resolve().parent / "policy.json" gradi putanju iz datoteke, a ne iz procesa. Taj jedan redak uklanja ovisnost o radnom direktoriju bez promjene bilo čega u privilegijama.

Namjerno usidrite putanju, pa provjerite šta resolve radi

resolve() slijedi simboličke veze, pa se instalacija koja kuku poveže na mjesto sidri na cilju veze, a ne na direktoriju koji drži vezu. To je obično ono što želite za verzionirano postavljanje, a pogrešno je za raspored koji očekuje podatke pored simboličke veze. Odlučite što postavljanje znači i napišite kod u skladu s tim, umjesto da razliku otkrijete u produkciji. Path(__file__).parent bez resolve() čuva vlastiti direktorij veze.

Ako podaci pripadaju instanci, a ne programu, uzmite apsolutnu putanju iz konfiguracije. Tvrdo kodiranje lokacije veže kuku za jedan raspored hosta.

Prođite četiri granice redom

Počnite s radnim direktorijem: uporedite WorkingDirectory, opciju cd OpenVPN-a i svaki omotač koji mijenja direktorij prije exec. Zatim potvrdite riješenu lokaciju, jer datoteka sličnog imena u drugom postavljanju može odgovoriti na traženje i sakriti grešku. Sljedeći je pogled na datotečni sistem: chroot ili mount imenski prostor servisa mogu apsolutnu putanju hosta jednostavno učiniti odsutnom. Posljednji je identitet pristupa, što je pitanje odvojeno od vidljivosti.

ProtectHome i PrivateTmp skrivaju različite lokacije i nijedno se ne pojavljuje u ispisu direktorija uzetom s hosta. Putanja koja postoji za root u ljusci može biti nevidljiva unutar imenskog prostora jedinice, i zato testiranje iste naredbe izvan servisa tako malo dokazuje.

Ispravite traženje bez proširenja servisa

Sidrenje putanje rješava samo prvu granicu. Ono ne otkriva direktorij koji servis skriva i ne daje neprivilegovanom računu pristup datoteci samo za root. Podizanje script-security mijenja koje će skripte OpenVPN pokretati; to ne utječe na to gdje se relativno ime rješava. Mijenjanje radnog direktorija za cijeli servis šire je od problema, jer se svaka druga relativna putanja certifikata, dnevnika ili pomoćnika pomiče s njim.

Preferirajte usko rješenje: deterministička putanja u skripti, eksplicitna konfiguracijska vrijednost za podatke instance i vlasništvo datoteka koje odgovara računu pod kojim kuka stvarno radi.

Zabilježite dokaze koji imenuju granicu

Korisno izvješće o kvaru sadrži tri stvari: točnu putanju koju je kuka pokušala, okruženje koje ju je proizvelo i koja je granica odbila. Ispišite riješenu putanju i iznimku bez izlijevanja sadržaja datoteke. Ta trojka razdvaja pogrešno sidro od skrivenog montiranja i od odbijanja dozvole, a to su tri različita rješenja.

Tvrdnja da root može pročitati datoteku iz terminala odgovara na jedno od tih pitanja i nijedno od ostalih. Umjesto toga testirajte iz vlastitog konteksta servisa.

Povezani članci