Un script care pornește un client VPN de la un furnizor rămâne blocat până la expirarea timpului, iar jurnalul arată că clientul cere un cod de verificare pe care nimeni nu l-a tastat. Parola a fost furnizată, deci concluzia evidentă este că parola este greșită. Nu este. Cererea codului este o conversație separată pe un canal separat, iar scriptul tău nu a deschis-o niciodată.

Parcurge cele cinci verificări de mai jos în ordine. Oprește-te la prima care eșuează, pentru că fiecare pas ulterior presupune că anterioarele sunt valabile.

Verificarea 1: clientul citește intrarea standard, măcar?

Testează înainte de a scrie orice automatizare: trimite un secret fals clientului printr-o conductă și urmărește ce se întâmplă. Dacă își tipărește cererea și apoi așteaptă, nu citește conducta.

Mulți clienți deschid dispozitivul de terminal direct, sau refuză să ia un secret dintr-un flux care nu este terminal, ca o conductă rătăcită să nu poată scurge o parolă. OpenVPN este excepția documentată, pentru că --auth-user-pass acceptă o cale de fișier. Clienții furnizorilor care cer un cod de unică folosință nu au de obicei o opțiune echivalentă, iar cererea lor așteaptă un terminal pe care scriptul tău nu l-a oferit niciodată.

Verificarea 2: procesul copil are un terminal?

Un pty alocă un terminal copilului, ceea ce transformă cererile în ieșire lizibilă la care poți răspunde în ordine.

import pexpect

child = pexpect.spawn("openconnect vpn.example.net", encoding="utf-8", timeout=30)
child.expect("GROUP:")
child.sendline("staff")
child.expect("USERNAME:")
child.sendline("alice")
child.expect("PASSWORD:")
child.sendline(PASSWORD)
child.expect("Connected as", timeout=60)

Șirurile de cereri de mai sus sunt ilustrative; copiază textul exact pe care îl tipărește clientul tău, inclusiv majusculele și punctuația. Fiecare așteptare are un timp limită, iar un copil închis aruncă o excepție în loc să returneze o stare, așa că înfășoară secvența și tratează sfârșitul fișierului ca pe un eșec. Observă ce nu face acest bloc: copilul moare odată cu scriptul, pentru că un pty nu este un mecanism de detașare, iar disown este o comandă internă a shell-ului care nu poate ajunge la un proces pe care scriptul tău l-a pornit.

Verificarea 3: există o intrare neinteractivă acceptată?

Răzuirea ecranului se strică la actualizările clientului, așa că încearcă mai întâi o opțiune documentată.

Verifică ieșirea de ajutor pentru o opțiune de token sau cod de unică folosință și verifică dacă serviciul acceptă codul adăugat la câmpul parolei. Acolo unde clientul citește un fișier de acreditări, dă-i fișierul în loc de o cerere:

openvpn --config office.ovpn --auth-user-pass <(printf "%s\n%s\n" "$USER_NAME" "$PASSWORD")

Substituirea de procese îi dă clientului o cale lizibilă pe sistemele care oferă /dev/fd. Secretul rămâne un secret din punctul de vedere al clientului, așa că ține-l departe de jurnale, de istoricul shell-ului și de listele de procese. Dacă clientul respinge /dev/fd sau deschide calea acreditărilor de mai multe ori, scrie un fișier real cu permisiuni restrictive și șterge-l în același script.

Verificarea 4: tunelul va supraviețui scriptului?

Implicit tunelul moare odată cu părintele său, ceea ce este opusul a ceea ce are nevoie un script de pornire.

disown -h ajută doar când ai pornit clientul ca sarcină a shell-ului, pentru că editează tabelul de sarcini al acelui shell și nu poate ajunge la un proces pe care scriptul tău l-a pornit printr-un pty. Un manager de servicii este o casă mai bună pentru tot ce trebuie să se reconecteze fără supraveghere, pentru că repornește clientul și înregistrează de ce a murit. În orice caz, așteaptă un cod nou după fiecare reconectare: un token de unică folosință este consumat de prima autentificare reușită.

Urmărește ce face sudo secvenței. Cererea de parolă a sudo nu este cererea VPN-ului, iar a răspunde la ea cu parola VPN este cea mai obișnuită cale prin care o ordine de așteptări altfel corectă eșuează totuși.

Verificarea 5: codul unei persoane ar trebui să fie într-un script?

Aceasta este verificarea pe care oamenii o sar. Un token aparține unei persoane, în timp ce un tunel care trebuie să urce după un program aparține mașinii.

Dacă o sarcină trebuie să se reconecteze fără supraveghere, întreabă dacă un certificat de mașină sau un cont de serviciu poate înlocui autentificarea interactivă. Automatizarea codului de unică folosință al cuiva transformă un al doilea factor într-un secret stocat, ceea ce este o schimbare de politică și nu o comoditate de script. Acolo unde serviciul le acceptă pe amândouă, alege acreditarea care se potrivește cu modul în care rulează sarcina în realitate. Scrie răspunsul, pentru că următoarea persoană va întreba de ce scriptul ține un token.

Cum arată un script care funcționează

Scriptul tipărește pasul la care a ajuns, niciodată secretul, și iese cu un cod diferit de zero la orice așteptare eșuată.

Testează-l stricându-l intenționat: parolă greșită, grup greșit, token expirat. Fiecare eșec ar trebui să se oprească la un pas numit în loc să se blocheze. Apoi rulează-l o dată împotriva serviciului real și verifică tunelul din afara scriptului, nu din interior.

Articole similare