Een script dat een VPN-client van een leverancier start, blijft hangen tot de time-out, en het log laat zien dat de client om een verificatiecode vraagt die niemand heeft getypt. Het wachtwoord was doorgegeven, dus de voor de hand liggende conclusie is dat het wachtwoord fout is. Dat is het niet. De codevraag is een apart gesprek op een apart kanaal, en je script heeft dat nooit geopend.

Doorloop de vijf controles hieronder in volgorde. Stop bij de eerste die faalt, want elke latere stap veronderstelt dat de eerdere kloppen.

Controle 1: leest de client überhaupt standaardinvoer?

Test voordat je automatisering schrijft: stuur een dummy-geheim door een pijp naar de client en kijk wat er gebeurt. Als hij zijn prompt afdrukt en dan wacht, leest hij de pijp niet.

Veel clients openen het terminalapparaat direct, of weigeren een geheim van een stroom te nemen die geen terminal is, zodat een verdwaalde pijp geen wachtwoord kan lekken. OpenVPN is de gedocumenteerde uitzondering, omdat --auth-user-pass een bestandspad neemt. Clients van leveranciers die om een eenmalige code vragen, hebben meestal geen gelijkwaardige optie, en hun prompt wacht op een terminal die je script nooit heeft geleverd.

Controle 2: heeft het kindproces een terminal?

Een pty wijst een terminal toe aan het kind, wat prompts omzet in leesbare uitvoer die je in volgorde kunt beantwoorden.

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)

De promptreeksen hierboven zijn illustratief; kopieer de exacte tekst die je client afdrukt, inclusief hoofdletters en leestekens. Elke verwachting heeft een time-out, en een gesloten kind gooit een uitzondering in plaats van een status terug te geven, dus wikkel de reeks in en behandel het einde van het bestand als een fout. Let op wat dit blok niet doet: het kind sterft met het script, omdat een pty geen loskoppelingsmechanisme is en disown een ingebouwde shellopdracht is die een proces dat je script startte niet kan bereiken.

Controle 3: is er ondersteunde niet-interactieve invoer?

Schermschrapen breekt bij clientupdates, dus zoek eerst naar een gedocumenteerde optie.

Controleer de helpuitvoer op een token- of eenmalige-codeoptie, en controleer of de dienst de code accepteert die aan het wachtwoordveld is toegevoegd. Waar de client een inloggegevensbestand leest, geef hem het bestand in plaats van een prompt:

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

Procesvervanging geeft de client een leesbaar pad op systemen die /dev/fd bieden. Het geheim blijft een geheim vanuit het oogpunt van de client, dus houd het buiten logs, shellgeschiedenis en proceslijsten. Als de client /dev/fd weigert of het pad naar de inloggegevens meer dan eens opent, schrijf dan een echt bestand met strenge rechten en verwijder het in hetzelfde script.

Controle 4: overleeft de tunnel het script?

Standaard sterft de tunnel met zijn ouder, wat het tegenovergestelde is van wat een opstartscript nodig heeft.

disown -h helpt alleen als je de client als shelltaak hebt gestart, omdat het de taaktabel van die shell bewerkt en een proces dat je script via een pty startte niet kan bereiken. Een servicemanager is een betere plek voor alles wat zonder toezicht opnieuw moet verbinden, omdat hij de client herstart en vastlegt waarom hij stopte. Verwacht in elk geval een nieuwe code na elke herverbinding: een eenmalig token wordt verbruikt door de eerste geslaagde authenticatie.

Let op wat sudo met de reeks doet. Een sudo-wachtwoordprompt is niet de prompt van de VPN, en die met het VPN-wachtwoord beantwoorden is de meest voorkomende manier waarop een verder correcte verwachtingsorde toch faalt.

Controle 5: hoort de code van een persoon in een script?

Dit is de controle die mensen overslaan. Een token hoort bij een persoon, terwijl een tunnel die volgens een schema omhoog moet bij de machine hoort.

Als een taak zonder toezicht opnieuw moet verbinden, vraag dan of een machinecertificaat of een serviceaccount de interactieve login kan vervangen. Het automatiseren van iemands eenmalige code maakt van een tweede factor een opgeslagen geheim, wat een beleidswijziging is en geen gemak voor scripts. Waar de dienst beide ondersteunt, kies de inloggegevens die passen bij hoe de taak werkelijk draait. Schrijf het antwoord op, want de volgende persoon vraagt waarom het script een token houdt.

Hoe een werkend script eruitziet

Het script drukt de stap af die het bereikte, nooit het geheim, en eindigt met een niet-nul code bij elke mislukte verwachting.

Test het door het expres te breken: verkeerd wachtwoord, verkeerde groep, verlopen token. Elke fout zou bij een benoemde stap moeten stoppen in plaats van te hangen. Draai het daarna één keer tegen de echte dienst en controleer de tunnel van buiten het script, niet van binnen.

Gerelateerde artikelen