ENV variables loading as nil - ruby-on-rails

I am trying to run omniauth. I have my initializer as follows:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :coinbase, ENV['CLIENT_ID'], ENV['CLIENT_SECRET'], scope: 'wallet:user:read wallet:user:email wallet:accounts:read'
end
with my client ID and secret saved in my .env file. When I boot my server, however, both of these variables are listed as nil. I can get the procedure to work when it is hard coded, but this is obviously not a good practice. How can I get the variables from my .env file into my initializer?

Problem was solved by leveraging the dotenv gem and following the instructions in the readme

Related

Write a custom OmniAuth strategy

I've got a Rail 4 app with Devise.
I'm trying to configure OmniAuth to use our corporate Ping OpenID Connect IdP.
It appears that I have to write an OmniAuth strategy in Rack Middleware.
I took the 'omniauth-digitalocean' gem (which has their strategy) and carefully replaced all references of 'digitalocean' with another name. I was careful to respect all case to conform to convention.
The problem I'm having now is that I appear to have a private gem.
I added it to my Gemfile with:
gem 'omniauth-private', :path => "/var/lib/gems/2.0.0/gems/omniauth-private-0.1.0"
I get no errors when I run 'bundle install'.
I was getting this error with 'rake db:migrate':
fatal: Not a git repository (or any of the parent directories): .git
I believe this was caused by a .gitignore file in my custom gem.
I deleted the .gitignore file and now I'm getting:
Devise::OmniAuth::StrategyNotFound: Could not find a strategy with name `Private'. Please ensure it is required or explicitly set it using the :strategy_class option.
This is the same error message I was getting before I figure out I needed to write n Omniuth strategy, so I think it means my gem is not being recognized.
So I'm not sure exactly what's going on. I think I'm struggling with this private gem. But it could be an OmniAuth problem too.
Anyone ever gotten a private OpenID Connect IdP working with OmniAuth?
I had the same "Could not find a strategy with the name..." with my custom Omniauth OAuth2 strategy.
I created a custom strategy as per these instructions https://github.com/intridea/omniauth-oauth2, and saved my file in config/initializers - this then loads the module on ruby boot.
I feel that I should be able to store this in the lib/ folder, but can't work out what the filename or folder structure should be!
You need to add:
require 'strategies/private'
to the top of config/devise.rb. This points to your strategy file at /lib/strategies/private.rb
The "fatal" error about "Not a git repo" comes from the fact that gems use 'git ls'. Just running "git init" should fix it. I did that and then committed to github.
"Could not find a strategy with the name..." error is fixed by loading the custom gem properly. I did that by adding this line to my Gemfile:
gem 'omniauth-private', :path => "/var/lib/gems/2.0.0/gems/omniauth-private-0.1.0
In your devise/initializers file check and make sure you have the correct name
of the auth you want to configure example:
config.omniauth :facebook, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
config.omniauth :private, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'

Does Rails 4.2 use secret_token?

Are both secret_key_base and secret_token needed for production in Rails 4.2? Setting neither causes the following exception message:
Missing secret_token and secret_key_base for 'production'
environment, set these values in config/secrets.yml
The 4.2 upgrade guide (http://railsapps.github.io/updating-rails.html) says this:
When you create a new Rails application using the rails new command, a
unique secret key is generated and written to the
config/initializers/secret_token.rb file.
But no such file was created when I generated my app, and there is no reference to secret_token in config/secrets.yml
I'm assuming that the error message is wrong, and that only secret_key_base is needed. When I run my app in production on my dev machine, it starts with just secret_key_base, but in Engineyard, setting secret_key_base (via an environment variable) isn't working. I still get the error.
The problem you're seeing on Engine Yard is because the secret_key_base environment variable doesn't (yet) exist by default. That's something we're working on. You can put that in place on your own using custom chef; I suggest talking to our support team for more info on that.
As for the actual error you're getting, I just tested a brand new Rails 4.2 app ("rails new foo") to see if it's generating secret_token.rb, which it's not. I think what you need here is to create config/secrets.yml, and that file should look like this:
development:
secret_key_base: somekey
test:
secret_key_base: someotherkey
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
Now, when you see ENV["SECRET_KEY_BASE"], that's where Engine Yard has a bit of a twist - we don't provide that out of the box yet. As long as your repo is private, you can hard-code something in there on your own. Otherwise, using custom chef could get you squared away by creating a secret key base and putting it in the wrapper script responsible for launching your app worker processes (so config/env.custom on our platform, for example).
Hope this helps.
4.2 does use the secret key and the link you posted has the solution you are looking for.
In an environment that doesn't end up with the secret key active, you need to generate it using rake secret then place the output from the console into your config/initializers/secret_token.rb file (you can make one if there isn't one).
You have the option to avoid using secrets.yml. Many people prefer to use another gem/procedure (e.g. figaro) for handling secret info. To simplify your life you could just put this information into the secret_token.rb file and move on - or you can learn the various other idiomatic ways of handling the situation.
At least Rails 4.2.2 gave me the same error, but setting the environment variable SECRET_KEY_BASE in the rails user's .bash_profile file solved the problem for me, so the bit about secret_token seems to be bogus -- a holdover from earlier versions, probably.
Generate the secret by commanding rake secret, then use the generated string in file .bash_profile like this:
export SECRET_KEY_BASE='the_output_of_the_rake_secret_command'
I'd suggest re-generating a new app with the latest version of Rails installed.
This file was auto-generated in my last project:
# config/secrets.yml
# Be sure to restart your server when you modify this file.
# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rake secret` to generate a secure secret key.
# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.
development:
secret_key_base: fooooo
test:
secret_key_base: fooooo
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
I'd also recommend that you compare the generated files via the railsdiff site (example: http://railsdiff.org/4.1.10.rc2/4.2.1.rc2) as it sounds like you're upgrading from an older version.

How to use secrets.yml for API_KEYS in Rails 4.1?

In one of my recent projects I started out by .gitignoring the files containing secrets and environment variables. So the entire project is committed to the repo except the files that contain third party secrets such as that of Stripe, Twitter API or Facebook Graph or internal api_keys, ala the ./config/initializers/secret_token.rb file.
Now I am at a point where the project is about to go live (excited!) and I need to port all the environment variables on to the production server using Capistrano i.e. cap production deploy.
[Edit 4: Yr, 2018]
In case of initializers/secret_token.rb it is clear that Rails 4.1 has a new way of handling secrets.yml file that pulls in the :secret_key_base value to the production server. Here, I recommend using the capistrano-secrets-yml gem which works right out of the box and is dead simple to use.
What is left is the way to carry other secrets like API_KEYS, APP_IDs etc. to the production server without checking any of those into the repo. How to do this, what is the most recommended/securest way or the best practices?
NOTE: I'll be editing the question as it progresses/I get more clarity.
EDIT1: Server is a Ubuntu/Linux VPS on DigitalOcean [Answer to Denise, below].
EDIT2: Can the env_variables/secrets be carried over to the server via secrets.yml? Secret_token for sessions is not the only secret after all! [Answered on Edit3]
EDIT3: Yes! It's possible to send in the API_keys via secrets.yml according to this blog. Will share my findings in sometime. :-)
First rule: DO NOT CHECK-IN secrets.yml into the repo.
All right, here's how a secret.yml would look:
development:
secret_key_base: 6a1ada9d8e377c8fad5e530d6e0a1daa3d17e43ee...
# Paste output of $ rake secret here for your dev machine.
test:
secret_key_base: _your_secret_ as above
production:
secret_key_base: <%= secure_token %>
STRIPE_PUBLISHABLE_KEY: 'Put your stripe keys for production'
STRIPE_SECRET_KEY: 'Put actual keys for production here'
FB_APP_SECRET: 'same as above'
FB_CALLBACK_URL: 'FB url here'
FB_CALLBACK_UPDATE_URL: 'FB url here'
GOOGLE_KEY: 'Put your keys for production'
GOOGLE_SECRET: 'same as above'
TWITTER_KEY: 'same as above'
TWITTER_SECRET: 'same as above'
TWITTER_USERNAME: 'same as above'
LINKEDIN_KEY: 'same as above'
LINKEDIN_SECRET: 'same as above'
Note the secure_token up there in the production: block. On production server I'm using an initializer to dynamically generate secret_tokens on-the-fly.
sidenote: be careful about spaces and tabs inside the .yml file. It must be properly formatted and spaced (such as having a space after the ':' symbol).
To set it up on production you could then scp the file directly from your local or use the capistrano-secrets-yml gem.
This will not work. See an updated method as per #OddityOverseer's answer below.
To access the environment variables in your app environments/production.rb use:
FB_APP_SECRET = ENV['FB_APP_SECRET']
FB_CALLBACK_URL = ENV['FB_CALLBACK_URL']
FB_CALLBACK_UPDATE_URL = ENV['FB_CALLBACK_UPDATE_URL']
GOOGLE_KEY = ENV['GOOGLE_KEY']
GOOGLE_SECRET = ENV['GOOGLE_SECRET']
TWITTER_KEY = ENV['TWITTER_KEY']
TWITTER_SECRET = ENV['TWITTER_SECRET']
TWITTER_USERNAME = ENV['TWITTER_USERNAME']
LINKEDIN_KEY = ENV['LINKEDIN_KEY']
LINKEDIN_SECRET = ENV['LINKEDIN_SECRET']
UPDATED August-2016:
To access the environment variables in your app environments/production.rb use:
FB_APP_SECRET = Rails.application.secrets.FB_APP_SECRET
FB_CALLBACK_URL = Rails.application.secrets.FB_CALLBACK_URL
FB_CALLBACK_UPDATE_URL = Rails.application.secrets.FB_CALLBACK_UPDATE_URL
GOOGLE_KEY = Rails.application.secrets.GOOGLE_KEY
GOOGLE_SECRET = Rails.application.secrets.GOOGLE_SECRET
TWITTER_KEY = Rails.application.secrets.TWITTER_KEY
TWITTER_SECRET = Rails.application.secrets.TWITTER_SECRET
TWITTER_USERNAME = Rails.application.secrets.TWITTER_USERNAME
LINKEDIN_KEY = Rails.application.secrets.LINKEDIN_KEY
LINKEDIN_SECRET = Rails.application.secrets.LINKEDIN_SECRET
That's about it.
Rails.application.secrets.key_name
One way to do it is to store those secret keys in environment variables. How to set an environment variable is different depending on what operating system you're on. For a linux machine, usually you're editing a .bashrc or .bash_profile file in your home directory and adding a line that looks like:
export API_KEYS=apikeygoeshere
You'll have to edit the file for whatever user will run rails.
Then in production.rb, you can refer to those environment variables as:
ENV["API_KEYS"]
Another option is to use a ruby gem that essentially takes care of that for you, like figaro. The way it works is that you create another file that you don't check in and figaro takes care of setting them up as environment variables, which you can then refer to in your development.rb/production.rb scripts using the ENV["API_KEYS"] above. Because you aren't checking in the file that has all of the environment variables, you'll have to find some way to get that file onto whatever machines are running the code.
I know this question is specific to Rails 4.1, but those who upgrade to Rails 5.1 it now includes built in secret generation. Which seems a much better way to handle sensitive data in your rails app.
See: http://edgeguides.rubyonrails.org/5_1_release_notes.html#encrypted-secrets
A nice approach to deal with different environments would be to:
EDITOR=vim rails credentials:edit
development:
cloudinary:
cloud_name: dxe1hjkoi
api_key: 361019726125669
api_secret: Cn6tHfSf019278367sZoO083eOI
production:
cloudinary:
cloud_name: oiajsu98u
api_key: 091828812791872
api_secret: KJS98182kjaksh89721jhS9812j
Then use it as:
Cloudinary.config do |config|
config.cloud_name =
Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :cloud_name)
config.api_key =
Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :api_key)
config.api_secret =
Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :api_secret)
end

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.

Making ENV variables accessible in development

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.

Resources