Un script que inicia un cliente VPN de provedor queda colgado ata que expira o tempo, e o rexistro mostra que o cliente pide un código de verificación que ninguén escribiu. O contrasinal enviárase, así que a conclusión obvia é que o contrasinal é incorrecto. Non o é. A petición do código é unha conversa aparte nunha canle aparte, e o seu script nunca a abriu.

Faga as cinco comprobacións seguintes en orde. Detéñase na primeira que falle, porque cada paso posterior supón que os anteriores se cumpren.

Comprobación 1: o cliente le a entrada estándar, cando menos?

Próbeo antes de escribir calquera automatización: envíe un secreto ficticio ao cliente por un tubo e observe que ocorre. Se imprime a súa petición e despois espera, non está a ler o tubo.

Moitos clientes abren o dispositivo de terminal directamente, ou néganse a tomar un secreto dun fluxo que non é un terminal, para que un tubo extraviado non poida filtrar un contrasinal. OpenVPN é a excepción documentada, porque --auth-user-pass acepta unha ruta de ficheiro. Os clientes de provedor que piden un código dun só uso normalmente non teñen unha opción equivalente, e a súa petición espera un terminal que o seu script nunca forneceu.

Comprobación 2: ten o proceso fillo un terminal?

Un pty asigna un terminal ao fillo, o que converte as peticións en saída lexible que pode responder en orde.

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)

As cadeas de petición anteriores son ilustrativas; copie o texto exacto que imprime o seu cliente, incluídos maiúsculas e puntuación. Cada expectativa leva un tempo de espera, e un fillo pechado lanza unha excepción en lugar de devolver un estado, así que envolva a secuencia e trate o final de ficheiro como un fallo. Fíxese no que este bloque non fai: o fillo morre co script, porque un pty non é un mecanismo de desacoplamento e disown é unha orde interna da consola que non pode alcanzar un proceso que o seu script lanzou.

Comprobación 3: hai unha entrada non interactiva admitida?

O raspado de pantalla rompe coas actualizacións do cliente, así que busque primeiro unha opción documentada.

Revise a saída de axuda por se hai unha opción de token ou de código dun só uso, e comprobe se o servizo acepta o código engadido ao campo de contrasinal. Onde o cliente le un ficheiro de credenciais, déalle o ficheiro en lugar dunha petición:

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

A substitución de procesos dálle ao cliente unha ruta lexible en sistemas que ofrecen /dev/fd. O secreto segue sendo un secreto desde o punto de vista do cliente, así que mantéñao fóra dos rexistros, do historial da consola e das listas de procesos. Se o cliente rexeita /dev/fd ou abre a ruta de credenciais máis dunha vez, escriba un ficheiro real con permisos restritivos e bórreo no mesmo script.

Comprobación 4: sobrevivirá o túnel ao script?

Por defecto o túnel morre co seu pai, que é o contrario do que necesita un script de arranque.

disown -h só axuda cando lanzou o cliente como unha tarefa da consola, porque edita a táboa de tarefas desa consola e non pode alcanzar un proceso que o seu script lanzou mediante un pty. Un xestor de servizos é o mellor fogar para todo o que debe reconectarse sen supervisión, porque reinicia o cliente e rexistra por que morreu. En calquera caso, espere un código novo despois de cada reconexión: un token dun só uso consómese coa primeira autenticación correcta.

Observe que fai sudo coa secuencia. A petición de contrasinal de sudo non é a petición do VPN, e respondela co contrasinal do VPN é a forma máis común de que unha orde de expectativas por outra parte correcta siga fallando.

Comprobación 5: debería o código dunha persoa estar nun script?

Esta é a comprobación que a xente salta. Un token pertence a unha persoa, mentres que un túnel que debe erguerse segundo un horario pertence á máquina.

Se unha tarefa debe reconectarse sen supervisión, pregunte se un certificado de máquina ou unha conta de servizo poden substituír o inicio de sesión interactivo. Automatizar o código dun só uso de alguén converte un segundo factor nun secreto almacenado, o que é un cambio de política e non unha comodidade de scripting. Onde o servizo admite ambas as dúas, escolla a credencial que encaixa con como se executa realmente a tarefa. Escriba a resposta, porque a seguinte persoa preguntará por que o script garda un token.

Como se ve un script que funciona

O script imprime o paso ao que chegou, nunca o secreto, e sae cun código distinto de cero ante calquera expectativa fallida.

Próbeo rompéndoo a propósito: contrasinal incorrecto, grupo incorrecto, token caducado. Cada fallo debería deterse nun paso con nome en lugar de colgarse. Despois execúteo unha vez contra o servizo real e comprobe o túnel desde fóra do script, non desde dentro.

Artigos relacionados