Friday, January 31, 2020

Re: How to best secure environment variables (secret key, passwords etc.) stored in .yml files?

On 1/02/2020 2:24 am, Bill Torcaso wrote:
>
> A couple of years ago I posted on this topic to say that using ENV
> variables is dangerously subject to human error.  If it ever happens
> that (1) you put a server on the public internet with DEBUG on, and
> (2) a visitor can provoke a 5xx server error response, then all of
> your secrets will be dumped in the stack-trace output.
>
> (Yes, I know people will say "don't do that" regarding point #1, and
> similarly say "never publish code with a possible 500 error event". 
> But if it ever happens, you are screwed.  And you won't necessarily
> know that it happened.)
>
> In general, if your secrets are kept in plaintext in your github
> repository and your repository gets compromised, then you have lost
> everything.

I agree with all that. I hadn't considered the DEBUG gotcha but now you
mention it nothing is more certain. If it can go wrong it will. Don't
know whose law that is but I respect it. I always look at the worst case
and assume it will happen.

Please correct me if my assumptions are wrong but if the server itself
is compromised it doesn't matter about the secrets.

If I have access to the machine I could examine the code and find the
api which decrypts secrets and then write a script to fetch and decrypt
any secret. But why would I bother if I have already pwned the machine?

A real problem is spreading secrets around a multi-person dev team and
needing to change them all whenever a team member leaves.

Keeping them in editable text files in a standardised location for each
project lets the secrets be kept and easily updated by the minimum
number of people. Developers obviously know the standard location but
might require sudo to see them. That would be fine on their own machines
where their secrets can be mostly different than server secrets.

The layout of each secret in its own file named appropriately (eg.,
django_secret_staging.txt, django_secret_dev.txt, django_secret_prd.txt
etc) would permit the server software to retrieve the secret when
required using a simple method which works on all machines. I call mine
get_creds() and that lets me have different secrets between staging and
production. Compromising one machine doesn't undermine the other.

I think you are on the right track by keeping secrets in text files. I
just think encrypting them is a step too far.

Cheers

Mike

>
> I've tried to think of a way to store the secrets in a plaintext file
> and encrypt the file's contents before committing the ciphertext file
> to the repository.  The question, as always, is where to store they
> key for decrypting the secrets file.
>
> I have an idea in which the encryption key is manufactured on the fly
> from some non-obvious fact about the repository contents.  I'd like to
> get feedback from the Django community about it.
>
> Summary:
>
> * Put all secret info in a text file, but encrypt the file before it
> gets committed into the repository.
>
> * *Use an encryption key that is derived from some fact about the
> files in the repository.*
>
> * At runtime, use that same fact to derive the decryption key for
> the secrets file.
>
> * Ensure that the runtime server can never reveal the fact that is
> the basis of the encryption key.
>
>
> Suppose for example that the encryption key is the SHA-1 hash value of
> urls.py.  This is calculated during the release process, and used to
> encrypt the plaintext secrets file.  Then the encrypted secrets file
> is committed to the repository, and ultimately gets deployed to
> production.
>
> urls.py obviously changes over time.  But it is constant for any given
> commit of the entire codebase, which is what gets deployed.
>
> At start-up time, the Django server can open urls.py and hash the
> contents, and use that hash value to decrypt the contents of the
> secrets file.  As a result, the secrets are available at runtime, but
> they are never stored in a plaintext file.
>
> Why is this secure?  It relies on two assumptions.
>
> 1. Ensure that the contents of urls.py will never be published as
> part of an HTTPResponse.
>
> When this is true, the runtime server cannot reveal the decryption
> key for the encrypted secrets file.  That is to say, do not write
> a management command with name "getthesecretdecryptionkey".
>
> 2. Using security-through-obscurity, do not always use the same file
> (urls.py) as the basis of the hash value. Instead, use some
> obscure selection criteria like "the seventh-largest .PY source
> file in the tree; in case of a tie, use the alphabetically last file".
>
> Similarly, do not always use the same hash method; instead, select
> a hash method from a list like [ "SHA-1, SHA-256, "MD5", ] by
> taking the size of urls.py modulo the length of that list.
>
> I look forward to hearing comments about this approach.
>
> Bill Torcaso
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users+unsubscribe@googlegroups.com
> <mailto:django-users+unsubscribe@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/91ae856c-8408-44c6-893d-12e1189a418d%40googlegroups.com
> <https://groups.google.com/d/msgid/django-users/91ae856c-8408-44c6-893d-12e1189a418d%40googlegroups.com?utm_medium=email&utm_source=footer>.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/d64387f8-81af-a1c6-74b8-840a204214ba%40dewhirst.com.au.

No comments:

Post a Comment