Hashicorp Vault is a “secrets” management system, one of the various Hashicorp open-source tools used by the Digital Turbine DevOps team.
This post explains how we use the Vault at Digital Turbine, as well as our new, open-sourced “Hashi-Tools” library.
About a year ago, we deployed Vault to our production environment.
We embraced Vault to eliminate certain bad practices that are quite common in the industry; storing credentials statically in a configuration file or even hard-coded within the project’s repository.
Aside from the obvious security issue, this practice usually leads to a situation where multiple services share the same credentials. As a result, these credentials require access to many resources. This breaks the least-privileges principle and makes the revoking process of these keys – if they are compromised – very challenging.
For this reason (and others..), we wanted to change the way in which we work with secrets.
We figured that it would be best to have:
Vault seemed like a natural fit. It technically provides all of the above – supporting dynamic secrets for all popular systems and tools (cloud providers, databases, ssh, etc.) and providing a central, secure and configurable place to store secrets. In addition, it offers a variety of authentication methods which perform authentication and assigning policies to a user and services and finally, it has automatic revocation and auditing.
If you are not familiar with Vault, take a few minutes to review the documentation here.
In Vault, we use policies to restrict access, enforcing the “need to know” principle and implementing a “Role-Based Access Control” by specifying access privileges.
For each backend (AWS/Mysql, etc.), we define roles with a different set of permissions granted.
We want that each service can obtain credentials on demand, for each system, generated by the Vault server with the appropriate permissions. When a service is replaced, rebooted or dies – its credentials should be revoked.
We also like to use Vault as a “secret vault” to store constant sensitive information there, as we do with LastPass.
The flow should then be something like this:
We constructed a Vault cluster. The remaining implementation of the above workflow is on the developer’s side. I feel safe in claiming that for most developers, dealing with secrets is a no-brainer. Credentials with more than enough permissions either find their way to a configuration file inside the node, or they just all have access to them and they can put them wherever they like in the Git repo. With Vault, to be able to communicate with the Vault server, the developer implements an authentication mechanism in each project.
This is how it is done:
After logging-in, to obtain credentials from the Vault server, an HTTP call with the appropriate properties is required; and then parse the response and periodically renew the lease, along with the regulars, such as handle failures and monitoring.
To ease the migration of the secrets management to Vault, I wrote an SDK library. Most of our services are written in Scala, and so is the client.
The library contains two clients:
The library is used by all of our backend applications written in the past year.
So then let’s update the workflow:
The main features for Secrets are:
The full documentation can be found in the project’s repository.
There is still a long way to go to making the SKD more complete. The main tasks are here.