Куките, които работят без грешка и все пак съобщават за липсващ файл, обикновено гледат на грешното място, а не се провалят в работата си. Относителните пътища в скрипта се разрешават спрямо работната директория на процеса, а услугата стартира с работна директория, която не сте избрали. Файлът до скрипта и файлът, който процесът отваря, са едно и също нещо само когато нещо ги закотви. Тази разлика обяснява голяма част от отказите на куки, които погрешно се четат като проблеми с правата.

Проверете пътя преди правата, защото грешка в правата върху грешния файл пак е грешният файл.

Относителният път се разрешава спрямо процеса, не спрямо файла

Когато скрипт извика open("policy.json"), ядрото разрешава името спрямо текущата работна директория на процеса. Нищо от местоположението на самия скрипт не участва в това търсене. OpenVPN стартира куки от директория, която избира сам, и опцията cd може да я смени, така че скрипт, тестван на ръка от собствената му папка, се държи различно, щом демонът го стартира. Ръчният тест минава, стартирането на услугата се проваля, а редът в журнала споменава само липсващото име.

Python показва местоположението на скрипта като __file__, което прави закотвянето възможно. Path(__file__).resolve().parent / "policy.json" изгражда път от файла, а не от процеса. Този един ред премахва зависимостта от работната директория, без да променя нищо по привилегиите.

Закотвяйте пътя съзнателно, после проверете какво прави resolve

resolve() следва символни връзки, така че инсталация, която свързва куката на място, се закотвя в целта на връзката, а не в директорията, която държи връзката. Обикновено това е желаното за версионирано разгръщане и е грешно за схема, която очаква данни до символната връзка. Решете кое има предвид разгръщането и напишете кода да съвпада, вместо да откривате разликата в продукция. Path(__file__).parent без resolve() запазва собствената директория на връзката.

Ако данните принадлежат на инстанцията, а не на програмата, вземете абсолютен път от конфигурацията. Твърдото кодиране на местоположение обвързва куката с една схема на хоста.

Минете четири граници по ред

Започнете с работната директория: сравнете WorkingDirectory на юнита, опцията cd на OpenVPN и всяка обвивка, която сменя директорията преди exec. После потвърдете разрешеното местоположение, защото файл с подобно име в друго разгръщане може да отговори на търсенето и да скрие грешката. Следва изгледът на файловата система: chroot или mount пространство на услугата може просто да направят абсолютен път на хоста отсъстващ. Последна е самоличността за достъп, която е отделен въпрос от видимостта.

ProtectHome и PrivateTmp скриват различни местоположения и нито едно не се показва в списък на директория, взет от хоста. Път, който съществува за root в шел, може да е невидим вътре в пространството от имена на юнита и затова тестването на същата команда извън услугата доказва толкова малко.

Поправете търсенето, без да разширявате услугата

Закотвянето на пътя решава само първата граница. То не открива директория, която услугата скрива, и не дава на непривилегирован акаунт достъп до файл само за root. Повишаването на script-security променя кои скриптове ще стартира OpenVPN; то не влияе на това къде се разрешава относително име. Смяната на работната директория за цялата услуга е по-широка от проблема, защото всеки друг относителен път до сертификат, журнал или помощник се мести с нея.

Предпочитайте тясната поправка: детерминиран път в скрипта, явна стойност в конфигурацията за данните на инстанцията и собственост на файловете, съответстваща на акаунта, под който куката реално работи.

Записвайте доказателства, които назовават границата

Полезният отчет за отказ съдържа три неща: точния път, който куката е опитала, средата, която го е създала, и коя граница е отказала. Отпечатайте разрешения път и изключението, без да изливате съдържанието на файла. Тази тройка отделя грешно закотвяне от скрита mount точка и от отказ в правата, а това са три различни поправки.

Твърдението, че root може да прочете файла от терминал, отговаря на един от тези въпроси и на нито един от останалите. Вместо това тествайте от собствения контекст на услугата.

Подобни статии