secret key from file...

284 views
Skip to first unread message

Matt Harasymczuk

unread,
Mar 21, 2011, 10:59:10 AM3/21/11
to Django developers
I had an idea.
From time to time I find on the Internet a django app source code with
secret_key shown.

how about creating an secret.key file next to settings.py in main
project module, which should be added by developer
to .gitignore, .hgignore or equivalent

in settings we read key from file to SECRET_KEY and we go as usual.

SECRET_KEY = open("secret.key").read()

then, a django-admin startproject should give a warning "add
secret.key to your version management system ignore file", it should
automatically put generate secret phrase to this file

what about downloading an app from the Internet

manage.py createsecret
will ask if we want to generate new secret file
if file exists, and overwrite an existing one

dajngo has to be pythonic, therefore
cat secretkey.py

SECRET_KEY = "as it goes usual"

and in settings file

from .secretkey import *


What do you think?
IMHO both this ways are good


--
Matt Harasymczuk
http://www.matt.harasymczuk.pl

Kristaps Kūlis

unread,
Mar 21, 2011, 12:07:14 PM3/21/11
to django-d...@googlegroups.com
"real" config should not be in version control system, only reference
config should be stored in version control.

Consider database credentials - they should not be publicly available
/ downloadable from internet and they fall in same category -
sensitive information in settings.py .
Memcache credentials - in many cases memcache is unprotected .

I think docs should be updated to reflect sensitive settings.py
variables, which are confidential and provide "best practices" way
({local|secret}_settings.py ?) for deployment :). Perhaps manage.py
command to generate adequate strenght / randomness secret would be
beneficial .

Kristaps Kūlis

> --
> You received this message because you are subscribed to the Google Groups "Django developers" group.
> To post to this group, send email to django-d...@googlegroups.com.
> To unsubscribe from this group, send email to django-develop...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
>
>

Matt Robenolt

unread,
Mar 21, 2011, 12:57:46 PM3/21/11
to django-d...@googlegroups.com
What we use is a settings.cfg, which is an ini file for global configurations. Database settings, etc. We need to share these settings across different languages and parts of our application.

You can set up your ini file as such:

[secret]
key=abcdefghijklmnopqrstuvwxyz0123456789


ini files are easy to parse with the ConfigParser in Python. You can simply parse it in your settings.py:

import ConfigParser
config = ConfigParser.ConfigParser()
config.readfp(open('../settings.cfg'))

SECRET_KEY = config.get('secret', 'key')


Matt Harasymczuk

unread,
Mar 21, 2011, 1:07:56 PM3/21/11
to Django developers
Thats right,
there should be a secret_settings.py file with db credentials and
secret_key
also a warning that it should not be added to version control


--
Matt Harasymczuk
http://www.matt.harasymczuk.pl

Łukasz Rekucki

unread,
Mar 21, 2011, 1:29:23 PM3/21/11
to django-d...@googlegroups.com
On 21 March 2011 18:07, Matt Harasymczuk <ma...@harasymczuk.pl> wrote:
> Thats right,
> there should be a secret_settings.py file with db credentials and
> secret_key
> also a warning that it should not be added to version control

settings.py already has a warning:

# Make this unique, and don't share it with anybody.

I usually keep the generated default in VCS, so that anyone other team
members don't have to put it in their localsettings.py. Staging and
production servers have their own settings anyway, so it's not really
a problem.

I'm not sure what exactly are you proposing. Do you want to change the
default project template or the docs ?

--
Łukasz Rekucki

Matthew Roy

unread,
Mar 21, 2011, 2:01:58 PM3/21/11
to django-d...@googlegroups.com, Matt Harasymczuk
I don't think settings.py needs to be any more complicated by default. Personally, I do keep my db passwords in the settings file under version control. It seems pretty clear that it shouldn't be under public revision control. I also do (nearly) exactly what you describe to load the secret key from the filesystem.

For the base installation the compromise of the settings.py actually isn't all that bad. MySQL defaults to listening only on localhost and the database user is mapped to localhost if you follow the tutorial. Memcache is a non-default addition, and IIRC also defaults to localhost. If I understand how it works the compromise of the SECRET_KEY alone doesn't put you in serious hot water unless the attacker can also intercept traffic. This leads me to the conclusion that a novice users really doesn't need to worry about heavily securing the values in settings.py until the are ready to grow their setup.

That said, an automated tool to write a secret key to the file system and update settings.py to load it could make sense as a way to help users bridge the gap between the simple and moderately complex deployments.

Matthew


Kristaps Kūlis

unread,
Mar 22, 2011, 8:44:08 AM3/22/11
to django-d...@googlegroups.com
I personally would greatly appreciate update in docs to show "best
way" to handle per enviroment settings / sensitive settings, as now
there is many ways :)
Consider when one has his local development enviroment with locmem
cache and sqlite3 db, and staging server with MySQL / memcache and
production cluster with MySQL (different credentials) and memcache
cluster. In settings.py most deployment specific stuff is left blank
and on deployment {staging/production}_settings.py is created with
from settings import * and then overriding per env settings :).
Actually it took me far too much googling to find "how" and "what" to
do, at least I believe that such stuff should be put in docs to make
django more sysadmin friendly.

Kristaps Kūlis

Luke Plant

unread,
Mar 22, 2011, 10:04:59 AM3/22/11
to django-d...@googlegroups.com
On 22/03/11 12:44, Kristaps Kūlis wrote:
> I personally would greatly appreciate update in docs to show "best
> way" to handle per enviroment settings / sensitive settings, as now
> there is many ways :)
> Consider when one has his local development enviroment with locmem
> cache and sqlite3 db, and staging server with MySQL / memcache and
> production cluster with MySQL (different credentials) and memcache
> cluster. In settings.py most deployment specific stuff is left blank
> and on deployment {staging/production}_settings.py is created with
> from settings import * and then overriding per env settings :).
> Actually it took me far too much googling to find "how" and "what" to
> do, at least I believe that such stuff should be put in docs to make
> django more sysadmin friendly.

One problem is that there are simply so many options, there is no 'best'
way. Every assumption made in this thread holds only for some
situations. And the solutions are not at all Django specific - every web
site, with any technology, has this issue i.e. where to put sensitive
configuration information.

Django's settings file gives you enough power to put this information
anywhere you like, and our documentation already points out that you can
use any Python to set the values of settings. We could make this a bit
more explicit to point that this means you can store settings not only
in other Python files, but anywhere.

Luke

--
"I am going to let you move around more, just to break up the
mahogany." (True Quotes From Induhviduals, Scott Adams)

Luke Plant || http://lukeplant.me.uk/

Paul McMillan

unread,
Mar 22, 2011, 5:42:19 PM3/22/11
to django-d...@googlegroups.com
I would be in support of a manage.py command to change the secret key,
just as a convenience. I'd be happy to implement it.

Matthew Roy said:
> If I understand
> how it works the compromise of the SECRET_KEY alone doesn't put you in
> serious hot water unless the attacker can also intercept traffic.

The SECRET_KEY is secret for a number of very good reasons, and
compromise of it is quite likely to lead to compromise of your
application if the attacker is sufficiently motivated.

-Paul

Ian Kelly

unread,
Mar 22, 2011, 5:51:05 PM3/22/11
to django-d...@googlegroups.com
On Tue, Mar 22, 2011 at 6:44 AM, Kristaps Kūlis
<kristap...@gmail.com> wrote:
>  I personally would greatly appreciate update in docs to show "best
> way" to handle per enviroment settings / sensitive settings, as now
> there is many ways :)
>  Consider when one has his local development enviroment with locmem
> cache and sqlite3 db, and staging server with MySQL / memcache and
> production cluster with MySQL (different credentials) and memcache
> cluster. In settings.py most deployment  specific stuff is left blank
> and on deployment {staging/production}_settings.py is created with
> from settings import * and then overriding per env settings :).
>  Actually it took me far too much googling to find "how" and "what" to
> do, at least I believe that such stuff should be put in docs to make
> django more sysadmin friendly.

I don't know what the best way is, but I will share what we do. In
addition to the regular settings.py we have site_settings.py (which is
not under version control) in the same directory. Then at the end of
settings.py we add this simple code:

# Run a separate python file not in version control for database
# settings and other sensitive information.
from os.path import dirname, join
execfile(join(dirname(__file__), 'site_settings.py'))

Cheers,
Ian

Matt Robenolt

unread,
Mar 22, 2011, 6:49:52 PM3/22/11
to django-d...@googlegroups.com
Why not just do an import for your custom settings?

try:
from site_settings import *
except ImportError:
pass

Ian Kelly

unread,
Mar 22, 2011, 7:05:42 PM3/22/11
to django-d...@googlegroups.com
On Tue, Mar 22, 2011 at 4:49 PM, Matt Robenolt
<youdont...@gmail.com> wrote:
> Why not just do an import for your custom settings?
>
> try:
>        from site_settings import *
> except ImportError:
>        pass

No particularly compelling reason that I know of, the import machinery
is just unnecessary in this case. The site_settings.py is viewed as
an extension of the settings.py, so it doesn't need to be loaded as a
module in its own right. And for the same reason we know exactly
where we expect the file to be, so there's no need to consult
sys.path.

I suppose it just comes down to a matter of taste.

Cheers,
Ian

Matt Robenolt

unread,
Mar 22, 2011, 7:09:22 PM3/22/11
to django-d...@googlegroups.com
That's just interesting. I've never seen the use of `execfile()` before. We use a devsettings.py and use it to override an individual server or local settings, and then on the live/deployed server, no devsettings.py is even included. Hence the try...except wrapped around it. It's a nice little pattern that gets us by, but yes, things like this do show that there needs to be one overall "recommended" method for maintaining separate settings on a per server/environment basis.

Carl Meyer

unread,
Mar 22, 2011, 7:17:43 PM3/22/11
to django-d...@googlegroups.com, Ian Kelly

Interesting. I would have assumed that the reason is so that code in
site_settings.py has access to the previously defined values in the main
settings.py, and can actually modify them (i.e. append to
MIDDLEWARE_CLASSES or whatnot). With an import this is not possible.

Carl

Chris Church

unread,
Mar 22, 2011, 7:26:26 PM3/22/11
to django-d...@googlegroups.com, Matt Robenolt
I've used the execfile approach in my settings.py like so:

# Include any local settings that override the defaults.
try:
    execfile('local_settings.py')
    # Hack so that the autoreload will detect changes to local_settings.py.
    class dummymodule(str):
        __file__ = property(lambda self: self)
    sys.modules['local_settings'] = dummymodule('local_settings.py')
except IOError:
    pass

The advantage of execfile over an import is that the local_settings is executed within the settings.py namespace, so your local_settings.py can read or modify default/global settings (add its own middleware, installed apps, etc).

That all being said, I think it's best left to each project or team or developer to decide how to make settings.py work for them and hide any sensitive information.

Ian Kelly

unread,
Mar 22, 2011, 7:37:13 PM3/22/11
to Carl Meyer, django-d...@googlegroups.com
On Tue, Mar 22, 2011 at 5:17 PM, Carl Meyer <ca...@oddbird.net> wrote:
> Interesting. I would have assumed that the reason is so that code in
> site_settings.py has access to the previously defined values in the main
> settings.py, and can actually modify them (i.e. append to
> MIDDLEWARE_CLASSES or whatnot). With an import this is not possible.

That's a good reason too. It didn't occur to me because we don't
actually do that, and I'm having a hard time envisioning a scenario
where we might want to. It's good that it's not outside the realm of
possibility, though.

Reply all
Reply to author
Forward
0 new messages