¿Cómo pasar de forma segura la contraseña como argumento a un script de Python a través de SSH?

Tengo un script en Python que crea un usuario de Linux, dado un nombre de usuario y una contraseña como argumentos. quiero

  • llamar al script directamente (por ejemplo, ./pass.py )
  • llame al script en la misma máquina virtual desde python (por ejemplo, subprocess.Popen('/pass.py') )
  • llame al script desde una máquina virtual diferente desde python sobre SSH. (por ejemplo, subprocess.Popen(['ssh', 'host', 'pass.py') )

TL; DR Compruebe el código final y la pregunta

getpass funciona para el primer caso.

 password = getpass.getpass() 

Sin embargo, si ejecuto esto sobre ssh, ( ssh myhost /path/to/script.py username ) obtengo el siguiente resultado:

 /usr/lib64/python2.6/getpass.py:83: GetPassWarning: Can not control echo on the terminal. passwd = fallback_getpass(prompt, stream) Warning: Password input may be echoed. Password: password123 

Además, si ejecuto este script en Python usando subprocess :

 # Running from same host proc = subprocess.Popen(['./pass.py'], stdin=subprocess.PIPE) # Running from different host proc = subprocess.Popen(['ssh', 'myhost', '/path/to/pass.py', 'username'], stdin=subprocess.PIPE) 

Parece que cuelga alrededor de subprocess.Popen y no acepta la contraseña.

Sin embargo, si me deshago de getpass.getpass() y lo sustituyo por raw_input , funciona en los casos 2 y 3. No hace eco de la contraseña.

Por lo tanto, estoy pensando en lo siguiente, que toma --script como un argumento y solicita la contraseña a través de raw_input :

 import sys, getpass, argparse parser = argparse.ArgumentParser() parser.add_argument("username") parser.add_argument("-s", "--script", action="store_true") args = parser.parse_args() username = args.username if args.script: password = raw_input("Password: ") else: password = getpass.getpass() 

Esto satisface mis tres casos y no parece estar haciendo eco de la contraseña.

¿Estoy en lo cierto al suponer que esto es seguro y que la contraseña no se registrará?

Puede agregar -t durante la sesión de SSH, que impondrá un terminal sin eco. En su cliente:

 #!/usr/bin/env python import subprocess subprocess.call(["ssh", "-t", remote_host, "./add_user.py", "test_user"]) 

Entonces debería poder usar getpass en su servidor para una contraseña remota. También puedes llamarlo directamente o invocar a través de otro script:

 #!/usr/bin/env python import getpass, argparse parser = argparse.ArgumentParser() parser.add_argument("username") args = parser.parse_args() username = args.username password = getpass.getpass()