I'm trying to setup SMS texting with Twilio. I'm going thru their guide here: https://www.twilio.com/blog/2017/12/send-sms-ruby-rails-5-coffee.html but am running into an issue with the ERB in credentials.yml.enc not being parsed for the twilio credentials.
I've tried adding the credentials without using the ERB recommended in the guide, which works, but which would stop me from being able to define these as environment variables.
# config/credentials.yml
twilio_account_sid: <%= ENV.fetch("TWILIO_ACCOUNT_SID", "XXXXXXX") %>
twilio_auth_token: <%= ENV.fetch("TWILIO_AUTH_TOKEN", "XXXXXXX") %>
twilio_phone_number: <%= ENV.fetch("TWILIO_PHONE_NUMBER", "XXXXXXX") %>
# config/initializers/twilio.rb
Twilio.configure do |config|
config.account_sid = Rails.application.credentials.twilio_account_sid
config.auth_token = Rails.application.credentials.twilio_auth_token
end
I ran this in the console:
client = Twilio::REST::Client.new
client.messages.create({
from: Rails.application.credentials.twilio_phone_number,
to: '+11231234',
body: 'Hello there! This is a test'
})
I end up getting:
URI::InvalidURIError (bad URI(is not URI?): https://api.twilio.com/2010-04-01/Accounts/<%= ENV.fetch("TWILIO_ACCOUNT_SID", "XXXXXXX") %>/Messages.json)
I'm guessing this is because Rails 5.2's new encrypted credentials.yml file doesn't get processed with ERB. Anyone have a good workaround? Am I missing something?
Thanks!
I think you're misusing the config/credentials.yml.enc file.
Before that feature, people would use environment variables to store secrets (since it would be bad practice to commit them into your code repository). This was a hassle.
So then, Rails 5.2 introduced the encrypted store. The point is that you don't anymore have to manage environment variables, you just commit directly your secrets into your codebase (but encrypted of course).
So either you write directly your secrets into the config/credentials.yml.enc file, either you want to keep them in environment variables and then just use an initializer file in config/initializers/. Don't do both at the same time.
Related
I have a problem I am following step by step this tutorial to include the gem stripe to my rails application : https://stripe.com/docs/checkout/rails
But I have an issue when I launch my payment:
you did not set a valid publishable key. Call Stripe.setPublishableKey() with your publishable key.
The tutorial I am following doesn't use this method Stripe.setPublishableKey() and it seems working as well ...
I am using a .env file to get the API keys and I use the test keys from the tutorial.
Any idea for the solution ?!
Thank you very much :) If you need more information please tell me
My actual code is a copy/paste from the tutorial I use.
Edit 1
I don't understand why but it working when I push the project on Heroku ... but I still don't understand why it's failing on local
From the guide you linked:
The application makes use of your publishable and secret API keys
to interact with Stripe. An initializer is a good place to set these
values, which will be provided when the application is started.
Add the following to config/initializers/stripe.rb:
Rails.configuration.stripe = {
:publishable_key => ENV['PUBLISHABLE_KEY'],
:secret_key => ENV['SECRET_KEY']
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]
These keys values are pulled out of environmental variables so as not
to hardcode them. It’s best practice not to write API keys into your
code, where they could easily wind up in source control repositories
and other non-private destinations.
Have you added that data into config/initializers/stripe.rb ?
If so, you may need to restart your server as the files in config/initializers are only loaded on server startup
I am using a .env file to get the API keys and I use the test keys from the tutorial.
Rails don't autoload environment variables from .env file. So, in the tutorial author set required variables from the console before server start, but you use .env file.
To fix that use gem dotenv-rails: just add in your Gemfile(not need add the same lines as in gem description)
I was able to overcome the same type of error in another tutorial by changing the last line of the stripe.rb file to:
Stripe.api_key = Rails.application.credentials.stripe[:secret_key]
with the key being saved in the credentials.yml.enc file in rails 5.2
I have a project configured to use Rails encrypted secrets. Everything works fine until I try to access a secret within the production.rb environment file.
I found that if I try to access something like Rails.application.secrets.smtp_user_name within the configure block it wipes out all of the encrypted secrets (I'm only left with things in secrets.yml ... which I'm not using). Example:
Loading production environment (Rails 5.1.2)
irb(main):001:0> Rails.application.secrets
=> {:secret_key_base=>nil, :secret_token=>nil}
If I remove the attempt to access the secrets it works correctly:
irb(main):001:0> Rails.application.secrets
=> {:secret_key_base=>"...", :smtp_user_name=>"...", :smtp_password=>"...", :secret_token=>nil}
I'm currently working around it by using two configure blocks in production.rb as follows:
# This is hacky, it needs to come before the second configure block where
# the encrypted secrets are used.
Rails.application.configure do
config.read_encrypted_secrets = true
end
Rails.application.configure do
... stuff that uses Rails.application.secrets, like ActionMailer
end
Anybody else faced this and possibly have a more correct way to work around it?
It makes sense why this is happening (Rails doesn't know to load the encrypted secrets because we haven't told it to you), but I'm thinking there must be a better way to deal with it.
Update
This nailed me again 9 months later. To be clear, if you reference Rails.application.secrets BEFORE calling config.read_encrypted_secrets = true you will cache empty secrets and not be able to access any of the values in secrets.yml.enc!
In my case I had tried to configure Paperclip S3 credentials in application.rb while my config.read_encrypted_secrets = true was set in production.rb. Result was devise.rb blowing up trying to read a secret for the key base, all because in application.rb I had effectively cached nil secrets.
here is bug report related to your issue:
https://github.com/rails/rails/issues/30362#issuecomment-326821656
In general even if you have all things set up properly you need check also order how your application loads secrets. If your application ask first for Rails.application.secrets and then set proper flag... Rails.application.secrets will cache version without secrets... and Secrets from secret.yml.enc will not be merge.
For the first time I have a question to an answer I already solved, this is more about WHY my little fix solved it in the first place.
I'm following the Learn Rails book tutorial by Daniel Kehoe, creating an application that is supposed to subscribe people to a MailChimp list. I'm using the Gibbon gem, and in the book this is (part of) the code in the model used to set the variables:
def subscribe
mailchimp = Gibbon::API.new(Rails.application.secrets.mailchimp_api_key)
result = mailchimp.lists.subscribe({
:id => Rails.application.secrets.mailchimp_list_id,
<more code here for email and stuff>
end
My secrets.yml file for the variables in question looks like this:
mailchimp_api_key: <%= ENV["MAILCHIMP_API_KEY"] %>
mailchimp_list_id: <%= ENV["MAILCHIMP_LIST_ID"] %>
And, since I'm on Windows, I set the actual value of them in application.yml: [Edit: As people have pointed out, this comes from the Figaro gem and may or may not be part of the tutorial]
MAILCHIMP_API_KEY: mysecretkey
MAILCHIMP_LIST_ID: mysecretid
This, I should note, works perfectly fine locally. I can run my server and subscribe. However, pushing it to Heroku and setting the ENV variables via heroku config:set MAILCHIMP_API_KEY=mysecretkey and the same thing for MAILCHIMP_LIST_ID, it doesn't work. More specifically, it returns the error Invalid Mailchimp List ID:.
So, despite setting it and checking that it is actually set, it has no value at all for the List ID.
I fixed the problem by searching through Heroku's own help text on Config Vars, where it recommends the following: "Set up your code to read the vars at runtime. For example, in Ruby you access the environment variables using the ENV['KEY'] pattern"
I changed my code in the model, so instead of using Rails.application.secrets.mailchimp_list_id it's now this:
def subscribe
mailchimp = Gibbon::API.new(Rails.application.secrets.mailchimp_api_key)
result = mailchimp.lists.subscribe({
:id => ENV['MAILCHIMP_LIST_ID'],
<more code here for email and stuff>
end
And, what do you know, it works in Heroku (and locally)! Why, though? I mean, it did understand the same kind of code for the API Key, but not for the list ID, which seems strange to me. Also, how come the book in question doesn't reflect on this? The author seems willing to update it very regularly, and I see him answer questions on it with an almost religious dedication. Am I the only one to run into this problem?
Edit: Solved below. I feel a bit silly now, and as usual things have a very easy solution. I will note that the book did in fact have the keys duplicated into production in the secrets.yml file, I just missed that part, probably because I had to find an alternative solution to the whole problem of environmental variables and using the Figaro gem. If I have any criticism of the book, it's that it doesn't cater to us poor Windows users. :)
Figaro creates the config/application.yml file and according to its documentation, adds it to your .gitignore:
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!
This is done to prevent sensitive secrets (like passwords and salts) from being committed into your Git repository, where those secrets would be compromised.
Figaro does have a feature which you can use to transfer all the settings in application.yml to Heroku at once by running
figaro heroku:set -e production
As it turns out, the config/secrets.yml did not repeat the Mailchimp keys in the production section. To fix this, it should look like this:
development:
mailchimp_api_key: <%= ENV["MAILCHIMP_API_KEY"] %>
mailchimp_list_id: <%= ENV["MAILCHIMP_LIST_ID"] %>
production:
mailchimp_api_key: <%= ENV["MAILCHIMP_API_KEY"] %>
mailchimp_list_id: <%= ENV["MAILCHIMP_LIST_ID"] %>
Had almost the exact same error, but a slightly different cause.
Double check to make sure your secrets.yml is properly configured. Mine looked like the following:
...
production:
mailchimp_api_key: <%= ENV["MAILCHIMP_API_KEY"] %>
mailchimp_list_id: ENV["MAILCHIMP_LIST_ID"]
...
I didn't see the missing <%= %> after scanning the file MANY times, even after I ended up on this page. I'll leave this answer up in case Google sends others with the same typo here.
Have not played with Rails in ages so walking through the Learn Ruby on Rails tutorial which is excellent.
I'm having issues with google authentication, the example code calls the config/secrets.yml variables (which are read from ENV in the shell) from the app/models/contact.rb model update_spreadsheet method below
def update_spreadsheet
connection = GoogleDrive.login(Rails.application.secrets.gmail_username, Rails.application.secrets.gmail_password)
I have the ENV variable set via my ~/.bash_profile and have confirmed using the following code I can make things work, but it's not the example code so I'm just hacking.
def update_spreadsheet
connection = GoogleDrive.login(ENV["GMAIL_USERNAME"], ENV["GMAIL_PASSWORD"])
I can make it work but, I wanted to follow the tutorial and know how to troubleshoot better. if anyone has a pointer it would be appreciated.
Inside my config/secrets.yml file looks like:
development:
gmail_username: <%= ENV["GMAIL_USERNAME"] %>
gmail_password: <%= ENV["GMAIL_PASSWORD"] %>
Thank you
Rails reads secrets.yml but getting the value from secrets.yml is little different then how you had used it, check the code below:
secrets.yml:
development:
secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
some_api_key: SOMEKEY
This is how you can access the value:
Rails.application.secrets.some_api_key returns SOMEKEY
I was having the same issue here and followed all the instructions here and was still experiencing difficulties. My gmail password does not have any special characters, but in my .bash profile I just tried putting single quotes around the contents of the double quotes for both GMAIL_USERNAME and GMAIL_PASSWORD, and it finally worked!
The above solution did not work for me. However, I found the solution on How do I use variables in a YAML file?
My .yml file contained something like:
development:
gmail_username: <%= ENV["GMAIL_USERNAME"] %>
gmail_password: <%= ENV["GMAIL_PASSWORD"] %>
In your .rb file,access the yml file as:
template = ERB.new File.new("path/to/config.yml.erb").read
processed = YAML.load template.result(binding)
So when you introduce a scriptlet tag in .yml file, it is more of erb template. So read it as a erb template first and then load the yml as shown above.
I want to install New Relic on one of my open source rails applications (v 3.2.12). I don't want to have the license key in the repo. I'd like to load it with something like ENV.
By default that's loaded in the newrelic.yml file.
Where is that YAML file loaded? I guess I could manually merge it with a hash that loads the license from the ENV hash.
Any hints on how to do that?
I use the Figaro gem to handle secret keys with ENV environment variables, similar to you. For New Relic, I have:
config/application.yml (.gitignored and not pushed to source control)
# ...
NEW_RELIC_LICENSE_KEY: {{MY_KEY}}
which is then referenced in config/newrelic.yml:
# ...
license_key: <%= ENV['NEW_RELIC_LICENSE_KEY'] %>
A file called config/application.example.yml gets pushed up to the source code repo with instructions to put your own license key in:
config/application.example.yml
# ...
NEW_RELIC_LICENSE_KEY: # put your license key here
Also see this StackOverflow Q&A for more details:
What should be removed from public source control in Ruby on Rails?
I got a useful answer on IRC. newrelic.yml is erb interpolated. Meaning I can just add <%= ENV["NEWRELIC"] %> to the yml file.
Yes to the above answers. also, If you're on Heroku. After installing the NewRelic Addon, you can download newrelic.yml file and change
license_key: to:
license_key: <%= ENV['NEW_RELIC_LICENSE_KEY']%>
This will use the NEW_RELIC_LICENSE_KEY env variable set by the NewRelic addon
This doesn't necessarily answer the exact question you are asking, but this may solve your end goal.
Typically for this type of situation I add the newrelic.yml file to .gitignore and then create a newrelic.yml.example with all the non sensitive fields filled out and a place holder for the key.
This way I can add it into my newrelic.yml file for development and also have the template checked in for others use.