OpenVPN reaguje přesně na jeden výstup přihlašovacího skriptu: na návratový stav. Všechno ostatní, co skript dělá, je dekorace. Hook může dosáhnout správného verifikátoru, zpracovat odpověď a vytisknout přátelskou řádku, a přitom vrátit stav, který znamená opak toho, co autor zamýšlel. Přečtěte si nejdřív kontrakt a napište adaptér kolem něj, a celá tahle třída chyb zmizí.

Kontrakt je malý: identifikujte odeslaný účet, položte schválenému verifikátoru zamýšlenou otázku a přijměte jen dokumentovaný pozitivní výsledek tohoto verifikátoru pro daný požadavek. Všechno ostatní je infrastruktura.

Tři stavy, které hook může vrátit

Pro auth-user-pass-verify definuje manuál OpenVPN 2.6 návratový kód 0 jako přijetí, 1 jako odmítnutí a 2 jako odloženou autentizaci. To jsou jediné tři odpovědi, kterým server rozumí, a každá má pro spojení jiný důsledek. Skript, který skončí se stavem svého posledního příkazu, vlastně nechal o hlasu rozhodnout logovací volání nebo krok úklidu. Zapište stav výslovně v každé větvi, včetně větví, které se k verifikátoru nikdy nedostaly.

Úspěch HTTP a úspěch autentizace jsou oddělené vrstvy a jejich záměna je nejčastější způsob, jak tenhle hook selže. Odpověď 202 znamená, že požadavek byl přijat ke zpracování, ne že bylo ověřeno heslo. Definujte očekávaný stav, tvar odpovědi a konečný verdikt z API kontraktu, který jste dostali, a nevymýšlejte název pole jen proto, že vypadá věrohodně.

Pokud odpověď skutečně dorazí později, je to odložená cesta a tak je potřeba ji postavit. Odložený pokus, který se nikdy nedokončí, drží prostředky, dokud nevyprší časový limit.

Čtěte soubor s přihlašovacími údaji přesně tak, jak je zapsaný

U dokumentované metody přes soubor server zapíše uživatelské jméno a heslo jako první dva řádky dočasného souboru, předá tuto cestu skriptu a po návratu skriptu soubor odstraní. Čtěte ty dva řádky jako data: nikdy soubor nezpracujte přes source, nikdy ho nevyhodnocujte a nikdy jeho obsah nevkládejte do příkazové řádky, kde ho uvidí tabulka procesů. Zachovejte heslo bajt po bajtu, protože normalizace, kterou byste použili na uživatelské jméno, přihlašovací údaj tiše změní. Adresář pro tento dočasný soubor je rozhodnutí o nasazení, proto ověřte, že existuje a že ho na hostiteli nemůže číst každý.

Vlastní přihlašovací údaj verifikátoru držte odděleně od uživatelského: patří integraci brány, žije v úložišti tajemství platformy a potřebuje jen oprávnění ověřovat, takže není důkazem, že se autentizovala konkrétní osoba. Nedovolte ani, aby se hook stal druhým verifikátorem hesel. Ruční přepsání porovnání hashe se nezabezpečí optimalizací smyčky a udržovaný verifikátor už rozumí solenému a nákladnému schématu úložiště účtů.

Rozhodněte, co znamená nezařaditelná odpověď

Časové limity, chyby přenosu, poškozené odpovědi a nedostupný backend sdílejí jednu vlastnost: žádná z nich není pozitivní ověření. Hook by měl u každé z nich selhat zavřeně a zaznamenat důvod, podle kterého může operátor jednat. Ten důvod patří do chráněného logu, ne do zprávy vrácené člověku, který se snaží připojit.

Stejně opatrní buďte u cest, které se k verifikátoru vůbec nedostanou. Chybějící konfigurační hodnota, nečitelné tajemství nebo nenainstalovaná závislost by měly vyústit v odmítnutí s výrazným provozním markerem, ne v náhodné přijetí. Ty větve testujte odebráním závislosti v laboratoři, místo abyste o nich uvažovali. Tam, kde selhání logování může změnit návratový stav, se logování stalo součástí rozhodnutí a musí být učiněno neškodným.

Konfigurace serveru je důležitá i tady: uživatelsky definované skripty se uznávají jen tehdy, když je běžící konfigurace povoluje na požadované úrovni zabezpečení, a toto nastavení je záměrná volba, ne výchozí hodnota, kterou je třeba zvyšovat.

Ověřujte verdikt, ne vytištěnou řádku

Postavte test, který kontroluje návratový stav přímo. Napište vzorový soubor s přihlašovacími údaji, spusťte na něj hook se známým dobrým a známým špatným účtem a čtěte stav, který hlásí shell, ne text, který skript vypíše. Tato jediná kontrola zachytí většinu chyb v kontraktu dřív, než se klient vůbec připojí.

Potom prožeňte stejné případy skutečným klientem proti nelistovacímu posluchači a potvrďte, co server zaznamenal: přijato, odmítnuto nebo odloženo. Pokryjte deaktivovaný účet, špatné heslo, poškozenou odpověď verifikátoru, časový limit a nedostupný verifikátor. Pokud některý případ skončí ve stavu, který nedokážete pojmenovat, adaptér není hotový.

Držte mapování výsledku verifikátoru na návratový stav vedle skriptu v repozitáři, aby si další inženýr mohl přečíst kontrakt bez reverzního inženýrství kódu.

Související články