Secure Config as Code
How do you manage your database passwords for your application when applying the DevOps practice Everything as Code? This article gives you some directions.
What is Config as Code?
Before we can dive into Secure Config as Code we have to know what “… as Code” means:
Config as Code is about treating the configuration of your application (or service) the same way you treat your source code: you keep it in version control, you make it testable and you apply continuous integration and delivery (CI/CD) principles.
Infrastructure as Code (IaC) is often used interchangeably but has a different scope. It is about applying the software development practices mentioned above to your IT infrastructure. IaC is also known as programmable infrastructure.
The problem: Secrets in version control
Config as Code is a nice concept but it has a major issue. Keeping configuration data together with your source code in version control would mean you store your secrets in plain text as well. This is definitely a no-go for production environments.
Secrets are sensitive information of any kind like passwords, API keys, keystore passphrases that need separate treatment. Let’s see how.
Solution attempt 1: Protect your version control
You could keep your secrets in plain text in version control and restrict access to your version control system (VCS). This means you would have to hide your repo from anyone who might be interested in your code (and not your configuration). This is generally not a good idea.
Solution attempt 2: Keep your config in a separate VCS
In order to make your source code available you could separate your application config from your source code and only protect your application config with VCS access control. This has two major drawbacks: How do you keep your source code in sync with your configuration? And how do you provision access for target machines?
Solution attempt 3: Encrypt your secrets
Instead of maintaining secrets in plain text you could encrypt them prior to putting them into version control. This sounds like a viable solution. And then you have to decrypt those secrets. But how and where? By distributing the decryption secret on your target machine.
This approach sounds promising and decent tooling exists such as BlackBox or git-crypt which support GPG encryption for Git repos, but it has two drawbacks. First, the encrypted data is always only one secret away from being decrypted. Second, you’re stuck with automation and you have to provision your infrastructure manually.
This attempt still works for smaller applications/services with a handful of environments but it doesn’t work at a larger scale.
Solution attempt 4: Vault
If you want to go further with automating your secret management then you could use the open source solution Vault by HashiCorp. Vault supports a lot of use cases around managing secrets. You best get started by visiting their website https://www.vaultproject.io, reading through their intro section, and working through their awesome interactive tutorial.
In its core, Vault has a token authentication system. Clients — be it humans or machines — first have to authenticate with Vault to get an authentication token which expires after a configurable amount of time. So there is no master key that has to be distributed on all target machines.
For our use case, Secure Config as Code, Vault solves the chicken-and-egg problem of securely provisioning target machines automatically by providing a feature named AppRole that supports more than one channel/mechanism. You can read more about AppRole and its predecessor App ID here: https://www.vaultproject.io/docs/auth/index.html.
A drawback of this attempt is to keep secrets in sync with your application source and config. Maintaining and running a productive Vault cluster also needs a considerable amount of knowledge.
Vault is a promising solution in the DevOps area and is very lightweight and developer friendly. However, it comes with a certain complexity and cost. Give it a try to find out if it suits your needs.