0

My Django application uses at lot of environment variables, around 35 in total. Currently all these are handeld by a .env file that I source before I start my application stack. I guess that I don't have to point out that this is by far a very insecure way especially if it's about secret key's in production ...

Now my problem is that I don't really understand how to make the switch from a .env file to secrets, as I don't understand how to process the secrets at my container. For example, Django uses a connection string to connect with my MySQL database, see below:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
        'NAME': env.str('MYSQL_DB'),
        'USER': env.str('MYSQL_USER'),
        'PASSWORD': env.str('MYSQL_PWD'),
        'HOST': env.str('MYSQL_HOST'),
        'PORT': env.str('MYSQL_PORT'),
    }
}

Most of the time I use "env.str" to fetch my vars that I pass to the container at start. So how can I make my Django application work with docker secrets and if possible stay with fetching vars the way like shown above? Is it maybe possible to load all needed vars on start at my docker-entrypoint.sh, and if yes, how can this be accomplished?

I already came acorss this solution:

if [ -f /run/secrets/MYSQL_PWD ]; then
  export MYSQL_PWD=$(< /run/secrets/MYSQL_PWD)
fi

if [ -f /run/secrets/MYSQL_USER ]; then
  export MYSQL_USER=$(< /run/secrets/MYSQL_USER)
fi

Does that makes sense to trigger on startup to gets my env vars in place? See: https://github.com/grafana/grafana-docker/issues/149

Thanks for reading

  • Does this answer your question? [docker stack: setting environment variable from secrets](https://stackoverflow.com/questions/48094850/docker-stack-setting-environment-variable-from-secrets) – Iain Shelvington Aug 29 '20 at 00:19
  • @IainShelvington Indeed, that is some usefull information, but to me export $(egrep -v '^#' /run/secrets/* | xargs) is almost the same as my code mentioned above just more compact, thanks for sharing :D –  Aug 29 '20 at 00:22
  • @IainShelvington Just to make things clear to me, I first create all needed secrets for docker to later be available at /run/secrets. From that point on I simply trigger export $(egrep -v '^#' /run/secrets/* | xargs) at my entry point script to get the vars loaded inside my container, right? –  Aug 29 '20 at 00:25
  • If you want to use docker secrets and make them available as environment variables in your app, yes that's correct – Iain Shelvington Aug 29 '20 at 00:26
  • And does that also has some security benefit if I do it like that or is my container still "vulnerable" from this perspective if I load my secrets like that? Because that's actually the point I want to work around as you can already imagine ^^ –  Aug 29 '20 at 00:28
  • Passing secrets as mounted files to your containers secures them against users that can read the environment variables passed to the container, it does nothing to hide them from users that can exec into the containers. Which vulnerability are you trying to protect against? – Iain Shelvington Aug 29 '20 at 00:38
  • I'm pretty sure that nobody is able to easily access the docker hypervisor itself but I'm not sure about exploits or buffer overflows that might grant the attacker access to sensitive data inside the container... As the container is the resource that gets exposed somehow it will always remain a attack vector I want to get rid off as pratical as possible if it comes to sensitive data ;) –  Aug 29 '20 at 00:45

1 Answers1

0

One option is to create one secret with your file then use the source commande to load all your environment variables all at once.

docker secret create mysecret <path_to_your_env_file>

source /run/secrets/mysecret  // in your entrypoint.sh
Cyril G.
  • 1,879
  • 2
  • 5
  • 19
  • Okay but do I than have all my secrets in just one file? –  Aug 29 '20 at 00:25
  • Yes, the first command is making a secret with all your environment variables inside, the last parameter is your file. If you prefer you can make several files / several secrets, it is up to you. Then your secret is available like a normal file inside the container, you can use source command to load your variables. I updated my answer to be more clear. – Cyril G. Aug 29 '20 at 00:35
  • Okay, nice! But anyways not all my services need all vars and its a potential attack vector to have them all loaded where they are actually not really needed. I'm working with celey, redis etc and not all instances of my application need all vars so I guess that I will stick to the If statement like shown above as its more "fine granulated" anyways thanks for pointing out your answer :D –  Aug 29 '20 at 00:49