My Rails app uses OAuth authentication. For production credentials, I use dotenv gem. config/secrets.yml:
production:
secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
facebook_app_id: <%= ENV['FACEBOOK_APP_ID'] %>
facebook_app_secret: <%= ENV['FACEBOOK_APP_SECRET'] %>
For testing, I use specially registered Facebook app that has "redirect_uri" to http://localhost.
Should I use the same approach for "development" section or I can write creds of apps that are registered for testing? How I understand no one can use it (for fishing websites) because there is "redirect_uri" that pointing on "localhost" in the settings of the app.
It is recommended not to expose the creds, even for the testing. You should follow the same approach for both dev and test. Also, add your file containing all the credentials to .gitignore
Related
I have a Rails 6 application. In my credentials file, I have both development and production API keys. I want to be able to hide the production API keys since some developers don't need access to the credentials.
In previous versions of Rails, I could grab an environment variable using <%= ENV["MY_VAR"] %> and place that in the secrets.yml file. However, Rails credentials doesn't support executing Ruby in the yml file which makes sense because it's encrypted but this now puts limitations on the ability to prevent other developers from accessing production API keys. Is there anyway around this without hardcoding ENV["MY_VAR"] throughout the Rails app? Here is ultimately what I want to accomplish within my credentials file.
development:
aws: 11111111
production:
aws: <%= ENV["AWS_SECRET"] %>
You can generate credential file per environment
rails credentials:edit --environment development
rails credentials:edit --environment production
This will create the credentials file
config/credentials/development.yml.enc and config/credentials/production.yml.enc, and
encryption keys config/credentials/development.key, config/credentials/production.key
So you can share development key with other developers without need to share production.key
Checkout this commit for more details: https://github.com/rails/rails/pull/33521
I have implemented a Cloudinary type in one of my models, but get this error back when I try and save it to Cloudinary:
Image upload failed - Invalid Signature
ea4401c2ebf292208d28f9dc88c5ff1c4e73761d.
String to sign - 'tags=trial-images_image,trial-
images_image_55ba9896c6d05b8704802f0a,dev×tamp=1438292137'.
I'm not sure what to do about it, anyone experience this?
You should make sure to calculate the signature correctly. Specifically, you should sign both the tags and the timestamp (including your api_secret of course).
I had the exact same issue.
Please double check that you have the configuration parameters(cloud name, api key, api secret) correctly set up. They can be found by going to the management console on your cloudinary account. (Dashboard > Account Details).
As per their documentation:
(http://cloudinary.com/documentation/rails_additional_topics#configuration_options)
Configuration parameters can be globally set using a cloudinary.yml configuration file, located under the config directory of your Rails project. etc...
Here's an example of a cloudinary.yml file:
production:
cloud_name: "sample"
api_key: "874837483274837"
api_secret: "a676b67565c6767a6767d6767f676fe1"
etc...
... Another configuration option is to use a Rails initializer file. You can place a file named cloudinary.rb in the /config/initializers folder of your Rails project. Here's a sample initializer code:
Cloudinary.config do |config|
config.cloud_name = 'sample'
config.api_key = '874837483274837'
config.api_secret = 'a676b67565c6767a6767d6767f676fe1'
config.cdn_subdomain = true
end
One last configuration option allows you to dynamically configure the Cloudinary library by defining the CLOUDINARY_URL environment variable. The configuration URL is available in the Management Console's dashboard of your account. When using Cloudinary through a PaaS add-on (e.g., Heroku), this environment variable is automatically defined in your deployment environment. Here's a sample value:
CLOUDINARY_URL=cloudinary://874837483274837:a676b67565c6767a6767d6767f676fe1#sample
How I actually solved the issue
I solved the issue by adopting (and slightly modifying) the first option, which is to create cloudinary.yml file in config directory and write the following code:
(config/cloudinary.yml)
development:
cloud_name: <%= ENV["CLOUD_NAME"] %>
api_key: <%= ENV["API_KEY"] %>
api_secret: <%= ENV["API_SECRET"] %>
test:
cloud_name: <%= ENV["CLOUD_NAME"] %>
api_key: <%= ENV["API_KEY"] %>
api_secret: <%= ENV["API_SECRET"] %>
production:
cloud_name: <%= ENV["CLOUD_NAME"] %>
api_key: <%= ENV["API_KEY"] %>
api_secret: <%= ENV["API_SECRET"] %>
Please note that the configuration parameters (cloud name, api key, api secret) are set as environmental variables(CLOUD_NAME, API_KEY, API_SECRET) to prevent them from being exposed when the code is shared publicly. (You don't want to hard code the sensitive information)
You can set environmental variables in bash by editing .bash_profile file, which is located (and hidden) in the home directory:
(.bash_profile)
.....
export CLOUD_NAME="your cloud name"
export API_KEY="your api key"
export API_SECRET="your api secret"
.....
You can check that these environmental variables are correctly set by typing echo $CLOUD_NAME, for example, in your terminal.(You may need to quit and restart the terminal). If it's successful, the output will look something like:
echo $CLOUD_NAME
> your cloud name
Finally, if you are planning to deploy your app to heroku, you may also want to add cloudinary as an addon, which is free for a starter option, by typing the following command in the terminal:
heroku addons:create cloudinary:starter
Putting this all together might solve your issue.
Last but not least, I found the following blog post quite useful:
http://www.uberobert.com/rails_cloudinary_carrierwave/
It explains how you can use cloudinary and carrierwave to upload and manipulate the images on your application.
Hope it helps!
I am using Rails 4.1.1 and ruby 2.0.0
I've currently ignored my secrets.yml file to my gitignore for github.
secrets.yml
development:
secret_key_base: numb3r57ndl3tt3r5
test:
secret_key_base: differentnumbersandletters13531515
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE'] %>
If this production key is dynamic, where does it read it from? Where do we provide that info? How does that info get to heroku without getting to github?
I already have a secret key environment variable in my heroku app's settings.
I think it was created when I used the heroku_secrets gem https://github.com/alexpeattie/heroku_secrets to run the rake comment rake heroku:secrets RAILS_ENV=production
Can someone explain the conceptual steps, as well as the practical steps on how to utilize secrets.yml properly without exposing secret keys to the public?
If you can also go over with adding another secret key for a different API for instance, that would be much appreciated as well.
I'd like to understand what is happening in the steps in the explanation, rather than something like "do this, do this, do this". Also, if there is code, please specify which file it should be put in, instead of just giving the code, and assuming the reader will know where it goes just based on the code alone (stern look at heroku guide writers)
Thanks! =]
If you use this key <%= ENV["SECRET_KEY_BASE'] %>
On your local machine you can set environment vars in your shell, like (bash or zsh)
export SECRET_KEY_BASE="yourkeybasehere"
And simulate that you run on production (but at your local machine) like
RAILS_ENV=production rails s
However, deploying on Heroku, you can use what they call config vars, by running heroku config:set command for your app.
heroku config:set SECRET_KEY_BASE=yourkeybasehere
Then the Rails app will populate this config var into secret.yml
production:
secret_key_base: yourkeybasehere
Hope this explains thing you need to understand.
Though, if you would like to play and test.
One option is trying to edit your app/views/layouts/application.html.erb file and put the config var you want to display, for instance USERNAME config var
<!DOCTYPE html>
<html>
<head>
<title><%= ENV['USERNAME'] %></title>
</head>
<body>
<%= yield %>
</body>
</html>
Then deploy to heroku and run
heroku config:set USERNAME=gwho
You should see 'gwho' at the page title.
More details about Heroku config vars: https://devcenter.heroku.com/articles/config-vars
More details about Rails 4.1 secrets.yml: http://edgeguides.rubyonrails.org/4_1_release_notes.html#config/secrets.yml
Here's a (hopefully simple) step by step guide FOR HEROKU that should be performed prior to pushing files (secrets.yml) to GitHub, or another host.
*I am not an expert on this topic but this worked well for me and seems like a good solution. It combines info from answers to this question as well as answers to this question (How do you keep secrets.yml secret in rails?) to provide a simple guide :)
1) Copy secrets.yml to another file named secrets_backup.yml
you should now have two files with the same content as secrets.yml
2) Add secrets_backup.yml to your .gitignore
3) Change the text in secrets.yml to the following
development:
secret_key_base: <%= ENV["SECRET_KEY_BASE_DEV"] %>
test:
secret_key_base: <%= ENV["SECRET_KEY_BASE_TEST"] %>
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
4) cd to your rails project folder on the command line
5) In the terminal type heroku config:set SECRET_KEY_BASE_TEST=<pasted key>,
where <pasted key> should be copied and pasted from the test: secret_key_base:<key> which is in secrets_backup.yml
6) In the terminal type heroku config:set SECRET_KEY_BASE_DEV=<pasted key>,
where <pasted key> should be copied and pasted from the development: secret_key_base:<key> which is in secrets_backup.yml
7) My secrets.yml file already had the SECRET_KEY_BASE instead of the actual key, so I suspect yours will too. But if not, set the SECRET_KEY_BASE variable as the other two were set above.
8) Push your repo to GitHub and Heroku
9) Smile because you're the G.O.A.T and show off your sweet website!
New to rails. Followed Hartl's tutorial where he uses this code to dynamically generate secret token for config/initializers/secret_token.rb
require 'securerandom'
def secure_token
token_file = Rails.root.join('.secret')
if File.exist?(token_file)
# Use the existing token.
File.read(token_file).chomp
else
# Generate a new token and store it in token_file.
token = SecureRandom.hex(64)
File.write(token_file, token)
token
end
end
SampleApp::Application.config.secret_key_base = secure_token
I'm trying to follow the new Rails 4.1 way by using secrets.yml, and delete the secret_token.rb:
development:
secret_key_base: 79c1389c2fadc5a5a1918a5104ab34eb700c
test:
secret_key_base: fdb4edcde14173d62963705ca4d7876b5307790924
production:
secret_key_base: 85172605030a8225c083d886d066da2cb4aac1f0
But I think you cannot run ruby script like the one in secret_token.rb in a yml file. How would you have rails dynamically generate the secret tokens in secret. How should this be done? What is best practice?
Given a function secret_token whose only job is to generate a new token string each time one's application accesses the secrets.yml file, cookies and most likely other session-like behavior will not work correctly as the secret token changes each call to the function.
The preferred & secure way is to use any old secret key in the secrets.yml file for development and test environments (you can generate a secret string by issuing rake secret on the command line), then use an environment variable that your production server knows, so the secrets.yml file looks like:
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
For example, on Heroku, use heroku config:set SECRET_KEY_BASE="insert key here" to set the environment variable and there you have it. Don't be afraid to check the secrets.yml file into scm...as long as you haven't saved your production key to the file (and are instead using the environment variable method I just described), checking the file into scm poses no threat.
You can actually run ERB code in YML files. Something like:
development:
secret_key_base: <%= secret_token %>
should work (if whatever process reads the YML file can access the secure_token method).
There are lots of secrets that apps have that need to be secured in production when running in public cloud and PaaS environments. Common one is database.yml entries for mysql user and password, but there can be others. Your Google App secret, facebook app secret,... the list goes on. There are no clear way of securing these essentially configuration parameters. You DO NOT want to put these in a file as there is no guarantee who will have access to it.
In Heroku you can specify things via environment variables. In Cloudbees (a Java PaaS) you can specify these as Java System properties. Both Heroku and Cloudbees have a commandline utility for uploading this configuration parameters but there is no support for making this work both in development and production easily.
Question is how do you configure your parameters so that you can develop easily in development but not have the production secret be available in development
Ideally there would be a gem that will work in ruby and jruby environment and PaaS that will allow me to specify me secrets in a YML file that has development settings in development but actual production secrets pulled in from ENV or java.lang.System.getProperty.
##
# file: config/secure_config.yml
development:
db:
user_id: 'dev_mysql_user'
password: 'my_dev_pwd'
google:
app_id: 'xxxxx' # this is the secret for the dev app so it can be visible
app_secret: 'xxxxx'
# ...
production:
db:
user_id: <%= get_secure_config %>
password: <%= get_secure_config %>
google:
app_id: <%= get_secure_config %>
app_secret: <%= get_secure_config %>
Where the get_secure_config helper gets the value from ENV or java.lang.System.getProperty in case of Ruby or jRuby. The finally you can use them in your app as needed. For example in database.yml or in the devise code to authenticate using google.
# config/database.yml
# ...
production:
adapter: mysql2
username: <%= SecureConfig.db.user_id %>
password: <%= SecureConfig.db.password %>
And then for extra coolness the gem should also give me an executable that allows me to push the config to my PaaS
~/work/myproject> bundle exec secure_config -push_to_heroku
or
~/work/myproject> bundle exec secure_config -push_to_cloudbees
Check out Figaro. It's almost exactly what you're after.
You place your sensitive data in a git-ignored YAML file, which are then made available to the app in ENV. It also provides a rake task for configuring your Heroku instance with the variables.
As Daniel Wright suggested above Figaro is great! It does every thing I need for ruby on rails. I needed the same support on JRuby on rails and properties via JVM system properties for Cloudbees PaaS service as well. I have forked Figaro and made these extensions and sent a pull request to laserlemon/Figaro. In the mean time you can pull it using git directive in your gem file.
gem 'figaro', '0.4.2', :git => "git://github.com/RedMicaInc/figaro.git"
Main differences are documented below
How does it work?
It works really well.
There are a few similar solutions out there, and a lot of homegrown attempts. Most namespace your configuration under a Config (or similar) namespace. That's fine, but there's already a place to describe the application environment… ENV!
ENV is a collection of simple string key/value pairs and it works just great for application configuration.
These configuration parameters are also then made available as properties of FigaroSettings object. So if you had a property called MY_PROP you can use it in your code or configuration files using FigaroSettings.my_prop or FigaroSettings.MY_PROP
For JRUBY based applications properties stored in JVM system properties are also available in a similar manner. For instance if you had a property called MY_JAVA_PROP it is accessible as FigaroSettings.MY_JAVA_PROP. Java properties are case sensitive.
As an added bonus, this is exactly how apps on Heroku or Cloudbees are configured. So if you configure your Rails app using ENV, you're already set to deploy to Heroku. For Cloudbees you can use ENV or JVM properties similarly using FigaroSettings.<property>
How does it work with Cloudbees?
Cloudbees provides application configuration in a similar manner.
Typically, to configure your application parameters accessible via JVM system properties, you would do the following from the command line using the cloudbees sdk:
cloudbees config:set -a <my_app> PUSHER_APP_ID=8926
cloudbees config:set -a <my_app> PUSHER_KEY=0463644d89a340ff1132
cloudbees config:set -a <my_app> PUSHER_SECRET=0eadfd9847769f94367b
But Figaro provides a rake task to do just that! Just run:
rake figaro:cloudbees
Optionally, you can pass in the name of the Cloudbees app:
rake figaro:cloudbees[my-awesome-app]
If you just want to see the commands used you can run rake figaro:heroku_test