Declaring In-Line Secret Keys in Ruby On Rails - ruby-on-rails

I'm learning Ruby On Rails. I'm trying to use the aws-s3 gem to access Amazon S3. One line of my controller code reads:
AWS::S3::Base.establish_connection!(
:access_key_id => 'myrealaccesskeyishere',
:secret_access_key => 'myrealsecretkeyishere'
)
I've noticed that if I make an error, sometimes rails will come back and show a few lines of code where it thinks the error might be. Should I not be writing these out in the .rb controller files like this? Am I potentially risking my secret key? If so, how should I be doing this instead?

You should put this in an initializer. Place it in config/intializers/amazon_s3.rb
Is there a reason you are putting this code directly in the controller?

Related

Ruby on rails - Stripe : "you did not set a valid publishable key"

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

RoR, Fog: Getting Started with Fog

I just installed the gem asset_sync and I am trying to get set up with my AWS account. When I run bundle exec rake assets:precompile I get the following errror:
AssetSync::Config::Invalid: Fog provider can't be blank, Fog directory can't be blank
I understand the simply reason that I am getting this error, namely that I havent pushed the Fog provider or directory to heroku. What I am stumped about is where to put the Following code (Taken from the Fog README). In config/initializers/fog.rb? Is this all I need to do to start using fog, other than installing the gem?
require 'rubygems'
require 'fog'
# create a connection
connection = Fog::Storage.new({
:provider => 'AWS',
:aws_access_key_id => YOUR_AWS_ACCESS_KEY_ID,
:aws_secret_access_key => YOUR_AWS_SECRET_ACCESS_KEY
})
# First, a place to contain the glorious details
directory = connection.directories.create(
:key => "fog-demo-#{Time.now.to_i}", # globally unique name
:public => true
)
not a problem, getting started tends to be the hardest part.
The answer is, it depends. I'd actually venture to say it would be best to put this in your environment based initializers, ie config/init/development or config/init/production, etc. Relatedly, you probably will not want to generate a new directory every time you start your app (there is an account level limit of 100 total I believe). So you might want to either set a key for each environment for that create or simply create the directory somewhere outside the initializers (and within the initializer you can assume it exists).
If you want to use that directory directly, you'll still need to create a reference, but you can create a local reference without making any api calls with #new like this:
directory = connection.directories.new(:key => ...)
As for asset_sync, it needs those keys and a reference to the directory key, which you will probably want to provide via ENV vars (to avoid checking your credentials into version control). You can find details on which keys and how to set them here: https://github.com/rumblelabs/asset_sync#built-in-initializer-environment-variables (the readme also describes how to do it via initializers, but that probably isn't the best plan).
Hope that helps!

aws-s3 gem will connect in application.rb but fails on subsequent uses of API methods

My application.rb:
S3_CREDENTIALS = YAML.load(File.read(File.expand_path(Rails.root.join("config","s3_credentials.yml"))))["production"]
# AWS::S3::Base.establish_connection! S3_CREDENTIALS['connection']
AWS::S3::Base.establish_connection!(
:access_key_id => S3_CREDENTIALS['access_key_id'],
:secret_access_key => S3_CREDENTIALS['secret_access_key'],
:persistent => true, # from http://www.ruby-forum.com/topic/110842
s3_credentials.yml:
production: &defaults
access_key_id: <%=ENV['AWS_ACCESS_KEY_ID']%>
secret_access_key: <%=ENV['AWS_SECRET_ACCESS_KEY']%>
persistent: true
I launch my web server and in my customers_controller I check for the connection:
Rails.logger.info("S3 service connected? " + AWS::S3::Base.connected?.to_s)
And the log says it's connected:
S3 service connected? true
So I know the following:
My env variables are correct.
My initializer and yml files are correct.
Gem is fine
So then I do something simple like this in the controller:
#documents = Service.buckets()
I reload the page and here we go:
AWS::S3::InvalidAccessKeyId in CustomersController#edit
The AWS Access Key Id you provided does not exist in our records.
THE KICKER -
When I print my secret key and access key in plain text into the application.rb file (get rid of the s3_credentials.yml file, just put the keys into the appropriate lines in the application.rb file - I won't get the error.
Why is it that using environment variables with the aws-s3 gem fails spectacularly using the API methods but loads just fine? The keys can't be good and bad at the same time. It wouldn't connect at all if the keys were wrong, correct?
What I found after hours is that there is something inherently borked in the version of aws-s3 gem that I'm using. Period. There is no solution other than to fix the gem, and I don't have time to go that far. I checked the source and when to the connection.rb module to find where it's calling up the keys. It uses his own extract_keys! method, and after poking at that for a while I gave up.
I ended up using the aws-sdk gem. Config is a bit different than with aws-s3, but same ENV vars and it is all working now.
I submitted a request to the owner of the aws-s3 gem to take a look. But I don't know how active that gem is any longer.
aws-sdk is overkill when all you need is some simple access to S3 stuff, but whatever. It works.
Here is some of the config just in case someone finds it useful in the future:
aws.yml:
development: &defaults
access_key_id: <%=ENV['AWS_ACCESS_KEY_ID']%>
secret_access_key: <%=ENV['AWS_SECRET_ACCESS_KEY']%>
persistent: true
# bucket: YOUR BUCKET
max_file_size: 10485760
acl: public-read
NOTE : The <%= %> syntax above doesn't have spaces. Normally I format it with spaces. This might sound crazy to some, but if you put spaces between the tag and the value inside you will get an error from Amazon saying some crazy stuff about only requiring a single space. This drove me nuts. The leading or trailing space shouldn't matter! But it did. I took the spaces out - started working. Call me crazy. I spent hours battling this so you wouldn't have to!
application.rb (portion):
# Establish a base connection to Amazon S3
S3_CREDENTIALS = YAML.load(File.read(File.expand_path(Rails.root.join("config","aws.yml"))))["development"]
AWS.config(
:access_key_id => S3_CREDENTIALS['access_key_id'],
:secret_access_key => S3_CREDENTIALS['secret_access_key'],
)
And of course export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to your environment.
On Mac just 'export AWS_ACCESS_KEY_ID=YOUR_KEY_GOES_HERE AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY_GOES_HERE' and hit return.
Heroku is:
heroku config:set AWS_ACCESS_KEY_ID=YOUR_KEY_GOES_HERE AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY_GOES_HERE
Can't do anything for you if you're using Windows.
You're right that it would never work if the key was just wrong. Have you tried to make sure that S3_CREDENTIALS['access_key_id'] and ENV['AWS_ACCESS_KEY_ID'] contain what you think they contain? My first guess is that S3_CREDENTIALS['access_key_id'] ends up containing the literal string of <%=ENV['AWS_ACCESS_KEY_ID']%> (not interpreted) since you're not processing the yaml file as erb before loading the file.

Rails tutorial port to amazon dynamodb

I'm following michael hartl's tutorial for getting started with rails...
http://ruby.railstutorial.org/
I'm trying to modify my database backend from PostgreSQL to Amazon dynamodb.. Any advice/help on how to achieve this would be very helpful.
This is going to be tough because Hartl's tutorial stresses learning ActiveRecord knowledge very strongly, whose core components don't really make sense in the context of DynamoDB.
If you're insistent, Amazon provides the aws-sdk gem that you can bundle into your application. Set up your appropriate credentials in the config/initializers/aws.rb initializer
AWS.config({
:access_key_id => 'your_access_key_id',
:secret_access_key => 'your_secret_access_key',
})
You'll probably want your models (where appropriate) to inherit from AWS::Record::HashModel if you want to have a sensible way of interfacing with objects.
You'll also probably want to write some assessors in this format.
def img= image
self.has_image = true
AWS::S3.new.buckets[:images_cloudstock].objects[id].write(image.read)
end
def img
AWS::S3.new.buckets[:images_cloudstock].objects[id].url_for(:read) if has_image
end

AWS S3 Ruby url_for response headers (custom file name and file type)

I'm just wondering if this is a bug, an error on my part or has anyone managed to get this working
>irb
>require 'aws/s3'
>AWS::S3::Base.establish_connection!(
:access_key_id => key,
:secret_access_key => secret)
>AWS::S3::S3Object.url_for(
filename,
bucket,
:use_ssl => true,
:response_content_type=>'text/plain',
:response-content-disposition=>'attachment; filename=text.txt'
)
This will spit out a signed url
I can get a URL out of this but the :response_content_type & :response-content-disposition options don't seem to do anything at all.
These are documented at
http://docs.amazonwebservices.com/AWSRubySDK/latest/AWS/S3/S3Object.html#url_for-instance_method
Does anyone have luck with adding these per request headers? Or am I doing it wrong?
EDIT I figured it out: If anyone runs into the same - require the right gem not 'aws/s3' its 'aws-sdk' (there are two floating around out there with pretty much the same code - I think the latter is an old version)
aws-s3 is an old version of aws-sdk. Lots of code between them just works even if you swap the require header. Use aws-sdk to fix this problem.

Resources