Hooki, które działają bez błędu, a mimo to zgłaszają brakujący plik, zwykle patrzą w niewłaściwe miejsce, a nie zawodzą w swoim zadaniu. Względne ścieżki w skrypcie są rozwiązywane względem katalogu roboczego procesu, a usługa startuje z katalogiem roboczym, którego nie wybraliście. Plik obok skryptu i plik, który otwiera proces, są tym samym tylko wtedy, gdy coś je zakotwiczy. Ta luka wyjaśnia dużą część awarii hooków, które są błędnie czytane jako problemy z uprawnieniami.

Sprawdź ścieżkę przed uprawnieniami, bo błąd uprawnień na niewłaściwym pliku to nadal niewłaściwy plik.

Ścieżka względna jest rozwiązywana względem procesu, nie pliku

Gdy skrypt wywołuje open("policy.json"), jądro rozwiązuje nazwę względem bieżącego katalogu roboczego procesu. Nic z położenia samego skryptu nie bierze udziału w tym wyszukiwaniu. OpenVPN uruchamia hooki z katalogu, który sam wybiera, a opcja cd może go zmienić, więc skrypt testowany ręcznie ze swojego folderu zachowuje się inaczej, gdy uruchomi go demon. Test ręczny przechodzi, uruchomienie usługi kończy się niepowodzeniem, a wiersz logu wspomina tylko brakującą nazwę.

Python udostępnia położenie skryptu jako __file__, i to właśnie umożliwia zakotwiczenie. Path(__file__).resolve().parent / "policy.json" buduje ścieżkę z pliku, a nie z procesu. Ta jedna linia usuwa zależność od katalogu roboczego, nie zmieniając niczego w uprawnieniach.

Zakotwicz ścieżkę świadomie, a potem sprawdź, co robi resolve

resolve() podąża za dowiązaniami symbolicznymi, więc instalacja, która dowiązuje hook na miejsce, zakotwicza się w celu dowiązania, a nie w katalogu zawierającym dowiązanie. Zwykle tego chcemy przy wdrożeniu wersjonowanym, a jest to błędne dla układu, który oczekuje danych obok dowiązania symbolicznego. Zdecyduj, co wdrożenie ma na myśli, i napisz kod zgodnie z tym, zamiast odkrywać różnicę na produkcji. Path(__file__).parent bez resolve() zachowuje własny katalog dowiązania.

Jeśli dane należą do instancji, a nie do programu, weź ścieżkę bezwzględną z konfiguracji. Zakodowanie lokalizacji na stałe wiąże hook z jednym układem hosta.

Przejdź cztery granice po kolei

Zacznij od katalogu roboczego: porównaj WorkingDirectory, opcję cd OpenVPN i każdą otoczkę, która zmienia katalog przed exec. Potem potwierdź rozwiązaną lokalizację, bo plik o podobnej nazwie w innym wdrożeniu może odpowiedzieć na wyszukiwanie i ukryć błąd. Następnie przychodzi widok systemu plików: chroot lub przestrzeń nazw montowania usługi mogą po prostu uczynić bezwzględną ścieżkę hosta nieobecną. Na końcu tożsamość dostępu, która jest kwestią odrębną od widoczności.

ProtectHome i PrivateTmp ukrywają różne lokalizacje, i żadne z nich nie pojawia się w liście katalogu pobranej z hosta. Ścieżka istniejąca dla root w powłoce może być niewidoczna wewnątrz przestrzeni nazw jednostki, dlatego testowanie tej samej komendy poza usługą dowodzi tak niewiele.

Napraw wyszukiwanie bez rozszerzania usługi

Zakotwiczenie ścieżki rozwiązuje tylko pierwszą granicę. Nie ujawnia katalogu, który usługa ukrywa, i nie daje kontu bez uprawnień dostępu do pliku tylko dla root. Podniesienie script-security zmienia, które skrypty OpenVPN uruchomi; nie ma żadnego wpływu na to, gdzie rozwiązywana jest nazwa względna. Zmiana katalogu roboczego dla całej usługi jest szersza niż problem, ponieważ każda inna względna ścieżka certyfikatu, logu lub pomocnika przesuwa się razem z nią.

Preferuj wąską poprawkę: deterministyczna ścieżka w skrypcie, jawna wartość konfiguracji dla danych instancji i własność plików odpowiadająca kontu, pod którym hook rzeczywiście działa.

Zapisuj dowody, które nazywają granicę

Użyteczny raport awarii zawiera trzy rzeczy: dokładną ścieżkę, której próbował hook, środowisko, które ją wytworzyło, i która granica odmówiła. Wydrukuj rozwiązaną ścieżkę i wyjątek bez wylewania zawartości pliku. Ta trójka oddziela błędne zakotwiczenie od ukrytego montowania i od odmowy uprawnień, a to trzy różne poprawki.

Twierdzenie, że root może odczytać plik z terminala, odpowiada na jedno z tych pytań i na żadne z pozostałych. Zamiast tego testuj z kontekstu samej usługi.

Powiązane artykuły