The Marriage of Figaro… and Rails
Two years ago and 264,309 downloads ago, I wrote the Figaro gem. I had been using the pattern for some time already and was frustrated that something so simple wasn't already included in Rails. And now, finally, it is! Well… sort of.
Secrets
In the wee hours of this morning, DHH shipped Rails 4.1.0.beta1 with support for a config/secrets.yml
file, which is strikingly similar to Figaro's config/application.yml
in its function.
For those of you who are unfamiliar, Figaro loads the contents of application.yml
and merges the values into ENV
. The purpose is to provide Git-ignored configuration for sensitive information like API keys and other secrets.
# config/application.yml
stripe_publishable_key: pk_test_TLr0qqdKhm0yX1bZtKC4kFAC
stripe_secret_key: sk_test_Qbppb2nkFEzPoquOdBym0JL2
# config/initializers/stripe.rb
Stripe.api_key = ENV["stripe_secret_key"]
The purpose of the new secrets.yml
file is the same: to keep sensitive configuration information out of source control. Plus, the implementation is similar.
# config/secrets.yml
stripe_publishable_key: pk_test_TLr0qqdKhm0yX1bZtKC4kFAC
stripe_secret_key: sk_test_Qbppb2nkFEzPoquOdBym0JL2
# config/initializers/stripe.rb
Stripe.api_key = Rails.application.secrets.stripe_secret_key
What now?
On the surface, this Rails feature looks like a Figaro-killer! Figaro even received a new GitHub issue within hours of the Rails release:
This is definitely a step in the right direction but it makes me sad for Figaro :(
However, there are some notable differences between the two approaches. Rails' secrets.yml
has pros and cons when compared to Figaro's application.yml
:
Pros
- Convention. Now that there's an agreed upon convention in the Rails community, there can be a familiarity amongst developers as to how to properly configure a Rails application. Plus, services like Heroku and Travis have the opportunity to support the new convention.
-
Rich object support.
ENV
is limited to string key-value pairs. Oftentimes, an application needs configuration for a number of days or a fee percentage. These numeric values must be cast to strings when written and re-cast when read. -
Secure defaults. Now that Rails has a way to store sensitive information, newly generated applications will not check the
secret\_key\_base
into source control. Knowledge of thesecret\_key\_base
allows an attacker to read and manipulate an application's cookies, exposing your application to remote code execution. Revealing thesecret\_key\_base
value can be absolutely devastating.
Cons
-
The Twelve-Factor App. The twelve-factor methodology outlines best practices for application development in twelve areas, and arises from the experience of prominent application developers and maintainers working on the Heroku platform. One of the twelve areas is Config. It's a great read! tl;dr: Use
ENV
. -
Deployment. Because
secrets.yml
doesn't useENV
, configuring your production application requires installingsecrets.yml
remotely for every application server. This doesn't play well with Heroku's existing configuration conventions using, you guessed it…ENV
.
Conclusion
I don't believe that Rails 4.1's secrets.yml
is a perfect solution for application configuration, but it is a fantastic start!
When I started to write Figaro two years ago, it was as a pull request to Rails. So don't be sad for Figaro! I'm very happy to see that a variation on Figaro finally made its way into Rails.
That said, there may still be a place for Figaro and I'd love to hear your thoughts here on what Figaro's future might look like.
UPDATE:
Add another con to the list. As of now, Rails does not Git-ignore secrets.yml
by default. Going through the motions of generating a new Rails application will still commit the sensitive secret\_key\_base
value to source control. I expect that this will be resolved before Rails 4.1.0 is released.
Check out our latest product, Dead Man’s Snitch for monitoring cron, heroku scheduler or any periodic task.
Comments
Take into account, however, that config/secrets.yml as other YAML files in Rails is passed first through ERB, so you can indeed use ENV.
I’ll keep using Figaro or similar instead of the insecure-by-default setup on Rails. https://github.com/rails/rails/pull/13388
Alex: wow. I just assumed. I added an update to the post. Thank you!
Thanks for the post! I have never used Figaro in an application before (mainly because I have never heard of the gem), but since I use Heroku for my main application, I am definitely going to be looking into this!
The figaro gem is such a nice implementation. Thank you for conceiving it, building it, and maintaining it. It’s convenient to just “$ rake figaro:heroku” to set ENV variables when deploying on Heroku. But I guess If I can use ENV variables in the secrets.yml file, that’s good enough, and I’ll go back to setting ENV variables manually on Heroku. Unless there’s another benefit I’m overlooking?
With the release of 4.1, what’s the verdict on it git-ignoring `config/secrets.yml` by default?
Dennis, great question! I just generated a new Rails 4.1 application and secrets.yml is not git-ignored. The Rails gods have wised up a bit in deciding that at least the production keys should be specified via ENV rather than in the file itself. My question is: why just in production?
Here’s the generator template for secrets.yml:
https://github.com/rails/rails/blob/master/railties/lib/rails/generators/rails/app/templates/config/secrets.yml
For now, Figaro lives on! Version 1.0 will be released shortly.
https://github.com/laserlemon/figaro/blob/master/CHANGELOG.md
Long live the Figaro!
Just a quick post to say thanks for providing this! so much easier to use a simple gem than have to putz with heroku’s environment variables manually :-) (and for whatever reason just feels less secure)
Now just for a simple way to do something like this for my certificate files….