How to securely store passwords used in backend code

243 views
Skip to first unread message

Fenrir Sivar

unread,
Dec 8, 2020, 9:40:29 AM12/8/20
to django...@googlegroups.com
I inherited a django app that calls private APIs in a view to fetch some data. The credentials or api keys are currently hardcoded in the source, making it difficult to share.
What is the preferred way to store these kind of keys in a secure way only accessible to the django server?

Kasper Laudrup

unread,
Dec 8, 2020, 9:49:25 AM12/8/20
to django...@googlegroups.com
Hi Fenrir,
I don't know if it's the preferred way, but one way is to read them from
environment variables, that's what I do at least.

In production I set them in the .service file I use to launch gunicorn
overriding the defaults that will be used for development/test.

Let me know if you need some details on how I've done that, but maybe
someone else has some better ideas.

Kind regards,

Kasper Laudrup

Pankaj Jangid

unread,
Dec 9, 2020, 9:18:55 AM12/9/20
to Fenrir Sivar, django...@googlegroups.com
As Kasper suggests, I also use environment variables in development
environment. But a few more things add up to convenience.

1. I use ‘direnv’ for managing per directory environment variables. As I
enter a perticular directory (on terminal), it echos the newly set
environment variables.

2. It might be overkill but I use Docker on my development machine. And
I use the same environment variables in my docker-compose.yml. This
is also useful in production setup where you are deploying in Docker.

David Nugent

unread,
Dec 14, 2020, 11:05:51 PM12/14/20
to django...@googlegroups.com, Fenrir Sivar, Pankaj Jangid

On 10 December 2020 at 01:18:16, Pankaj Jangid (pan...@codeisgreat.org) wrote:

Fenrir Sivar <fenrir...@gmail.com> writes: 

> I inherited a django app that calls private APIs in a view to fetch some 
> data. The credentials or api keys are currently hardcoded in the source, 
> making it difficult to share. 
> What is the preferred way to store these kind of keys in a secure way only 
> accessible to the django server? 

As Kasper suggests, I also use environment variables in development 
environment. But a few more things add up to convenience. 

Not only convenience, but a very good idea. First and foremost, keep secrets out of configuration even gitignore'd ones, with .env files being the exception.

The environment is not a perfect place to store these but they are better then placing them in code or configuration.

For more info and a very tried and tested approach, check out https://12factor.net/


1. I use ‘direnv’ for managing per directory environment variables. As I 
enter a perticular directory (on terminal), it echos the newly set 
environment variables. 

Seconded ... and thirded!

If you use .env files you can even suck these in automatically, set your virtualenv and any configuration information in your .envrc. It is a really good approach especially so i you work on multiple projects and don't want to clutter your .*profile or Windows global env.


2. It might be overkill but I use Docker on my development machine. And 
I use the same environment variables in my docker-compose.yml. This 
is also useful in production setup where you are deploying in Docker. 


I would argue that this is definitely NOT an overkill unless you're entirely unfamiliar with container technology when it would become another burden in the path to understanding.

Running your code in a container when it is to be deployed in production in a container is very important to avoid pitfalls such as local dependencies of all sorts. "it works here" but fails in production is definitely something you want to avoid.  You can mount your development environment locally and run the server within the container and all is good, although this does raise some interesting challenges if you want to debug the server...



Peter of the Norse

unread,
Jan 10, 2021, 9:15:09 PM1/10/21
to django...@googlegroups.com
I use multiple settings.py files to do this.  Specifically, in my main one, I have what I consider the only acceptable instance of import *.

import os
if (os.getenv('PRODUCTION')):
    from .prod_settings import *
else:
    from .dev_settings import *

While dev_settings.py is in my repo, prod_settings.py is not. 

If there are settings that are used in different systems/programs, https://pypi.org/project/python-dotenv/ looks like the best choice.  Like Pankaj Jangid using Docker, and wants the same values in two places.

-- 
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAPvfA9A1zjp76qNf%2BN0QgacHuSzT0LQ246hFHoJCb7Bj1m1tYg%40mail.gmail.com.

David Nugent

unread,
Jan 10, 2021, 9:41:04 PM1/10/21
to django...@googlegroups.com, Peter of the Norse
On 11 January 2021 at 13:14:59, Peter of the Norse (rahm...@gmail.com) wrote:
I use multiple settings.py files to do this.  Specifically, in my main one, I have what I consider the only acceptable instance of import *.


Slightly off-topic (subject changed to reflect that), but there are other exceptions as well that conform to a similar pattern.

For example, refactoring models.py to a package requires adding an import into __init__.py (unless you want to change all dependent code and often needlessly cluttering import statements). Importing `*` instead if individual submodules into `__init__.py` is often the way to go and leads to less changes when you add models in new modules.

PEP8 doesn't explicitly disallow this, but only strongly recommends against it, but the concern is very project specific. I just use it in django for this use case but rarely otherwise.


Regards,

/d

Reply all
Reply to author
Forward
0 new messages