9

I just started on a Django project and in the settings.py file of the project, the database section looks like this:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'blogengine',                 # Or path to database file if using sqlite3.
        # The following settings are not used with sqlite3:
        'USER': 'blogadmin',
        'PASSWORD': 'blog@123',
        'HOST': 'localhost',                 # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
        'PORT': '3306',                      # Set to empty string for default.
    }
}

Is there any way in which I don't have to enter the password as plaintext but maybe enter it in some encrypted form?

Josh Correia
  • 3,807
  • 3
  • 33
  • 50
rahuL
  • 3,330
  • 11
  • 54
  • 79

2 Answers2

11

Another thing you could do is not to store your password/token in your settings.py, it is a bad practice for security, instead of that, you should create an environment variable in the user that runs your app let's say:

export MYSQL_PASSWORD=1234

And read it from your django app as follows

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'blogengine',                 # Or path to database file if using sqlite3.
        # The following settings are not used with sqlite3:
        'USER': 'blogadmin',
        'PASSWORD': os.getenv('MYSQL_PASSWORD'),
        'HOST': 'localhost',                 # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
        'PORT': '3306',                      # Set to empty string for default.
    }
}

You should do this for all your "sensible data" like EMAIL_HOST_PASSWORD, AWS tokens and secrets and that kind of stuff, this way you separate the configuration from the environment and you don't have to change those parameters in your testing server or local environment, you just have to ensure that your environment variables are the same but points to the correct location according to your environment.

iferminm
  • 2,019
  • 19
  • 34
  • 3
    ...er. This seems like a bad idea. Wherever that environment variable is being exported, it's still in a file somewhere, so it's still in cleartext on-disk, and you don't gain anything over just having it in the settings file - except now you have an additional file you have to keep secure. Environment variables aren't any more private than world-unreadable files, the application user can always just cat /proc/(pid)/environ and see the values. – AdamKG Aug 18 '13 at 13:57
  • 2
    The idea is to restrict access, so, just that user can see the variable, i normally follow this http://12factor.net/, and environment variables are the way i found to have several developers working on the same app and their local environments and not having to change a lot of parameters when deploying to my testing server or my production server. – iferminm Aug 18 '13 at 14:08
  • 2
    our settings.py is commited in our git, so devs can run it "out of the box" while at the same time only the server-admin knows the password to the actual server I think this is the way to go and should way more upvotes – wotanii Apr 19 '17 at 12:20
10

There is no point in trying to protect that password.

Any token in that file that can be used to access the database can be used by anyone else to access the database. That's how shared secret security works. Replace the password by a randomly generated token, and you still have to communicate that token to settings.py, for example.

Your better bet is to restrict what computers can connect to your MySQL database using that username and password, adding an additional layer of security. Oh, and making sure no one can access settings.py by securing your webserver and source control systems properly.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343