OpenVPN leest het wachtwoord van de terminal, niet van stdin
Waar OpenVPN echt een wachtwoord leest, waarom een bestand op stdin faalt, en de drie ondersteunde routes voor gescripte aanmelding op Linux en macOS.
OpenVPN vraagt om een gebruikersnaam en wachtwoord op de sturende terminal, en een bestand dat naar de standaardinvoer wordt omgeleid is die terminal niet. Dat ene detail verklaart het script dat blijft hangen terwijl het wachtwoord daar in de pijp staat. De prompt wordt door de client getekend en het lezen gebeurt van het terminalapparaat, dus stdin omleiden verandert niets. Voed de client via een van zijn gedocumenteerde invoerroutes en hetzelfde script verbindt bij de eerste poging.
Drie routes dekken bijna elk geval, en elk faalt op zijn eigen manier. Kies op basis van de prompt die de client echt toont, niet op basis van de optie die het makkelijkst te scripten is.
De prompt komt niet van stdin
Wanneer OpenVPN inloggegevens nodig heeft, opent het de sturende terminal en leest daar. Daarom ziet een interactieve test er goed uit, terwijl hetzelfde commando onder cron of een unit-bestand stil blijft staan met de prompt in een log geschreven waar niemand naar kijkt. Sommige builds vallen terug op de standaardinvoer als er geen terminal is, en die inconsistentie is erger dan een harde fout, omdat ze het probleem tot de uitrol verbergt.
Controleer de omgeving voordat je code schrijft: voer de client uit onder dezelfde gebruiker, met dezelfde stdin, als de planner of servicemanager zal doen. Als de prompt nooit in het log verschijnt en het proces geen voortgang maakt, wacht er iets op een terminal die niet bestaat.
Eerste route: een inlogbestand met twee regels
De authenticatieoptie neemt een pad, en het bestand bevat precies twee regels, eerst de gebruikersnaam en dan het wachtwoord, en niets anders. Geef het pad expliciet op in plaats van op een standaardbestandsnaam te vertrouwen, want een verdwaald inlogbestand in de werkmap is hoe het verkeerde account in gebruik raakt. Zet de modus op 0600 en geef het eigendom aan het account dat de client uitvoert.
De client leest dat bestand één keer bij het starten, dus het wachtwoord roteren betekent het proces herstarten. Dat is meestal het gedrag dat je wilt, en het hoort in de runbook naast de rotatieprocedure.
Tweede route: askpass voor de wachtwoordzin van de sleutel
Een met een wachtwoordzin beveiligde privésleutel roept een tweede, andere prompt op, en die heeft zijn eigen bestandsgebaseerde antwoord: de optie askpass leest de wachtwoordzin van de eerste regel van een bestand. Voor op SSH gebaseerde tunnels is het equivalent een askpass-programma dat de client uitvoert, en waarvan de standaarduitvoer het geheim wordt.
Geen van beide vormen zet het geheim in de argumentenlijst, en beide laten het bestaan als bestand of als een uitvoerbaar programma dat het afdrukt. De bescherming is bestandsrechten en proceseigendom, niet onduidelijkheid. Een helper die een hardgecodeerde string echoot is een geheim met extra stappen.
Derde route: de eigen CLI van de portalclient
Zakelijke clients leveren meestal een commandoregel-startpunt dat zonder enig venster verbindt met een genoemde portal, en dat is de ondersteunde route. Op Linux biedt de GlobalProtect-client verbindings- en certificaatimportbewerkingen via zijn CLI, en portals die certificaatauthenticatie gebruiken hebben de importstap nodig voordat een geautomatiseerde verbinding kan werken. Geef er de voorkeur aan boven synthetische toetsaanslagen: je krijgt een echte exitstatus, geen afhankelijkheid van vensterfocus, en het overleeft een vergrendeld scherm.
Als de eerste verbinding nog steeds een mens nodig heeft om een certificaat te accepteren, is de automatisering niet af. Doe de import tijdens de installatie en leg hem vast als voorwaarde.
Wanneer de flow een pseudo-terminal nodig heeft
Een reeks die om een wachtwoord en daarna om een eenmalige code vraagt, heeft geen enkel bestand om te lezen. Een terminalstuurprogramma zoals Expect is het juiste gereedschap, omdat het om de beurt op elk patroon wacht, en het heeft het gestarte proces nodig voordat het überhaupt iets kan matchen.
Twee fouten domineren. Een script dat op een prompt wacht zonder de client te starten, wacht voor altijd, en Tcl is geen shell, dus shell-rekenwerk binnen een expect-blok wordt niet zo geëvalueerd als het leest. Laat de debugvlag aan staan terwijl je de patronen bouwt, en zet hem daarna uit.
Geheimen die lekken, en waar ze zich verstoppen
Alles wat als argument wordt doorgegeven is zichtbaar in de processenlijst, dus inloggegevens horen in een bestand of achter een helper, nooit op de commandoregel. Eenmalige codes worden naar ontwerp verbruikt en moeten voor elke poging worden gemaakt. Foutlogs dragen vaak de gebruikersnaam en soms meer, dus redigeer ze voordat je ze ergens heen stuurt, en houd het geheim buiten het profiel zelf, want een configuratiebestand met een ingebed wachtwoord wordt in tickets en repositories geplakt. Het account roteren betekent dan elke kopie najagen, en dat is precies de kosten die deze opzet vermijdt.
Auditeer de routes die je hebt gekozen en sluit ze vervolgens aan op het unit-bestand of de planner die de client echt gaat uitvoeren. De tunnel leeft precies zo lang als dat proces.