Storing Rails Secrets
Rails apps these days come with a secrets.yml file which conveniently populates a Rails.application.secrets
object which can be accessed throughout the application.
While you could just fill this file up with all of your sensitive credentials and check it into a private repo, thatās probably not the best idea ā and I doubt most of you are doing that.
Instead, youāre probably either generating it at deployment time with a tool like Chef, or taking the Twelve-Factor App approach and supplying your secrets at runtime through environment variables.
Donāt get me wrong, both of these approaches are far superior to just hoping your secrets.yml
doesnāt get leaked, but they still pose some risk.
For example, even if youāre storing your cred in encrypted databags on your Chef server, what happens if the populated file on disk gets leaked? Similarly, environment variables have their own problems.
Luckily, for Rails apps deployed to Cloud Foundry with a CredHub, thereās another way.
At itās most basic, CredHub is just an encrypted credential store ā similar to HashiCorp Vault. What makes CredHub nice, though, is how seamlessly your Cloud Foundry deployed apps are able to communicate with it.
Introducing CredHubble ā A CredHub Ruby Client
So how do you integrate CredHub with your Rails app? This is where the CredHubble CredHub ruby client comes in. CredHubble is an http client for the CredHub API that Iāve been working on in my spare time since thereās currently no official Ruby client available. I used to make service clients all of the time while working on HealtheIntent at Cerner so it was a bit nostalgic to get to play around with Faraday and Virtus again.
Itās not an unofficial client, so I didnāt want to take an official sounding name credhub-ruby
or something. So I thought real hard and tried to be creative.
CredHubble was the best I could come up with. It lets you look at or view credentials, just like the Hubble Space Telescope lets you look at much cooler things. Like galaxies and supernovas. Yeahā¦
CredHubble is not perfect by any means and CredHub has a pretty simple API so you could whip up something custom with Net::Http
pretty quickly and name it something even better if you want. š
It does handle most of the CredHub API endpoints that youāre most likely to care about as an app developer, though.
Anyways, hereās how you can use CredHubble to fetch secrets from CredHub and populate your secrets.yml
.
First, add cred_hubble
to your Gemfile and run bundle install
. This will install the gem and make it available to your app.
Next, weāre going to make an initializer to bootstrap the client.
Initial Client Setup
If your environment has a CredHub instance deployed, your app instances will automatically come with two environment variables:
CF_INSTANCE_CERT
CF_INSTANCE_KEY
These point to a TLS client certificate and TLS encryption key that your app can use to authenticate with CredHub over mutual TLS. The CredHub serversās TLS certās CA will already be included among the Diego cellās trusted certificate authorities so you donāt need to worry about it. Weāll use these two variables to instantiate our client:
Using your CredHub Client
Now that you have a client available throughout your app, you can call out to it in your secrets.yml
. Hereās a brief example of what that might look like:
In the above example, the CredHub credential names are passed in through environment variables for deployment convenience.
This allows them to be set with a simple cf set-env
or specified in your applicationās CF manifest.yml
.
So whatās going on here? Well itās really pretty simple. The current_credential_value
method on the Credhub client fetches the current value for the credential with the given name (e.g. '/secret-key-base'
).
CredHub saves historical versions of credentials for auditing and to simplify credential rotation, but for our example app we only care about the most up to date version.
The interpolate_credentials
method takes in a JSON encoded string, such as the VCAP_SERVICES environment variable and will ask CredHub to populate any credentials that have "credhub-ref"
as their key.
This is handy for getting access to any service instance credentials that may have been stored in CredHub*.
* Note: Future versions of Cloud Foundry will support dereferencing VCAP_SERVICES
automatically and will populate you appās environment with the dereferenced values so that applications do not need to be CredHub-aware.
This can behavior can be disabled, however, so you still may need to have your app āinterpolateā VCAP_SERVICES
manually.
Getting Credentials into CredHub
Weāve now seen how to read secrets from CredHub and place them directly into our secrets.yml
file. But how do we get them up there in the first place?
The CredHubble client supports setting credentials, but you may also find it easier to just use the credhub-cli and to follow the docs.
Itās important to note, though, if youāre using the CLI with UAA auth, the important thing here is to give your app the appropriate permissions to be able to read any Credentials youāve made. This means give "read"
permissions to the "mtls-app:<app-guid>
actor.
Anyways, hereās how you can do it with CredHubble from within a Rails Console:
Instantiate the client (or just use the Credhub.client we made in our initializer):
Create your credential:
Set your credential:
You can now retrieve it and view its permissions:
Well there you have it, a way to make your Cloud Foundry deployed Rails app a bit more secure through CredHub and CredHubble. I hope you found this post helpful, and if notā¦ well at least I tried. šš