securely passing a password to subprocess.Popen via environment - python

I would like to securely ask a password to a user and then pass it to subprocess.Popen to run a command that requires it.
I have seen this question and that one, but I wonder if I can securely pass the password via the subprocess environment like that:
import subprocess, os
user_password = input("what is you password?")
my_env = os.environ.copy()
my_env["userpass"] = user_password
my_command = "python --version"
subprocess.Popen(my_command, env=my_env)
Will the password be flushed once the python script is closed ? I have look at the subprocess documentation but it's not explained.
When I add this line print(os.environ['userpass']) at the end of my code to print the OS environment, I can retrieve the user password. Do it means that the password can be access by the other running processes ?
Edit: I can't pipe the password as the command I use doesn't read its password from standard input

Related

How to automate password entry for Azure?

I want to automatically login an Azure system to access the virtual machine. I run the following code:
process_1 = subprocess.call(key.SSH_KEY + ' | ' + key.PASSKEY, shell = True) # Login to virtual machine
and receive the following:
/bin/sh: key.PASSKEY: command not found
azureuser#xx.xx.1x.1xx's password:
It believes the key.PASSKEY is another command, when it is the input for the azureuser#xx.xx.1x.1xx's password: part. How do I make sure that the key.PASSKEY is entered as the password automatically when this subprocess command is run?
The answer was found using the following video: https://www.youtube.com/watch?v=8QfD8V_-7ok
I did:
ch = pexpect.spawn(key.SSH_KEY)
ch.logfile = sys.stdout.buffer
ch.expect("azureuser#xx.xx.1x.1xx's password:")
ch.sendline(key.PASSKEY)
ch.expect("azureuser#vm")
ch.sendline('ls')

pass password to a Python script on prompt

How can I pass a password to my python script when it prompts for a password. I do not want the user to enter the password when it prompts. It should be passed directly from the script.
subprocess.run(['ansible-vault', 'decrypt', 'main.yml', 'linux.yml','--ask-vault-pass'])
While running the script it prompts for the password. I want the password to be passed from script only not by the user or passing a password file.
Is there a way to pass the password here? I have other ansible vault option like vault-password etc but that doesn't serve my purpose.
Instead of using the cmdline ansible-vault, you can use the Python package - ansible-vault which will allow you to hardcode the password inside the script itself:
from ansible_vault import Vault
vault = Vault('password')
main_data = vault.load(open('main.yml').read())
linux_data = vault.load(open('linux.yaml').read())
As you are hardcoding the password inside the code, ensure you don't commit this code anywhere or send it to anyone, it's a serious security risk.

python-gerrit-api alternative authentication

Is there a way not to hardcode the password in the python script while using python-gerrit-api module ?
from gerrit import GerritClient
gerrit = GerritClient(base_url="https://yourgerrit", username='******', password='xxxxx')
There are a few possible solutions for this:
Solution 1:
Use the python argparse module to take the password as input from the CLI using the command-line arguments. Set the $GERRIT_PASSWORD environment variable, and use that in the password argument.
./script.py --username=$GERRIT_USERNAME --password=$GERRIT_PASSWORD
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--username', help='Username')
parser.add_argument('--password', help='Password')
args = parser.parse_args()
username = args.username
password = args.password
from gerrit import GerritClient
gerrit = GerritClient(base_url="https://yourgerrit", username=username, password=password)
Note: You can achieve a similar state by directly getting the value of the environment in your code, using os.environ, instead of using the argparse module. However, the recommended way would be to give the input using arguments.
Solution 2:
Use the python getpass module, to take the password as input from the user interactively:
import getpass
username = input("Username: ")
password = getpass.getpass(prompt="Password: ")
from gerrit import GerritClient
gerrit = GerritClient(base_url="https://yourgerrit", username=username, password=password)
Both the solutions mentioned above are derived from the fact that accessing Gerrit over HTTPS either requires the password to be input in the CLI command or requires the user to enter it interactively.
(i)
git clone "https://$USERNAME:$PASSWORD#$GERRIT_HOST/$PROJECT"
(ii)
git clone "https://$USERNAME#$GERRIT_HOST/$PROJECT"
Password for 'https://$USERNAME#$PROJECT': <Enter the password>

How to restrict permission to run script?

I would like to restrict ability to run my Python 3 script to certain host and users on Linux. Is there any Python 3.x build in function or library which would allow me to do this relatively easy please?
Not exactly a Python answer, but a Linux one - you may add all users who can run a script to some group:
groupadd allowed-users
usermod -a -G allowed-users some-user
Then change group of the script and restrict read access to it only for group (if user can't read a script it can't run it).
chown allowed-users script.py
chmod 640 script.py
I'm sure there is a better way of doing that but below is my first attempt.
#!/usr/bin/python3
import getpass
import socket
hostname = socket.gethostname()
username = getpass.getuser()
allowedusers = 'user1'
allowedhosts = 'host1'
if hostname in allowedhosts:
print('hostname allowed')
if username in allowedusers:
print('user allowed')
else:
print('username not allowed')
exit()
else:
print('hostname not allowed')
exit()
print('script will continue to run as hostname and user are allowed')

fabric task error when prompting for password

I'm having an error I can't seem to get past. I have a simple fabric task that must be run as a different user on the remote system, e.g:
def update():
env.user = 'otheruser'
#~ env.password = 'otherpass' # this works, but I don't want it here.
with cd(env.sitefolder):
run('hg pull -u')
If I run this with env.password hardcoded it works. If I use fab -p otherpass update it works too. If I omit it the docs say I will get prompted. This is true, but it doesn't work. Every time after entering the password I get this error:
> fab dev update
[darkstar] Executing task 'update'
[darkstar] run: hg pull -u
[darkstar] Login password:
ERROR:paramiko.transport:Exception: Error reading SSH protocol banner
...
Fatal error: Error reading SSH protocol banner
Aborting.
Using fabric 1.2.2 on Ubuntu Natty. I also tried the env.no_keys option but it didn't change anything. Can anyone help?
Prompt for the password yourself!
def update():
env.user = 'otheruser'
env.password = getpass.getpass('Enter password: ')
with cd(env.sitefolder):
run('hg pull -u')
getpass is part of the standard library, it's just a raw_input that doesn't echo what you type
This can also happen if target is out of memory/disk space. Restarting and/or solving memory/disk space problems can solve this.

Categories