Keeping Passwords in Source Control
ejohn.org
ejohn.org
[1] https://github.com/AGWA/git-crypt and http://www.agwa.name/projects/git-crypt/
(or the diff is done on the plaintext and then encrypted?)
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."
We use a combination of Google's open source Keyczar [1] and a relatively new Python keyring [2] library which uses the Keyczar crypter to read/write keys to a keyring storage backend, where the backend interface can be implemented with local crypted files or a cloud service.
[1] http://www.keyczar.org/ [2] http://pypi.python.org/pypi/keyring
We built this Python wrapper called appauth around of the concept of a Keyring service by application domain.
e.g. pseudo code:
import appauth
auth_service = appauth.AuthService('my-web-app')
db_creds_cfg = auth_service.get('primary-db')
Inside of db_creds_cfg, it can be a free-form dictionary that provides whatever details is needed to get into a resource: db_creds_cfg['db_host']
db_creds_cfg['db_port']
db_creds_cfg['username']
db_creds_cfg['password']
I put in some honest effort to find an open source solution to this, but failed to find anything with a simple install process AND programming interface. Is there any interest from HN if we choose to open source this?Furthermore, we use Google Authenticator on our servers to require two-factor auth: http://code.google.com/p/google-authenticator/, on top of disabling password auth in favor of signing in with ssh keys. All log files are then either set to permission 600 just to be super paranoid.
http://www.postgresql.org/docs/9.0/static/libpq-pgservice.ht...
I personally don't understand this type of comment. Just open source it!
In fact, none of our web servers carry ANY credentials at all. Our IIS processes run as a specific user and are granted access to resources (message queues, databases etc) as required.
I'm not sure stuff like this is entirely possible on Linux (I haven't tried to be honest), but I assume you can do the equivalent with OpenLDAP / pam_ldap and SELinux.
BAsically, we don't use global config like that by design - the application only recovers the security context on demand.
Still, much better than keeping the passwords in VC unprotected, of course.
My preference still is using environment variables so that the secure bits can be fully decoupled from your code, however..
If you're not familiar with the practice, I'd encourage you to read the "twelve-factor" section on configuration: http://www.12factor.net/config . The advice applies even if you're not using Heroku for hosting.
To be honest, not having secrets under some kind of source control seems like a bad idea, as you just know that the reality is that they will be in an untracked spreadsheet somewhere.
The disadvantage is that you'll need to compile scrypt from source.
[1] http://www.tarsnap.com/scrypt.html
[2] slide 20: http://www.tarsnap.com/scrypt/scrypt-slides.pdf
[3] slide 19: http://www.tarsnap.com/scrypt/scrypt-slides.pdf
http://packages.ubuntu.com/search?keywords=scryptReplacing an encryption algorithm with a key derivation function doesn't make sense.
Both kdf and cipher are used during single file encryption with openssl and the scrypt command line utility. Openssl implicitly uses a md5 as a kdf during encryption [1.1][1.2]. Cast5 requires a 128bit key, and the kdf helps stretch the user's password to fit this key requirement.
I can understand the confusion, as scrypt is typically referenced in kdf discussions. It's actually somewhat difficult to extract the kdf functionality from the scrypt source code because the code is geared towards single file encryption. See this post for a confused q&a with scrypt's author [2]. Wrappers around scrypt like this python package[3] have made the "mistake" of using the entire encryption pipeline when they just wanted the kdf. Using scrypt in this manner should still be safe, but it will waste some cpu cycles on aes.
[1.1] http://www.openssl.org/docs/apps/enc.html
[1.2] http://www.openssl.org/docs/crypto/EVP_BytesToKey.html
It probably doesn't matter either way, but when you deviate from standard best practices in crypto you should at least explain why you do it. (my best guess would be that the code predates the invention of AES?)
Why are you mixing deployment with development? They should be two different things IMHO.
More info on hiera-gpg here: http://www.craigdunn.org/2011/10/secret-variables-in-puppet-...
> console.error("You need to run `make decrypt_conf` to update it.");
Couldn't you just make the decrypt_conf target depend on the encrypted configuration file and make the standard build command depend on the decrypted file? This way it would get enforced with every 'make'.
In case you don't use Makefiles for building at all (because you only use script languages for example) I don't get why you use a Makefile instead of just two shell scripts.
If this is the first target (or a prerequisite of the first target), then running 'make' will ensure that those variables are set to non-empty strings.
> var db_password = process.env.DB_PASS ;
You dont have to keep any password sensitive file whatever inside an opensource project. that is what envirronment variables are fucking made for !