GSOC 2020: Secrets Manager

Hello! :grin:

My name is Ashlah.

I also want to participate in Django’s Google Summer of Code. I pick the Secrets Manager topic from Django’s ideas list. I know there are some topics discussing this, but I think I have a different approach on how to tackle this problem.

My stands are based on these statements (emphasizes are mine):

… and provide secrets per environment - either as environment variables, files, or via a direct HTTP API. The project would be to design and add an abstraction interface over secrets managers that allows users to easily map to an external secret in a settings file. …

… the key thing we need to build and make sure is good, is the design of the API we give to people using Django, as that’s the thing that will be hardest to change later. …

… one thing users struggle with is keeping secrets out of settings files. So if we had a good story (with a nice API) and how you store secrets (in say a file that gets loaded into the environment) without other dependencies then that’s a big win.

The Django Way™ is to put such things in settings, but the whole(?) point of this is to keep values that would go into setting out of it.

My Idea

My idea is giving the developers an API using a module-level variable (similar to django.conf.settings), namely secrets, which can be used as a mapping object (similar to os.environ). Using this approach, developers can have access to their secrets anywhere by simply import and get the secrets by it’s key.

from django.conf.secrets import secrets

secrets['SECRET_KEY']

The source of secrets (files, HTTP API, or any other sources) can be defined through the SECRET_BACKENDS settings which contain the list of parameters of the secret backend classes that will be used.

SECRET_BACKENDS = [
    {
        'BACKEND': 'django.conf.secrets.backends.DotEnvSecret',
        'OPTIONS': {
            'PATH': secrets['DOTENV_PATH'],
        },
    },
    {
        'BACKEND': 'custom_secret_backends.GoogleSecretManager',
        'OPTIONS': {
            'URL': secrets['GOOGLE_SECRETS_URL'],
            'CREDENTIALS': secrets['GOOGLE_SECRETS_CREDENTIALS'],
        },
    },
]

The details of my idea can be found here: https://gist.github.com/hashlash/8b8988a19c7167b1b352c3284cda951f

If you have any feedback, I would love to hear it :heart:. I really appreciate it

Cheers,
Ashlah

So, your Django server wouldn’t start if your secrets backend is down right ?

I’m not sure what’s the point of this, whatever backend you want to use in Django runtime, you can use to generate your Django runtime environment or settings file, ie. hit your secret backend with Ansible and write a settings file.

“Secret management backends” are pretty trendy, and I used to be fond of them, but so far I fail to see good reasons why you’d need that in your infra, it turns out it doesn’t add any actual value in terms of security. I mean, sure, you could revoke a secret from outside Django, but in this case don’t you have bigger problems like: shouldn’t you actually shutdown Django until you get control of the situation again ?

Maybe you have a policy of changing passwords which I could understand, but in this case can’t you just regenerate the settings file and SIGHUP whatever you run Django with ?

Don’t get me wrong, I would LOVE to see more security features, we have Cryptographic Signing, why not add encryption ? it would require the cryptography module, but leverage the SECRET_KEY (which you will definitely not want to change in your “Secret management backend”, and which you will want not to propagate outside necessary).

Other than that, you proposal is really well written,
Looking forward to read more :+1: keep up the great job !