Python script with password security?

Hello,

I'm writing a Python script that will connect to a postgresql database using the psycopg2 library.  I'm getting around it pretty well but one concern I have is that when connecting to the database host, I have to hard code the username and password into the connection statement.  I would prefer not to do this and would like to somehow refer to an external file for this information and import that user account info then construct the connection string.  That way at least the username/password combo wouldn't be directly visible when looking at the Python code.  Any help or alternative ideas would be very much appreciated.

Example of the psycopg2 connection statement:
import psycopg2

conn_string = "dbname='mydatabase' port='1234' user='joe_shmoe' password = 'joespassword' host='hostaddress.com'"
conn = psycopg2.connect(conn_string)

Open in new window


Thanks,
Glen
jisoo411Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Walter RitzelSenior Software EngineerCommented:
I'll start working on something similar. I'll have a script that will get one file with the following text:
dbhost = xxx.xxx.xxx
dbuser = xxxxx
dbpass = xxxxx

and it will encrypt the file with the simplecrypt module:
from simplecrypt import encrypt, decrypt
ciphertext = encrypt('password', plaintext)

Open in new window


Then I'll create a module that will load the file and decrypt:
from simplecrypt import encrypt, decrypt
plaintext = decrypt('password', ciphertext)

Open in new window


Module is here:
https://pypi.python.org/pypi/simple-crypt
Kyle HamiltonData ScientistCommented:
you could also store your keys/passwords as environment variables outside your application directory.

then use the os module to access the env vars your py script

import os
print os.environ['HOME']

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jisoo411Author Commented:
Sorry for the late reply.  These both look like good potential solutions for me.  Here's some extra context as well, I'm developing this Python script on a Windows machine but it will run on a Linux machine.  The main purpose of this script is to pull CSV files into a local directory then load them into the postgresql database.  

With the environment variable method, will the os module work seamlessly between Windows vs Linux?  For instance, if I create the following environment variables on both Windows 10 and Linux:

UserName = Joe
Password = JoePassword
TempDir = C:\Temp (Linux would be something like '/usr/tmp/processing')

Would the os module refer to them in exactly the same way using the os.environ function call?  I.e. os.environ['TempDir'] would output C:\Temp when run on Windows and /usr/tmp/processing when run on Linux?

Thanks,
Glen
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

jisoo411Author Commented:
Looking at the os reference, it looks like maybe the getenv function would do this...

import os
print os.getenv('TempDir')

That gives me C:\Temp on Windows 10.  I'm guessing it will work in Linux since the reference says it works on most flavors of unix.  One follow up question though, setting an environment variable in Linux is typically temporary for the session.  Where would I set this to make it system-wide and permanent?  

Thanks,
Glen
Kyle HamiltonData ScientistCommented:
If you wanted to set the environment variable in linux permanently you could add it to the .bashrc file, or for a given user, add it to .bash_profile:

export TempDir=/usr/tmp/processing

Open in new window

(notice no quotes or spaces)
Kyle HamiltonData ScientistCommented:
here's another way:

if you wanted to keep those variables in their own file, you could make a .passwords file, with the export lines, then in your .bash_profile:

source path/to/.passwords

Open in new window


remember that every time you add an environment variable to a file, you have to either start a new shell, or source the file in which the variables are defined.
jisoo411Author Commented:
I'll be looking to set this environment variable permanently for all users.  It'll be a common variable utilized by all Python scripts being dropped onto the server and executed via cron or some other job scheduler.
Kyle HamiltonData ScientistCommented:
The I would put it in a .passwords file that will be dropped on whatever server you need in some predetermined directory.


in .passwords
export NAME="name"
export PWD="password"
export DIR=/your/temp/dir/

Open in new window


In your script which gets triggered by cron, add the source line:

source /path/to/.passwords

Open in new window


and in your python script:

import os
password = os.getenv('PWD')
username = os.getenv('NAME')
tempdir = os.getenv('DIR')

Open in new window

jisoo411Author Commented:
That would work if I developed on a linux machine, unfortunately my workstation is Windows while the environment I deploy my code to is linux.  It sounds like simply adding the export statements to the .bashrc file would suffice and would eliminate any need to that source line in my python script, is that correct?
Kyle HamiltonData ScientistCommented:
i assumed your cron would run a bash shell script. you would put the source line in the shell script.

if you put the variables in .bashrc, you will need to do that for every server you deploy on.

you could still automate it with a script that appends to .bashrc.

it's a half a dozen, or six thing. (i can never remember that expression right :)

many ways to skin a cat...
jisoo411Author Commented:
Very true.  Thankfully we're only dealing with 1 or 2 linux servers for the long term so we're good there.  I just tried to put in the export statements, I restarted bash and did a "printenv" to verify that they got set (which they did).  But after I closed my putty session and started a new one, the exports disappeared.  Somehow they became session-specific and not permanent.  I performed the following steps:

1.  vi ~/.bashrc

2.  Added line: export temp_dir="/home/ubuntu/tmp/"

3. exec bash -l

Open in new window


Is there something I'm missing?
jisoo411Author Commented:
Searching around google, I see a file called "/etc/profile" being mentioned.  When I look at the file on my linux box I see that it's executing ". /etc/bash.bashrc" as well as "/etc/profile.d".  Should I be putting these export statements in "/etc/profile" instead?
jisoo411Author Commented:
Nevermind, "/etc/profile" is apparently a root directory and I don't have permissions to modify that :/
jisoo411Author Commented:
Looks like it's the .profile file in the home directory that keeps the settings permanent.  I set up the temp_dir export statement in there and closed out my session window then logged back in and the printenv command still shows the variable.  Hopefully that's it.
Kyle HamiltonData ScientistCommented:
glad you got it working.

typically the file is in the home directory, called .bash_profile

cheers.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Python

From novice to tech pro — start learning today.