Making ENV variables accessible in development - ruby-on-rails

When storing sensitive credentials I normally create a yml file and load it like so in my development.rb
APP_CONFIG = YAML.load_file("#{Rails.root}/config/config.yml")[Rails.env]
I can then access like so
APP_CONFIG["google_secret"]
Problem is Heroku doesn't like this so i need to set ENV variables locally to make integration easier. so i have created a env.rb file like so
ENV['google_key'] = 'xxx'
ENV['google_secret'] = 'xxx'
ENV['application_key'] = 'xxx'
and to accesss it i thought i could use
x = ENV['application_key']
But its not finding the variable, how do I load them in the development environment?
Thanks

You should put the env.rb file in initializers folder. You can add env.rb file to .gitignore file if you don't want to push it to heroku.

Have you considered using Figaro to do this? Figaro was inspired by Heroku's secret key application configuration, so it's really easy to make secret ENV variables in development accessible in Heroku production environments.
I wrote up an answer on this StackOverflow thread about hiding secret info in Rails (using Figaro) that can hopefully serve of some reference to you as well.

Related

Where should I put keys at my rails app?

I am trying to use the gem webpush to create push notifications at my rails app.
At this part at tutorial he say:
"Use webpush to generate a VAPID key that has both a public_key and private_key attribute to be saved on the server side."
# One-time, on the server
vapid_key = Webpush.generate_key
# Save these in your application server settings
vapid_key.public_key
vapid_key.private_key
My doubt is: What exactly is "application server settings"? Where should I put these keys at my rails app?
Idealy it should be stored in environment variables (depends on the OS you use).
If you are using dotenv gem and find it conveniant to use dotenv in production you can store it in .env file.
To use a variable use ENV['NAME']
Also for this purpose you can use default rails config/secrets.yml file. To use a variable use Rails.application.secrets.name.
Also you can combine env variables with secrets.yml file like:
secrets.yml
...
key: ENV['NAME']
benefit: use variable independent of rails environment.
Notice: Neve share you credentials file to git or any public repo! If you need to share this file with other developers just send them copy with development keys.
Links:
dotenv
environment variables
secrets.yml
I wrote a gem to help with this now that Rails no longer supports secrets.yml.
REMINDER: you should never store a private key or any other secret variable in a file that is committed to your version control - use environment variables for that.

Where do I put the Google API .json key file?

I am trying to integrate Google Calendar API into my Rails app, so I can create Google calendar events from my app.
Google has provided a client_secret.json file. I can use it locally, but now have no idea how to implement the key file on heroku.
Can anyone help me with this?
It should just be a secret and key (the names and values).
For heroku, you can set them as environment variables. Like so:
heroku config:set GOOGLE_SECRET=8N029N81ASLDKFA823_WO4ANF
(but please use the information provided in your json file)
Now. The next step is to make sure that your application only calls for those keys in a single way. An option is to use the config/secrets.yml file. Call to the environment variable in the secrets file. Then, you can use the dotenv gem in development so you have .env file in your application's root where you place all your env vars (but do NOT check in the .env file)
Create a file if it doesn't exist config/secrets.yml and inside it add:
production:
google_secret: ENV['GOOGLE_SECRET']
development:
google_secret: ENV['GOOGLE_SECRET']
(obviously, again, make sure the name is what you choose)
Next add dotenv to your gem file and run bundle
gem 'dotenv-rails', :groups => [:development, :test]
Create a new file called .env in the app's root. And add your variable directly including both the key name and the value.
GOOGLE_SECRET=8N029N81ASLDKFA823_WO4ANF
You can add as many env variables as you need to.
Now edit the .gitignore file and add the .env file to it, to make sure you don't accidentally check in your private information.
Lastly, in any place that you need to USE the environment variable, is to call it from secrets like so:
Rails.application.secrets.google_secret
I know it seems like a lot of steps, but it will ensure that you dev matches your prod without making a lot of if Rails.env.development? statements in your code.

Where to put environment variables on the server?

I have a Rails app on a production server and an .rb file where I do this:
Rails.configuration.my_sect = if Rails.env.development? || Rails.env.test?
{
secret_key: 'some_secrete',
public_key: 'some_public'
}
else
{
secret_key: ENV['key1'],
public_key: ENV['key2']
}
end
The application is on a Linux server. What's the best place to put the values of those secret_key and public_key on the server so ENV['key1'] and ENV['key2'] can always be accessible?
I don't want to use any gem or Capistrano.
I would put them in the server script, because, for example, shell configuration files like ~/.bashrc are not loaded in cron scripts or other scenarios.
The "server script" could be as simple as key1=foo key2=baz rails s.
Add /config/en_vars.rb to .gitignore
Create a file config/en_vars.rb and put your variables there:
ENV['key1']='foo'
ENV['key2']='bar'
Then in config/environment.rb add the lines below the require line:
en_vars = File.join(Rails.root, 'config/en_vars.rb')
load(en_vars) if File.exists?(en_vars)
Even if you say you don't want to use any gem, I recommend you to use dotenv; even if it's not suggested to use it on a production environment.
Otherwise, the simplest plain solution is:
create a per-project environment variables file (let's say "$PROJECT_DIR/.env")
Add it to .gitignore
execute it before the application server starting, with something like
source "$PROJECT_DIR/.env" && rails server
But that's what dotenv is created for, so why reinvent the wheel?

How do you manage secret keys and heroku with Ruby on Rails 4.1.0beta1?

With the release of the secrets.yml file, I removed my reliance on Figaro and moved all of my keys to secrets.yml and added that file to .gitignore.
But when I tried to push to Heroku, Heroku said they needed that file in my repo in order to deploy the website. which makes sense, but I don't want my keys in git if I can avoid it.
With Figaro, I would run a rake task to deploy the keys to heroku as env variables and keep application.yml in the .gitignore. Obviously, I can't do that any more. So how do I handle this?
Secrets isn't a full solution to the environment variables problem and it's not a direct replacement for something like Figaro. Think of Secrets as an extra interface you're now supposed to use between your app and the broader world of environment variables. That's why you're now supposed to call variables by using Rails.application.secrets.your_variable instead of ENV["your_variable"].
The secrets.yml file itself is that interface and it's not meant to contain actual secrets (it's not well named). You can see this because, even in the examples from the documentation, Secrets imports environment variables for any sensitive values (e.g. the SECRET_KEY_BASE value) and it's automatically checked into source control.
So rather than trying to hack Secrets into some sort of full-flow environment variable management solution, go with the flow:
Pull anything sensitive out of secrets.yml.
Check secrets.yml into source control like they default you to.
For all sensitive values, import them from normal environment variables into secrets ERB (e.g. some_var: <%= ENV["some_var"] %>)
Manage those ENV vars as you normally would, for instance using the Figaro gem.
Send the ENV vars up to Heroku as you normally would, for instance using the Figaro gem's rake task.
The point is, it doesn't matter how you manage your ENV vars -- whether it's manually, using Figaro, a .env file, whatever... secrets.yml is just an interface that translates these ENV vars into your Rails app.
Though it adds an extra step of abstraction and some additional work, there are advantages to using this interface approach.
Whether you believe it's conceptually a good idea or not to use Secrets, it'll save you a LOT of headache to just go with the flow on this one.
PS. If you do choose to hack it, be careful with the heroku_secrets gem. As of this writing, it runs as a before_initialize in the startup sequence so your ENV vars will NOT be available to any config files in your config/environments/ directory (which is where you commonly would put them for things like Amazon S3 keys).
An equivalent for secrets.yml of that Figaro task is provided by the heroku_secrets gem, from https://github.com/alexpeattie/heroku_secrets:
gem 'heroku_secrets', github: 'alexpeattie/heroku_secrets'
This lets you run
rake heroku:secrets RAILS_ENV=production
to make the contents of secrets.yml available to heroku as environment variables.
see this link for heroku settings
if u want to run on local use like this
KEY=xyz OTHER_KEY=123 rails s

ENV variables only available in production console, not in app -- Rails, Figaro Gem

I am using the figaro gem and have created an application.yml file with all of my variables as per the documentation. This application.yml file is located in a shared folder (I'm using capistrano) and is symlinked to config/application.yml within the current live app directory, however I can only access the variables in the rails console and not the app. My credentials are listed as follows (real details omitted):
Note: I have tried removing the "" speech marks and also prefixing this list with production: with each line having 2 spaces, not tabbed, and it doesn't solve anything. The permissions on the file are exactly the same, 777, as the databse.yml file which was implemented in the same way.
application.yml
FFMPEG_LOCATION: "/path/to/ffmpeg"
EMAIL_USERNAME: "me#gmail.com"
EMAIL_PASSWORD: "password"
S3_BUCKET: "my_bucket"
AWS_SECRET_KEY_ID: "my_secret_key"
AWS_ACCESS_KEY_ID: "my_access_key"
I can access these variables in the production console =>
Loading production environment (Rails 3.2.14)
irb(main):001:0> ENV["S3_BUCKET"]
=> "my-s3-bucket-name"
However they don't return anything in the app itself. I set my linux box up following Ryan's excellent Pro railscast episode http://railscasts.com/episodes/335-deploying-to-a-vps
How can I get these variables accessible in the app itself?
If anyone needs more code just shout.
EDIT
I removed the figaro gem implemented the yaml config shown in the following railscasts tutorial: http://railscasts.com/episodes/85-yaml-configuration-revised. I think this is effectively what the figaro gem was doing however instead of using ENV variables, the tutorial uses CONFIG[:variables] which seem to work great.
Per Comment:
Nginx runs as its own user, so the environment variables need to live in it's space. As a user when you log in and run console, you're accessing a different set of environment variables than the nginx user accesses.
You can do this if you choose by adding them to the nginx config in the main context. But it's probably easier to go with straight yaml and add your secret tokens to your yaml file.

Resources