[Fixed]-Django, Security and Settings

45šŸ‘

It isnā€™t secure, anyone with access to your source control now has access to your database.

The two main methods of storing sensitive data are either with environment variables or via a json file


Excerpted from Settings ā€“ Hiding secret data using a JSON file. The original authors were Antoine Pinsard and fredley. Attribution details can be found on the contributor page. The source is licenced under CC BY-SA 3.0 and may be found in the Documentation archive. Reference topic ID: 942 and example ID: 8734.

Hiding secret data using a JSON file

When using a VCS such as Git or SVN, there are some secret data that must never be versioned (whether the repository is public or private).

Among those data, you find the SECRET_KEY setting and the database password.

A common practice to hide these settings from version control is to create a file secrets.json at the root of your project (thanks ā€œTwo Scoops of Djangoā€ for the idea):

{
    "SECRET_KEY": "N4HE:AMk:.Ader5354DR453TH8SHTQr",
    "DB_PASSWORD": "v3ry53cr3t"
}

And add it to your ignore list (.gitignore for git):

*.py[co]
*.sw[po]
*~
/secrets.json

Then add the following function to your settings module:

import json
import os
from django.core.exceptions import ImproperlyConfigured

with open(os.path.join(BASE_DIR, 'secrets.json')) as secrets_file:
    secrets = json.load(secrets_file)

def get_secret(setting, secrets=secrets):
    """Get secret setting or fail with ImproperlyConfigured"""
    try:
        return secrets[setting]
    except KeyError:
        raise ImproperlyConfigured("Set the {} setting".format(setting))

Then fill the settings this way:

SECRET_KEY = get_secret('SECRET_KEY')
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgres',
        'NAME': 'db_name',
        'USER': 'username',
        'PASSWORD': get_secret('DB_PASSWORD'),
    },
}

Credits: Two Scoops of Django: Best Practices for Django 1.8, by Daniel Roy Greenfeld and Audrey RoyGreenfeld. Copyright 2015 Two Scoops Press (ISBN 978-0981467344)


Excerpted from Settings ā€“ Using Environment variables to manage Settings across servers. The original authors were sudshekhar, ssice and NBajanca. Attribution details can be found on the contributor page. The source is licenced under CC BY-SA 3.0 and may be found in the Documentation archive. Reference topic ID: 942 and example ID: 3580.

Using Environment variables to manage Settings across servers

Using environment variables is a widely used way to setting an appā€™s config depending on it environment, as stated in The Twelve-Factor App.

As configurations are likely to change between deployment environments, this is a very interesting way to modify the configuration without having to dig in the appā€™s source code, as well as keeping secrets outside the application files and source code repository.

In Django, the main settings are located as settings.py in your projectā€™s folder. As it is a simple Python file, you can use Pythonā€™s os module from the standard library to access the environment (and even have appropriate defaults).

settings.py

import os

SECRET_KEY = os.environ.get('APP_SECRET_KEY', 'unsafe-secret-key')

DEBUG = os.environ.get('DJANGO_DEBUG', "True") == "True"

ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS', '').split()

DATABASES = {
    'default': {
        'ENGINE': os.environ.get('APP_DB_ENGINE', 'django.db.backends.sqlite3'),
        'NAME': os.environ.get('DB_NAME', 'db.sqlite'),    
        'USER': os.environ.get('DB_USER', ''),
        'PASSWORD': os.environ.get('DB_PASSWORD', ''),
        'HOST': os.environ.get('DB_HOST', None),
        'PORT': os.environ.get('DB_PORT', None),
        'CONN_MAX_AGE': 600,
    }
}

With Django you can change your database technology, so that you can use sqlite3 on your development machine (and that should be a sane default for committing to a source control system). Although this is possible it is not advisable:

Backing services, such as the appā€™s database, queueing system, or cache, is one area where dev/prod parity is important. (The Twelve-Factor App ā€“ Dev/prod parity)

šŸ‘¤Sayse

0šŸ‘

Would like to thank Sayse for the wonderful idea of using Environment variables. For those using Pycharm to connect to a mysql database, you need to create a ā€˜USERā€™ environment variable and call it using os.environ.get(ā€˜environment variableā€™, ā€) if you want to avoid storing the database password in the settings.py.

šŸ‘¤AwsAnurag

0šŸ‘

No, it isnā€™t secure .

you mustnā€™t upload those information to internet .

what I always do is :

  • Adding env file in the root directory .
    for example , if the project named MYPROJECT
    the dir for env file would be MYPROJECT/env

  • Adding env file to .gitignore file.

  • I use database url form , I found it more elegant , and less lines .
    to use it type :

    • pip install dj_database_url

    • Add this line to settings.py

      import dj_database_url

    • Then as simple and elegant as this type :
      DATABASES = { 'default': dj_database_url.config(default='postgres://user:password@localhost:5432/database_name'), }

  • Now , replace the url with a keyword ,and hide the url safely in env file , as :

    DATABASES = { 'default': dj_database_url.config(default=os.environ.get('DATABASE_URL')), }

    note : this way you typed os.environ.get() only once.

  • Go to env file and add :
    export DATABASE_URL='postgres://user:password@localhost:5432/database_name'

  • Donā€™t forget ! to let tell the terminal about those keywords! Type in terminal in project dir :
    source env

Good Luck .

Leave a comment