Python + SSH Password auth (sem bibliotecas externas ou chaves públicas / privadas)?
Então, estou ciente de que você pode usarPexpect
para resolver o problema, mas eu gostaria de não confiar em bibliotecas adicionais para resolver o problema além daquelas fornecidas com o Python3.
Eu também estou ciente de que a geração de chaves públicas e sua permissão no host remoto é ideal, mas é mais ou menos o que eu pretendo usar este script para (configurar as chaves no lugar certo, etc.).
Isto é tanto quanto eu comecei em "meu próprio" com um monte de ajuda da comunidade SO. Eu estou meio preso verificando se o pseudo terminal bifurcado filho é feito executando o que é suposto ou não. Significado eu posso dizer se o SSH é feito em execução ou não, porque ele vai viver por tanto tempo quanto orun()
função está operando.
(minhapid_exists
retornaráTrue
desde que esteja dentro da operação run (). E se eu sairrun()
para rapidamente a sessão SSH não terá tempo suficiente para fazer o que é suposto fazer)
#!/usr/bin/python
import pty, sys
from subprocess import Popen, PIPE, STDOUT
from time import sleep
from os.path import expanduser, abspath
from os import walk, setsid, fork, waitpid, execv, read, write, kill
def pid_exists(pid):
"""Check whether pid exists in the current process table."""
if pid < 0:
return False
try:
kill(pid, 0)
except (OSError, e):
return e.errno == errno.EPERMRM
else:
return True
class ssh():
def __init__(self, host, execute='echo "done" > /root/testing.txt', user='root', password=b'SuperPassword'):
self.exec = execute
self.host = host
self.user = user
self.password = password
self.run()
def run(self):
command = [
'/usr/bin/ssh',
self.user+'@'+self.host,
'-o', 'NumberOfPasswordPrompts=1',
self.exec,
]
# PID = 0 for child, and the PID of the child for the parent
pid, child_fd = pty.fork()
if not pid: # Child process
# Replace child process with our SSH process
execv(command[0], command)
while True:
output = read(child_fd, 1024).strip()
print(output)
lower = output.lower()
# Write the password
if b'password:' in lower:
write(child_fd, self.password + b'\n')
break
elif 'are you sure you want to continue connecting' in lower:
# Adding key to known_hosts
write(child_fd, b'yes\n')
elif 'company privacy warning' in lower:
pass # This is an understood message
else:
print('Error:',output)
sleep(5)
print(pid_exists(pid))
ssh('10.10.10.1')
Não consigo encontrar muita (ou nenhuma) informação sobre como obter o processo de execução do pseudo-pseudo-terminal que o Python abre e canaliza para mim. Posso ou devo envolver o subprocesso como explicado aqui:https://stackoverflow.com/a/12235442/929999 Ou existe outra maneira?