Hvorfor en OpenVPN-hook ikke finner filen ved siden av skriptet
Relative stier i en hook løses mot prosessen, ikke mot skriptet. Forankre dem med __file__, og kontroller deretter navnerom og identitet før tillatelser.
Kroker som kjører uten feil og likevel rapporterer en manglende fil, ser vanligvis på feil sted, ikke at de svikter i jobben sin. Relative stier i et skript løses mot prosessens arbeidskatalog, og en tjeneste starter med en arbeidskatalog du ikke har valgt. Filen ved siden av skriptet og filen prosessen åpner, er bare det samme når noe forankrer dem. Det gapet forklarer en stor del av krokfeilene som feilaktig leses som tillatelsesproblemer.
Kontroller stien før tillatelsene, fordi en tillatelsesfeil på feil fil fortsatt er feil fil.
En relativ sti løses mot prosessen, ikke mot filen
Når et skript kaller open("policy.json"), løser kjernen navnet mot prosessens nåværende arbeidskatalog. Ingenting ved skriptets egen plassering deltar i det oppslaget. OpenVPN starter kroker fra en katalog den velger selv, og valget cd kan endre den, så et skript testet manuelt fra sin egen mappe oppfører seg annerledes når daemonen kjører det. Den manuelle testen består, tjenestekjøringen feiler, og logglinjen nevner bare det manglende navnet.
Python eksponerer skriptets plassering som __file__, og det er det som gjør forankring mulig. Path(__file__).resolve().parent / "policy.json" bygger en sti fra filen i stedet for fra prosessen. Den ene linjen fjerner avhengigheten av arbeidskatalogen uten å endre noe ved privilegiene.
Forankre stien med vilje, og kontroller deretter hva resolve gjør
resolve() følger symbolske lenker, så en installasjon som lenker kroken på plass, forankrer ved lenkens mål, ikke ved katalogen som holder lenken. Det er vanligvis det du vil ha for en versjonert utrulling, og det er feil for et oppsett som forventer data ved siden av den symbolske lenken. Bestem hva utrullingen mener, og skriv koden deretter i stedet for å oppdage forskjellen i produksjon. Path(__file__).parent uten resolve() beholder lenkens egen katalog.
Hvis dataene tilhører instansen og ikke programmet, ta en absolutt sti fra konfigurasjonen. Hardkoding av en plassering binder kroken til ett vertsoppsett.
Gå gjennom fire grenser i rekkefølge
Start med arbeidskatalogen: sammenlign enhetens WorkingDirectory, OpenVPNs cd valg og enhver innpakning som bytter katalog før exec. Bekreft deretter den løste plasseringen, fordi en fil med samme navn i en annen utrulling kan svare på oppslaget og skjule feilen. Deretter kommer filsystemvisningen: en chroot eller et mount-navnerom for tjenesten kan gjøre en absolutt vertssti rett og slett fraværende. Til slutt er det tilgangsidentiteten, som er et spørsmål atskilt fra synlighet.
ProtectHome og PrivateTmp skjuler forskjellige plasseringer, og ingen av dem vises i en katalogliste tatt fra verten. En sti som finnes for root i et skall, kan være usynlig inne i enhetens navnerom, og derfor beviser testing av samme kommando utenfor tjenesten så lite.
Rett oppslaget uten å utvide tjenesten
Forankring av stien løser bare den første grensen. Det avdekker ikke en katalog tjenesten skjuler, og det gir ikke en uprivilegert konto tilgang til en fil som bare er for root. Å øke script-security endrer hvilke skript OpenVPN vil kjøre; det har ingen effekt på hvor et relativt navn løses. Å endre arbeidskatalogen for hele tjenesten er bredere enn problemet, fordi enhver annen relativ sertifikat-, logg- eller hjelpersti flytter med.
Foretrekk den smale rettelsen: en deterministisk sti i skriptet, en eksplisitt konfigurasjonsverdi for instansdata og fil-eierskap som samsvarer med kontoen kroken faktisk kjører som.
Registrer bevis som navngir grensen
En nyttig feilrapport inneholder tre ting: den nøyaktige stien kroken forsøkte, miljøet som frembrakte den, og hvilken grense som avviste. Skriv ut den løste stien og unntaket uten å dumpe filens innhold. Den tredelingen skiller en feil forankring fra en skjult mount og fra en nektet tillatelse, som er tre forskjellige rettelser.
Påstanden om at root kan lese filen fra en terminal besvarer ett av de spørsmålene og ingen av de andre. Test i stedet fra tjenestens eget kontekst.