How to securley pass Password as Argument to a Pyt

2019-04-10 23:13发布

问题:

I have a python script that creates a linux user, given a username and password as arguments. I want to

  • call the script directly (e.g, ./pass.py)
  • call the script on the same VM from python (e.g, subprocess.Popen('/pass.py'))
  • call the script from a different VM from python over SSH. (e.g, subprocess.Popen(['ssh', 'host', 'pass.py'))

TL;DR Check the final code snippit and question

getpass works for the first case.

password = getpass.getpass()

However, if I run this over ssh, (ssh myhost /path/to/script.py username) I get the following output:

/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

Also, if I run this script in python using 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)

It seems to hang around subprocess.Popen and won't accept the password.

However, if I get rid of getpass.getpass() and replace it with raw_input, it works for cases 2 and 3. It doesn't echo the password.

I am therefore thinking of the following instead, which takes --script as an argument and asks for the password via 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()

This satisfies all three of my cases and does not appear to be echoing the password.

Am I correct in assuming that this is safe and the password won't get logged?

回答1:

You can add -t during SSH session, that will enforce an echo free terminal. On your client:

#!/usr/bin/env python

import subprocess

subprocess.call(["ssh", "-t", remote_host, "./add_user.py", "test_user"])

Then you should be able to use getpass on your server for a remote password. You can also call it directly or invoking through another 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()