[GSOC 2020] Proposal for a native secrets manager

Greetings!

As I am trying to design an elegant solution to the problem, I’ve checked a few intrinsics of Django and would like to give an overview to get some feedback. These are some implementations that I believe are well suited for the situation:

  • Make secret variables available at runtime in settings, from django.conf package (single settings.SECRETS dict, maybe?)
  • Create committable secret files by encrypting the values (as adopted in other frameworks, like Rails’ secrets.yml)
  • Create a friendly interface to allow developers to plug external secret vaults to the proposed solution (as a developer, one can plug an existing vault to make variables available in settings, as mentioned in the first topic)

Given these few features, I’ve stumbled into a doubt. Is it possible to use the already existing SECRET_KEY to encrypt/decrypt the secret variables? I haven’t come to a solution to this problem yet, maybe an external file with a public-private key schema could also be used for that purpose, but it seems like it would require more setting up than the community expects.

Any feedback regarding this issue is welcome. I plan to develop a more detailed solution to submit as my formal proposal soon.

Sincerely,
Victor Moura.

1 Like

I personally quite like how ansible manages secrets with ansible vault. It is a python implementation too, so it could inspire you.

1 Like

I agree ansible vault is great. I’ve used it before and I believe its internal behaviour could be implemented into Django, but abstracting it to our users.

As developers, Django users meed to keep some data secret, but in a large enterprise, they are unlikely to be able to control exactly what secrets management engine is in use by Ops and Infrastructure. They are likely to want to provide CyberARK, AWS Secrets Manager, HashiCorp Vault and so on. At the same time, as Django users need some thing easy and self-contained to start with.

I really like the idea of modeling this on Rails secrets.yml, or with a vault - I wrote something similar that I never really finished enough for Django to use https://pypi.org/project/confsecrets.

However, if there is time, it would be great to structure this something like AUTHENTICATION_BACKENDS or DATABASES, not saying that there should be more than one secrets manager at a time, but that the implementation has a type (like the DATABASE alias’s ENGINE), and parameters (like a DATABASE alias’s HOST, PORT, etc.)

I actually wrote the proposal for this GSOC topic, and I’ve been asked to work with AWS Secrets Manager, a home grown secrets manager, and had to use my own solutions like https://pypi.org/project/confsecrets. In one project, I’ve had to use both confsecrets and a home-grown secrets manager.

1 Like

I want to answer more concretely this question:

Is it possible to use the already existing SECRET_KEY to encrypt/decrypt the secret variables?

Django and Python include 1-way hash capabilities, so you can make sure that a value signed using the secret_key has not been modified, but this is not encryption. Two Python packages provide cryptography - PyCryptodome and Cryptography. The second is preferable at this time. With the addition of one of these modules, the SECRET_KEY could also be used for symmetric encryption/decryption. The Django user will probably need some management commands to get additional things into settings.SECRETS.

The SECRET_KEY however is not enough, because then all Django applications would be using the same salt. Instead, each Django project must provide some sort of encryption Salt on their own to use the settings.SECRETS. For why this is, I would refer you to Bruce Schnier’s book, Applied Cryptography. I never got all the way through it; so I don’t judge, but that’s how I learned to work with cryptography libraries correctly.

1 Like

Yeah, as I started to check how Django used this SECRET_KEY I realised that its used for hashing only, which wouldn’t be a good fit for the situation. I adapted my formal proposal to consider another alternative regarding cryptographic keys, similarly to Rails’ secrets, which is a feature that I’ve had a great experience as a developer in previous opportunities.

Thank you for the detailed explanation :slight_smile:

I’ve been thinking about this - when I wrote confsecrets, I was concerned about two things that do not necessarily apply to a Django OOB feature:

  • Re-reading the secrets file if it has changed outside of Django (e.g. rather than caching a secret in memory, always check).
  • Meeting government encryption standards, and so using a 32-bit key with AES (AES-256)

I think the Fernet encryption in cryptography is perfect for an OOB Django implementation.

It is more important I think to get an API right - you suggested something like Rails’s secrets.yml, and they had some confusion there about what goes in git and what is kept out. A super cool feature therefore would be integrating with the OS’ keyring on Linux and OS X … but not necessary.

1 Like

Fortunately, even though the submission deadline has passed, I defined how I imagine the usage of this feature (similarly to Django settings: settings.VAR_NAME) but with its own object (so it can be loaded before settings and the usage in secrets.py itself can occur).

I also specified how, when and which files I imagine that would be created and which could be committed or not.

Regarding security issues, I suggested AES256 and mentioned that there should be a solution to prevent memory cache attacks (I guess your suggestion is a feasible solution, my concern is how costly it would be to constantly decrypt a large secrets file. This is something that will have to be discussed in a further opportunity).

Thank you very much for your feedback, it has been very insightful and, luckily, the last one was covered in my submission despite my availability to read it only by now xD