Et skript som starter en leverandørs VPN-klient, henger til det timer ut, og loggen viser at klienten ber om en bekreftelseskode som ingen skrev inn. Passordet ble sendt, så den åpenbare konklusjonen er at passordet er feil. Det er det ikke. Kodeprompten er en separat samtale på en separat kanal, og skriptet ditt åpnet den aldri.

Gå gjennom de fem kontrollene nedenfor i rekkefølge. Stopp ved den første som feiler, fordi hvert senere trinn forutsetter at de tidligere holder.

Kontroll 1: leser klienten standard inndata i det hele tatt?

Test før du skriver noen automatisering: send en dummy-hemmelighet gjennom et rør til klienten og se hva som skjer. Hvis den skriver ut prompten og deretter venter, leser den ikke røret.

Mange klienter åpner terminalenheten direkte, eller nekter å ta en hemmelighet fra en strøm som ikke er en terminal, slik at et villfarent rør ikke kan lekke et passord. OpenVPN er det dokumenterte unntaket, fordi --auth-user-pass tar en filbane. Leverandørklienter som ber om en engangskode har vanligvis ingen tilsvarende bryter, og prompten deres venter på en terminal som skriptet ditt aldri stilte til rådighet.

Kontroll 2: har barneprosessen en terminal?

En pty tildeler en terminal til barnet, noe som gjør prompter om til lesbar utdata du kan svare på i rekkefølge.

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)

Promptstrengene over er illustrative; kopier den nøyaktige teksten klienten din skriver ut, inkludert store og små bokstaver og tegnsetting. Hver forventning har en tidsgrense, og et lukket barn kaster et unntak i stedet for å returnere en status, så pakk inn sekvensen og behandle slutten av filen som en feil. Legg merke til hva denne blokken ikke gjør: barnet dør med skriptet, fordi en pty ikke er en frakoblingsmekanisme, og disown er en innebygd skallkommando som ikke kan nå en prosess skriptet ditt startet.

Kontroll 3: finnes det støttet ikke-interaktiv inndata?

Skjermskraping bryter sammen ved klientoppdateringer, så se etter en dokumentert bryter først.

Sjekk hjelpeutdataene for et token- eller engangskodevalg, og sjekk om tjenesten godtar koden som er lagt til passordfeltet. Der klienten leser en påloggingsfil, gi den filen i stedet for en prompt:

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

Prosessubstitusjon gir klienten en lesbar bane på systemer som tilbyr /dev/fd. Hemmeligheten er fortsatt en hemmelighet fra klientens side, så hold den unna logger, skallhistorikk og prosesslister. Hvis klienten avviser /dev/fd eller åpner påloggingsbanen mer enn én gang, skriv en ekte fil med strenge tillatelser og slett den i samme skript.

Kontroll 4: overlever tunnelen skriptet?

Som standard dør tunnelen med forelderen sin, noe som er det motsatte av hva et oppstartsskript trenger.

disown -h hjelper bare når du startet klienten som en skalljobb, fordi den redigerer jobbtabellen til det skallet og ikke kan nå en prosess skriptet ditt startet gjennom en pty. En tjenestebehandler er et bedre hjem for alt som må koble til på nytt uten tilsyn, fordi den starter klienten på nytt og registrerer hvorfor den døde. Uansett, forvent en ny kode etter hver gjenoppkobling: et engangstoken brukes opp av den første vellykkede autentiseringen.

Legg merke til hva sudo gjør med sekvensen. En sudo-passordprompt er ikke VPN-ens prompt, og å svare på den med VPN-passordet er den vanligste måten en ellers korrekt forventningsrekkefølge likevel feiler.

Kontroll 5: bør en persons kode være i et skript?

Dette er kontrollen folk hopper over. Et token tilhører en person, mens en tunnel som må opp etter en plan tilhører maskinen.

Hvis en jobb må koble til på nytt uten tilsyn, spør om et maskinsertifikat eller en tjenestekonto kan erstatte den interaktive innloggingen. Å automatisere noens engangskode gjør en annen faktor til en lagret hemmelighet, noe som er en policyendring og ikke en bekvemmelighet for skript. Der tjenesten støtter begge, velg den påloggingen som passer med hvordan jobben faktisk kjører. Skriv ned svaret, fordi neste person vil spørre hvorfor skriptet holder et token.

Hvordan et fungerende skript ser ut

Skriptet skriver ut trinnet det nådde, aldri hemmeligheten, og avslutter med en ikke-null kode ved enhver mislykket forventning.

Test det ved å ødelegge det med vilje: feil passord, feil gruppe, utløpt token. Hver feil bør stoppe ved et navngitt trinn i stedet for å henge. Kjør det deretter én gang mot den ekte tjenesten, og kontroller tunnelen utenfra skriptet, ikke innenfra.

Relaterte artikler