| First: I completely agree. Keeping plaintext secrets in source control is a bad idea. Encrypting them is a good idea. If you have plaintext secrets, encrypt them now using this makefile or git-crypt. Then rotate them. That said, this solution has a couple of issues: 1. It encrypts the entire file instead of individual secrets in the settings file. Encrypted files can't take advantage of many version control features. A small change in plaintext creates a huge diff in ciphertext. Git blame doesn't work anymore. Git diff gets a lot more spammy, since you'll see a diff for the entire settings file if there's the slightest change in it. 2. It uses symmetric key encryption. If a developer knows the password to encrypt a secret setting, they can decrypt all the other secret settings. This is true until someone rotates the passphrase and re-encrypts the file. To fix both of these problems, I recommend using Keyczar (http://code.google.com/p/keyczar/). If you write the right wrappers, it allows you to encrypt individual settings with a public key. Decrypting them requires a private key that exists only on production servers. At a past job (Cloudkick), sensitive things in our settings.py looked like this: from cloudkick.crypto_wrappers import kz_decrypt
...
BORING_THING = "whatever"
SECRET_THING = kz_decrypt("kz::xxxx....", "/path/to/private/key")
kz_decrypt did exactly what you'd think: given an encrypted string and a private key, return the decrypted string. The private key was only on production servers, so the risk of leaking a secret was minimal. The public key was in source control, so anyone could encrypt a secret. For debugging or testing, one could also replace the call to kz_decrypt with a plaintext string. I wish the code had been released. It was only 100 lines or so.This set-up would require a some extra work for settings files that don't allow code execution. Still, once you've set it up, it's pretty close to the most secure and convenient way to store secrets. |
The whole reason for doing it at all was simply that MySQL doesn't support Kerberos. There's a very old ticket for that in their bug tracker.
"For everything else, there's Kerberos."