Django settings are a great tool to set up configurations for each deploy, from development to production. Some parameters are more sensitive and must be kept out of version control. These usually include Django’s SECRET_KEY, database credentials, or server-specific values.

A way to manage this information is necessary as secrets need to be stored securely and be readily available to team members. Well-known Django patterns help you separate logic and configuration, so sensitive information doesn’t end up committed with your code by mistake. However, these practices alone won’t solve the problems that emerge from proper handling of these secrets, like encrypting the files and distribution of encryption keys to your team.

We want to complete the picture by introducing Bunkr, a platform-agnostic solution for secret management.

Pattern 1: Multiple setting files

A typical Python practice is to use a local_settings.py, excluded from version control, which can import a base settings.py. The “Two-Scoops of Django” book took it one step further and suggested to create a settings folder with one file per stage: development, staging, tests, and production.

# app/settings/production.py from .base import * DEBUG = False # SECURITY WARNING: keep the secret key used in production secret!

SECRET_KEY = '4e&6aw+(5&cg^_!05r(&7_#dghg_pdgopq(yk)xa^bog7j)^*j' DATABASES = {

'default': {

'ENGINE': 'django.db.backends.mysql',

'NAME': 'DB_NAME',

'USER': 'DB_USER',

'PASSWORD': 'DB_PASSWORD',

'HOST': '10.0.1.130', # Or an IP Address that your DB is hosted on

'PORT': '3306',

}

}

You can run Django specifying your production settings:

$ python manage.py runserver --settings=app.settings.production

Before we can commit this file, we must encrypt it as it contains production credentials which may lead to leakage. Typical tools like git-crypt use symmetric encryption, although they may not adapt properly to development scenarios or scale well when sharing the encryption key.

Uploading the file to Bunkr gives us storage, security, and streamlined sharing across our team.

$ bunkr new-file-secret django-production-settings production.py

As part of our deployment, we now copy this file from our local Bunkr to the remote server. From a shell script we could do:

$ bunkr access django-production-settings text | ssh user@remote 'cat > app/settings/production.py'

Pattern 2: Keeping separate configuration files

The pro of the previous method is that you can work directly with Python types, but the con is that what should be configuration usually ends up growing into custom logic, making it more prone to bugs.

We can further separate our code and configuration by reading the configuration values from a secrets file formatted as JSON, YAML or even XML. The file can be sourced from Bunkr as we did in the previous pattern.

{

"SECRET_KEY": "4e&6aw+(5&cg^_!05r(&7_#dghg_pdgopq(yk)xa^bog7j)^*j",

"DB_PASS": "DB_PASSWORD",

"DB_USER": "DB_USER"

}

To load this file within your code, we will use a snippet from https://medium.com/@ayarshabeer/django-best-practice-settings-file-for-multiple-environments-6d71c6966ee2:

import os

import json

from django.core.exceptions import ImproperlyConfigured with open(os.environ.get('MYSITE_CONFIG')) as f:

configs = json.loads(f.read()) def get_file_variable(setting, configs=configs):

try:

val = configs[setting]

if val == 'True':

val = True

elif val == 'False':

val = False

return val

except KeyError:

error_msg = "ImproperlyConfigured: Set {0} environment variable".format(setting)

raise ImproperlyConfigured(error_msg) SECRET_KEY = get_file_variable("SECRET_KEY")

Pattern 3: Environment variables

An alternative to configuration files for your Django settings is to use env variables. This method was popularized by “The Twelve Factor App”. The advantage of this method is that some deployments are significantly simplified.

Some Platforms as a Service like Heroku do not allow to upload individual files outside your repository but provide convenient ways to handle the Environment within the machine. It is very easy to connect Bunkr and Heroku. Django can make use of the environment variables like this (from https://medium.com/django-musings/what-to-do-with-passwords-and-secrets-16c2409bfdd8):

import os

from django.core.exceptions import ImproperlyConfigured def get_env_variable(name):

“””Gets the environment variable or throws ImproperlyConfigured

exception

:rtype: object

“””

try:

return os.environ[name]

except KeyError:

raise ImproperlyConfigured(‘Environment variable “%s” not found.’ % name) SECRET_KEY = get_env_variable(’SECRET_KEY’)

Wrapping up

Bunkr can help you manage the secret information you need to store for your Django Application. It is vital to keep configuration and code separate so that the later can be version controlled. Handling configuration has always been painful and required a conglomerate of tools, due to the sensitive nature of some information, often tying you to a specific way of doing things. Bunkr makes it effortless to manage your secrets for different deploys and across your team, so you can keep configuring Django your way.