Home > other >  Why can't Django find secrets.json file?
Why can't Django find secrets.json file?

Time:02-01

So I have my Django project, and am trying to deploy it via heroku server. I realized that I need to created secrets.json file (in the same directory as manage.py), and then add it to .gitignore, for sake of security. But after deploying the project, I got an error saying it couldn't find secrets.json file. Below is my code.
settings.py

secret_file = os.path.join(BASE_DIR, 'secrets.json')
with open(secret_file) as f:
    secrets = json.loads(f.read())

def get_secret(setting, secrets=secrets):
    try:
        return secrets[setting]
    except KeyError:
        error_msg = "Set the {} environment variable".format(setting)
        raise ImproperlyConfigured(error_msg)
SECRET_KEY = get_secret("SECRET_KEY")

secrets.json

{
    "SECRET_KEY" : xxx,
    "EMAIL_HOST_USER" : xxx,
    "EMAIL_HOST_PASSWORD" : xxx
}

After saving these, I added secrets.json to .gitignore.
But an error occurs at line 2 (with open(secret_file) as f:), saying it can't find secrets.json file. What do you think is the problem?

*FYI, The BASE_DIR doesn't seem to be the problem, since it works fine else where. Such as STATICFILES_DIRS.

CodePudding user response:

You are correct to ignore your secrets file. It shouldn't be part of your repository, and it shouldn't be shipped to Heroku. Since that file is not included in your source code, Heroku can't open it.

As far as I know, having a secrets.json is not a common pattern in the Django / Python world¹.

I'm a bit confused by this:

def get_secret(setting, secrets=secrets):
    try:
        return secrets[setting]
    except KeyError:
        error_msg = "Set the {} environment variable".format(setting)
        raise ImproperlyConfigured(error_msg)

Your KeyError handler refers to environment variables. That's on the right track! Configuring your application with environment variables is a common pattern.

But a JSON file called secrets.json isn't an environment variable. A more common approach would be to load values in your settings file directly from the environment:

import os

SECRET_KEY = os.getenv("SECRET_KEY")

# You can even provide a default in case the environment variable isn't set:
ANOTHER_SETTING = os.getenv("ANOTHER_SETTING", default="some-default-value")

On Heroku, you can set config vars that will be automatically injected into your environment:

heroku config:set SECRET_KEY=some-value

So that leaves local development. There are several ways to set environment variables on your local machine, but a common one is to create a file called .env:

SECRET_KEY=xxx
EMAIL_HOST_USER=xxx
EMAIL_HOST_PASSWORD=xxx

If you run your code locally via heroku local it will automatically pick up your .env file. So will Pipenv, if you use that. There's also python-dotenv and direnv and others.

.env files have become something of a de facto standard, and you're much more likely to find tools supporting them than ones supporting a secrets.json file.


¹There is python-secrets, which might help you with secrets.json files. You appear to be opening your secrets file manually, though.

If you plan to keep using your secrets file, I suggest you find something like this that automatically reads the file and merges settings into the environment. I've never used this library and only came across it in a search while answering this question.

  •  Tags:  
  • Related