Infrastructure as Code – Don’t Let Security Slow You Down
February 6, 2015 | DevOps | Dustin Collins
A particularly thorny problem many developers face when writing configuration management code is how to use different secrets to test against various parts of their infrastructure. For best results, obtaining secrets should be the same no matter which environment you are in: local, test, dev or prod.
Current approaches all have the same problem: they introduce confusion into how your organization handles security. Confusion slows your team down. Slowing your team down makes another team angry because they’re waiting on that update to the platform to deploy their new application. Others are frustrated that we’re all cutting corners with security. Breaking SecDevOps is easy, see?
Here are some of the more popular ways to approach using secrets during development:
1- Write the secrets into the code.
No one disputes that this is bad form, even if your code is in a private repository. There is no separation of duties, access is way over-privileged, and there is no audit of access (although there is audit of updates).
2- Write the secrets to local files ignored by source control.
Looks fine from a source control standpoint, but wait – how do I get the secrets to create this local file, are they stored somewhere for me to retrieve or just in someone’s head? How are secrets being made available to our different environments? What happens when they change, how do I know to get new secrets?
3- Export the secrets as environment variables on the dev machine.
Same problems as #2.
4- Use something like chef-vault or citadel to provide the secrets on converge.
Chef-vault uses a machine’s public keys to grant authorization to a public service. The mechanism for creating those keys, getting them on the machine and retiring them are left up to you. Instead of being to create a role-based mapping of nodes, you are stuck with passing a list of nodes. Also, now you can only use Chef.
Citadel tackles the problem by using AWS IAM groups. Once you grow your infrastructure to a non-trivial size you end up with a gnarly mess of CloudFormation templates. And unless you develop on an AWS machine, you can’t test locally very easily.
So to recap, the above solutions can be characterized as:
Give up on secrets management and just give them to everyone
Have a few individuals manage secrets and require devs to request them as needed
Force developers to manually manage and exchange the secrets using a non-defined process
Lock the system into a single technology (Chef or AWS); and still be without audit capabilities, or ability to support true dev/ci/production workflows.
Reducing confusion and friction to enable speed with security is one of our primary goals at Conjur. To that end, we provide tooling to make development with secrets easier.
Let’s walk through an example of using Conjur in a test-kitchen workflow, injecting secrets into our kitchen.yml at runtime. The code for this example is here: https://github.com/conjurdemos/conjur-kitchen. Follow the README to launch it on your machine.
We are converging the rabbitmq cookbook, injecting the management console’s username and password from Conjur. This is just a standard cookbook setup with one file of note, `.conjurenv`. This file maps secrets stored in Conjur to temporary environment variables or files and allows you to run them in local context. When we run `conjur env run` the variables are pulled from Conjur and exported to environment variables only until the command exits. In this case `RABBITMQ_USERNAME` and `RABBITMQ_PASSWORD` are made available. You can always check if you have access to these secrets by running `conjur env check`.
Now all we have to do is override the Chef attributes in our `kitchen.yml` to point to these environment variables and we are ready to converge. `conjur env run — kitchen converge` is the command. The instance converges correctly, the tests run and test-kitchen exits. If you now run `echo $RABBITMQ_USERNAME` you get nothing. That environment variable is gone as soon as test-kitchen exits. This part is important – no credentials are left on the developer machine. As a developer I don’t even need to know what the value of the secret is. When someone rotates this secret, it doesn’t hinder my workflow at all.
This test-kitchen demo is just one example of how Conjur can enhance your existing workflows without sacrificing speed for security. Any tool you use that can accept environment variables as input will work great with Conjur.
Read more about the conjur env command here: http://developer.conjur.net/reference/tools/conjurenv