Comments:"John Resig - Keeping Passwords in Source Control"
URL:http://ejohn.org/blog/keeping-passwords-in-source-control/
I learned a neat tip from my co-worker, Craig Silverstein (more on Craig joining Khan Academy), recently and I thought others might find it to be useful.
It has to deal with the eternal question: How do you store sensitive configuration options (such as usernames, passwords, etc.) in source control? Typically what I’ve done is to just punt on the problem entirely. I create a dummy configuration file, such as conf/sample-settings.json
which has the basic structure but none of the details filled out. For example:
conf/sample-settings.json
If someone else needed the details I would just email it to them, or some such (not ideal). Especially when it came time to add additional information to the file or make other changes.
The technique I picked up from Craig was to, instead, keep an encrypted version of the configuration file in source control and then provide a means through which the user can encrypt and decrypt that data.
In this case you can still have the a dummy config file, if you wish.
To start you’ll want to make sure you have your source control ignore the configuration file — just to make super-sure that no one ever accidentally commits it. In Git you’d add a line like this to your .gitignore
file:
.gitignore
Next you’ll want to create your actual config file and populate it with the real values.
conf/settings.json
(* Do not check this in to source control!!)
Finally you’ll want to create a script (I’m using a Makefile
) that the user can run to encrypt and decrypt the file. This script uses OpenSSL, and specifically CAST5, to encrypt/decrypt the file. OpenSSL was chosen in particular as it worked out-of-the-box on both Linux and Mac machines.
OpenSSL reads in the appropriate files (depending upon if you’re encrypting or decrypting) then will prompt you for a password to encrypt/decrypt the file. (You’re free to use any encryption scheme that OpenSSL supports, of course.)
Makefile
With all this in place the next step is simple, you’ll run:
and you’ll enter in a password with which to encrypt the config file:
Make sure you write this down and don’t forget it — it’ll be very hard (if not impossible) to get your config file back if you forget the password.
At this point you’ll have a conf/settings.json.cast5
file and you can commit all the changes, using something like:
Now whenever someone downloads the code from source control they’ll need to either fill in their own values into the config file or they’ll need to get the password from you (the one you entered when you ran make encrypt_conf
— or even better, use a shared password safe to manage this). Once they have the password they just run the following and enter it:
If you ever need to update the values in the config file, it’s really straight-forward. Just update the config file, run make encrypt_conf
again, and commit the new conf/settings.json.cast5
file.
One extra bit that you can add to your application, to make this process more intuitive, is a check for a missing config file and output with instructions for using the Makefile
.
For example if you were using Node.js you could do:
Also, you may want to consider having a check to see if the decrypted file is out of date (which can happen if some changes were made in the source control, then were checked out, but you didn’t also run make decrypt_conf
). Perhaps something like the following:
And that’s it! Simpler than passing around config files manually and you still get all the benefit of using revision control to manage the file and changes.