Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Figaro v2 development is underway but stalled. I need your help! Please consider sponsoring Figaro's development.
With the constraints of a family and a full-time job, even the emotional support that sponsorship provides is extremely valuable in re-energizing Figaro development. Thank you! 💛
Simple, Heroku-friendly Rails app configuration using ENV
and a single YAML file
NOTE: If you're using Figaro 0.7 or prior, please refer to the appropriate documentation or upgrade to Figaro 1.0.
Figaro was written to make it easy to securely configure Rails applications.
Configuration values often include sensitive information. Figaro strives to be secure by default by encouraging a convention that keeps configuration out of Git.
Figaro is inspired by the Twelve-Factor App methodology, which states:
The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard.
This is straightforward in production environments but local development environments are often shared between multiple applications, requiring multiple configurations.
Figaro parses a Git-ignored YAML file in your application and loads its values
into ENV
.
Add Figaro to your Gemfile and bundle install
:
gem "figaro"
Figaro installation is easy:
$ bundle exec figaro install
This creates a commented config/application.yml
file and adds it to your
.gitignore
. Add your own configuration to this file and you're done!
Given the following configuration file:
# config/application.yml
pusher_app_id: "2954"
pusher_key: "7381a978f7dd7f9a1117"
pusher_secret: "abdc3b896a0ffb85d373"
You can configure Pusher in an initializer:
# config/initializers/pusher.rb
Pusher.app_id = ENV["pusher_app_id"]
Pusher.key = ENV["pusher_key"]
Pusher.secret = ENV["pusher_secret"]
Please note: ENV
is a simple key/value store. All values will be converted
to strings. Deeply nested configuration structures are not possible.
Oftentimes, local configuration values change depending on Rails environment. In such cases, you can add environment-specific values to your configuration file:
# config/application.yml
pusher_app_id: "2954"
pusher_key: "7381a978f7dd7f9a1117"
pusher_secret: "abdc3b896a0ffb85d373"
test:
pusher_app_id: "5112"
pusher_key: "ad69caf9a44dcac1fb28"
pusher_secret: "83ca7aa160fedaf3b350"
You can also nullify configuration values for a specific environment:
# config/application.yml
google_analytics_key: "UA-35722661-5"
test:
google_analytics_key: ~
Figaro.env
Figaro.env
is a convenience that acts as a proxy to ENV
.
In testing, it is sometimes more convenient to stub and unstub Figaro.env
than
to set and reset ENV
. Whether your application uses ENV
or Figaro.env
is
entirely a matter of personal preference.
# config/application.yml
stripe_api_key: "sk_live_dSqzdUq80sw9GWmuoI0qJ9rL"
ENV["stripe_api_key"] # => "sk_live_dSqzdUq80sw9GWmuoI0qJ9rL"
ENV.key?("stripe_api_key") # => true
ENV["google_analytics_key"] # => nil
ENV.key?("google_analytics_key") # => false
Figaro.env.stripe_api_key # => "sk_live_dSqzdUq80sw9GWmuoI0qJ9rL"
Figaro.env.stripe_api_key? # => true
Figaro.env.google_analytics_key # => nil
Figaro.env.google_analytics_key? # => false
If a particular configuration value is required but not set, it's appropriate to raise an error. With Figaro, you can either raise these errors proactively or lazily.
To proactively require configuration keys:
# config/initializers/figaro.rb
Figaro.require_keys("pusher_app_id", "pusher_key", "pusher_secret")
If any of the configuration keys above are not set, your application will raise an error during initialization. This method is preferred because it prevents runtime errors in a production application due to improper configuration.
To require configuration keys lazily, reference the variables via "bang" methods
on Figaro.env
:
# config/initializers/pusher.rb
Pusher.app_id = Figaro.env.pusher_app_id!
Pusher.key = Figaro.env.pusher_key!
Pusher.secret = Figaro.env.pusher_secret!
Figaro is written with deployment in mind. In fact, Heroku's
use of ENV
for application configuration was the original inspiration for
Figaro.
Heroku already makes setting application configuration easy:
$ heroku config:set google_analytics_key=UA-35722661-5
Using the figaro
command, you can set values from your configuration file all
at once:
$ figaro heroku:set -e production
For more information:
$ figaro help heroku:set
If you're not deploying to Heroku, you have two options:
ENV
variables directlyGenerating a remote configuration file is preferred because of:
config/application.yml
is like that of config/database.yml
.Yes. Kind of.
Figaro and dotenv were written around the same time to solve similar problems.
ENV
.KEY=VALUE
pairs.Either library may suit your configuration needs. It often boils down to personal preference.
Yes. Kind of.
Rails 4.1 introduced the secrets.yml
convention for Rails application
configuration. Figaro predated the Rails 4.1 release by two years.
ENV
.Rails.application.secrets
.ENV
for configuration in every environment.ENV
for production only.The emergence of a configuration convention for Rails is an important step, but
as long as the last three differences above exist, Figaro will continue to be
developed as a more secure, more consistent, and more standards-compliant
alternative to secrets.yml
.
For more information, read the original The Marriage of Figaro… and Rails blog post.
In most cases, upgrading from Figaro 0.7 to 1.0 is painless. The format
expectations for application.yml
are the same in 1.0 and values from
application.yml
are loaded into ENV
as they were in 0.7.
However, there are breaking changes:
Figaro.env
In Figaro 0.7, calling a method on the Figaro.env
proxy would raise an error
if a corresponding key were not set in ENV
.
In Figaro 1.0, calling a method on Figaro.env
corresponding to an unset key
will return nil
. To emulate the behavior of Figaro 0.7, use "bang" methods as
described in the Required Keys section.
NOTE: In Figaro 0.7, Figaro.env
inherited from Hash
but in Figaro 1.0,
hash access has been removed.
In Figaro 0.7, a Rake task existed to set remote Heroku configuration according
to values in application.yml
.
In Figaro 1.0, the Rake task was replaced by a command for the figaro
executable:
$ figaro heroku:set -e production
For more information:
$ figaro help heroku:set
NOTE: The environment option is required for the heroku:set
command. The
Rake task in Figaro 0.7 used the default of "development" if unspecified.
If you're using Spring, either stop
or add config/application.yml
to the watch list:
# config/spring.rb
%w(
...
config/application.yml
).each { |path| Spring.watch(path) }
My name is Steve Richert and I wrote Figaro in March, 2012 with overwhelming encouragement from my employer, Collective Idea. Figaro has improved very much since then, thanks entirely to inspiration and contribution from developers everywhere.
Thank you!
Figaro is open source and contributions from the community are encouraged! No contribution is too small.
See Figaro's contribution guidelines for more information.
FAQs
Unknown package
We found that daqing_figaro demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.