AWS Access Key not working in rails app - ruby-on-rails

I have a rails app setup with paperclip and aws-sdk
My aws.yml file is below:
development:
access_key_id: ENV['AWS_ACCESS_KEY_ID']
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
production:
access_key_id: ENV['AWS_ACCESS_KEY_ID']
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
My development.rb file is here:
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['AWS_BUCKET']
}
}
I'm 100% sure my keys are correct. I've double, triple and quadruple checked the keys. I first tried an Iam user key, but that didn't work, then I tried creating a root key and that didn't work either. I'm back to using a brand new Iam user key and that user has full S3 access.
/config/initializers/algoliasearch.rb uses an environment variable just fine:
AlgoliaSearch.configuration = { application_id: 'xxxxxx', api_key: ENV['algolia_admin_api_key'] }
Still, though, when I try to upload a file in my development environment I get the InvalidAccessKey error from aws. I haven't tried it on production yet because that's using the same keys (just the bucket name is different).
Am I using the wrong keys? Or is something preventing my key from being accessed? I can't find anything telling me how to set my keys up properly and I'm completely lost. I know I got this working before and can't remember there being any other steps.

I figured out the solution: I had to add the s3 credentials to the production.rb and development.rb environment files:
# development.rb
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['AWS_BUCKET'],
:access_key_id => ENV['HOMEIN_AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['HOMEIN_AWS_SECRET_ACCESS_KEY']
}
}
They're both the same, except for the bucket name.
I feel like there's a more elegant solution that I don't know of, though...

Related

Uploading files to AWS with paperclip

I'm currently trying to upload images to AWS but keep getting Aws::Errors::MissingCredentialsError: unable to sign request without credentials set.
In my current setup I configure paperclip defaults setting as the following in my application.rb file.
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV["s3_bucket"],
:access_key_id => ENV["s3_access_key_id"],
:s3_secret_access_key => ENV["s3_secret_access_key"],
:s3_region => ENV["s3_region"]
}
}
Then in my application.yml I set the values of the variables like so
development:
s3_bucket: "open-doors-dev"
production:
s3_bucket: "open-doors-pro"
s3_region: "us-west-1"
s3_access_key_id: "MY ACCESS KEY HERE"
s3_secret_access_key: "MY SECRET KEY HERE"
However when I try and test this code in the rails console I get the above error. I printed out the values of config.paperclip_defaults in my code and they match the values that I supplied in application.yml so I do not understand why this code is failing.
I figured out what was going wrong. I had two problem the first being that in paper_clip defaults; :s3_secret_access_key should have just been secret_access_key the second being I had to change my policy to an inline policy though I'm unsure as to why that was giving me an error.

Rails ArgumentError (missing required :bucket option) fixes not working?

My Rails app is hosted on Heroku but I need to get Paperclip working locally so I can upload photos in testing. I'm really close, but I'm stuck on the "missing required :bucket option" error.
I've tried moving around settings in my environment files as well as well as adding a config/application.yml file with my AWS credentials in it, but no dice.
Here's my config from development.rb (looks the same in production.rb):
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
I've tried moving :bucket attribute outside of :s3_credentials but it didn't change anything. Application.yml looks like this:
AWS_ACCESS_KEY_ID="xxxxxxxxxxxxxxxxx"
AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxx"
S3_BUCKET_NAME="xxxxxx"
I also installed the dot-env gem and added an s3.env file to the index of my app which contains the same credentials as above, but even that hasn't worked. Nor did adding my Paperclip config inline with the has_attached_file in my model.
What do I do??
Alternatively, if someone runs into this problem and doesn't want to use a .env file, the following works.
Assuming your bucket is hosted in the US region, put a file called aws.yml under the config dir. The file should be in the following format:
development:
access_key_id: AWS_ACCESS_KEY_ID
secret_access_key: AWS_SECRET_KEY_ID
production:
access_key_id: AWS_ACCESS_KEY_ID
secret_access_key: AWS_SECRET_KEY_ID
In your model:
class Model < ActiveRecord::Base
has_attached_file :avatar, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'}, :storage => :s3,
:s3_credentials => "#{Rails.root}/config/aws.yml",
:bucket => "your_bucket_name"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
Replace your_bucket_name with the name of your actual bucket.
Gemfile:
gem 'aws-sdk', '< 2.0'
Under Environments, production and development:
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
To put it in production on Heroku, you have to set the following using the terminal:
$ heroku config:set S3_BUCKET_NAME=your_bucket_name
$ heroku config:set AWS_ACCESS_KEY_ID=your_access_key_id
$ heroku config:set AWS_SECRET_ACCESS_KEY=your_secret_access_key
Your Application.yml file doesn't look like YAML. It should look like this:
AWS_ACCESS_KEY_ID: "xxxxxxxxxxxxxxxxx"
AWS_SECRET_ACCESS_KEY: "xxxxxxxxxxxxxxxxxxxx"
S3_BUCKET_NAME: "xxxxxx"
If you are loading the yml file like they advise here you'll want your yml file to look like this:
development:
AWS_ACCESS_KEY_ID: "xxxxxxxxxxxxxxxxx"
AWS_SECRET_ACCESS_KEY: "xxxxxxxxxxxxxxxxxxxx"
S3_BUCKET_NAME: "xxxxxx"
You need a way to set the environment variables for your app in your development environment. Using Application.yml or .env file should work, but you probably don't need both.

Paperclip uploads on Heroku using S3

I'm sorry to rehash an old gripe but I'm at my wits end and not sure where to go next. I am using Paperclip on Heroku and have S3 uploads configured. I was able to get things working in my local development environment but once it's running on Heroku I run into this error:
AWS::S3::Errors::PermanentRedirect (The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.
I've googled this error and read through the Heroku documentation and I believe I have everything set up correctly. I initially thought that my problems stemmed from having my bucket in the s3-us-west-1.amazonaws.com region, but I'm not convinced anymore.
Here are the relevant parts of my Heroku config:
AWS_REGION: us-west-1
S3_BUCKET_NAME: my-super-awesomely-amazing-bucket
From my config/environments/production.rb file:
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
My paperclip.rb initialize file:
if Rails.env.production?
Paperclip::Attachment.default_options[:url] = ':s3_domain_url'
Paperclip::Attachment.default_options[:path] = '/:class/:attachment/:id_partition/:style/:filename'
Paperclip::Attachment.default_options[:s3_host_name] = 's3-us-west-1.amazonaws.com'
end
And my paperclip config from the relevant model:
has_attached_file :document,
:styles => { },
:default_url => "/image_styles/:style/missing.png"
So...what am I doing wrong here? At this point I'm sure I've missed something obvious but I'm stumped on where to go from here. I feel like I've assiduously configured everything and yet that PermanentRedirect error keeps coming up.
Bucket
This might not be the direct solution, but we've found that you have to include the bucket option outside of your s3_credentials block:
#config/environments/production.rb
config.paperclip_defaults = {
storage: :s3,
s3_host_name: 's3-eu-west-1.amazonaws.com',
s3_credentials: {
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
},
bucket: ENV['S3_BUCKET_NAME']
}
This is working 100% for us on Heroku, but whether it wil work for you (as your bucket is in a different region) is a different matter
If you need more help, ask a comment and I'll gladly give you some ideas
Try this link http://adamthedeveloper.blogspot.in/2014/02/awss3permanentredirect-bucket-you-are.html . Previously this happened to Europe region buckets only and get resolved by setting AWS::S3::DEFAULT_HOST. Hope this solve your issue.

Ruby on Rails with Figaro and Paperclip

I'm using localhost right now and installed the Figaro gem to help me test using Paperclip with my S3 bucket. When I try to upload something, I get this message:
missing required :bucket option
In development.rb I inserted the following code:
config.paperclip_defaults = {
storage: :s3,
s3_credentials: {
bucket: :ENV['AWS_BUCKET'],
access_key_id: :ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: :ENV['AWS_SECRET_ACCESS_KEY']
}
}
And then I placed the following code in the Figaro-generated application.yml file:
development:
AWS_BUCKET: (the actual name of my bucket)
AWS_ACCESS_KEY_ID: (the actual access key)
AWS_SECRET_ACCESS_KEY: (etc)
I will say that when I declare what the bucket is directly into the model I'm using for this, it does seem to work (a new folder is generated in my bucket) but the image never actually appears in the destination (perhaps a separate issue or perhaps not).
I know I am missing something obvious here, I'm probably not doing something right. Using Rails v4 with aws-sdk v1.34 and Figaro v0.7.0. Thanks to anyone who can help me.
I think there is just a syntax typo. ENV is a variable; it's a hash and not a symbol. Just remove the : from in front of ENV. It should be:
config.paperclip_defaults = {
storage: :s3,
s3_credentials: {
bucket: ENV['AWS_BUCKET'],
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
}
}
Further to your comment, this is live code which is 100% working for us right now:
config.paperclip_defaults = {
storage: :s3,
s3_host_name: 's3-eu-west-1.amazonaws.com',
s3_credentials: {
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
},
bucket: ENV['S3_BUCKET_NAME']
}
Also make sure you restart your rails server each time you change these details. Reason being the config files are loaded at initialization, and maintained for the server's session

aws-s3 error: AWS::S3::MissingAccessKey error, but keys have been defined?

I'm pretty new to ROR. I've recently deployed an app on heroku and have tried to add an attachment function to the app via paperclip.
I've followed all the steps in adding aws-s3 to my app. Here was my initial code:
user.rb (model)
has_attached_file :avatar,
:styles => {:small => "70x70>"},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => ":attachment/:id/:style/:basename.:extension"
validates_attachment_size :avatar, :less_than => 1.megabytes
validates_attachment_content_type :avatar, :content_type => ['image/jpeg', 'image/png']
s3.yml (file is located in config folder) note: all of these buckets exist on my aws-s3
development:
bucket: my_avatar-dev
access_key_id: amazonaccesskey
secret_access_key: amazon_secret_access_key
test:
bucket: myapp_avatar-test
access_key_id: amazonaccesskey
secret_access_key: amazon_secret_access_key
production:
bucket: myapp_avatar-pro
access_key_id: amazonaccesskey
secret_access_key: amazon_secret_access_key
gemfile
gem 'aws-s3'
When running this configuration, I would get a error page 500 error when loading my app. Running Heroku logs showed the following error: AWS::S3::MissingAccessKey (You did not provide both required access keys.
So I followed some advice and defined the key and secret_key as environment variables to heroku, using the following line of code:
heroku config:add S3_KEY=amazonaccesskey S3_SECRET=amazon_secret_key
I then added an initializer to test environments and launch via key or .yml file depending on environment, code is as follows:
initializers/s3.rb
if Rails.env == "production"
# set credentials from ENV hash
S3_CREDENTIALS = { :access_key_id => ENV['S3_KEY'], :secret_access_key => ENV['S3_SECRET'], :bucket => "myapp_avatar-pro"}
else
# get credentials from YML file
S3_CREDENTIALS = Rails.root.join("config/s3.yml")
end
user.rb model was then update to the following:
has_attached_file :avatar, :storage => :s3, :s3_credentials => S3_CREDENTIALS
I then deployed to heroku and tested the app, but I still keep getting the same error (page 500) and error code: AWS::S3::MissingAccessKey (You did not provide both required access keys.
How is this possible if I have defined the variables in heroku? Is there something I am missing? Is it possible it's something with the gem? Also, I'm using HAML for styling... not sure that matters at all, but just in case it does. I'm quite lost, so any help would be greatly appreciated. Thank you so much!
Having just worked through the same problem and trawling a number of similar posts. I found that any of the possible configurations in the above answer i.e. declaring all of the hashes in the model, using the .yml or using the initializer all work fine from my dev and on heroku as long as the S3 bucket is of US Standard type> The choice is just about how DRY you want to be.
When I originally set S3 up, I used a European bucket. This gave me the spurious error message:
AWS::S3::MissingAccessKey (You did not provide both required access keys.
I note from the AWS site : http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html
that AWS uses a specific endpoint address for each region to reduce latency and am guessing (because I am a novice coder) that the US standard is either a default or coded into the AWS-S3 plugin. (Maybe someone can edit this up into a more complete answer?)
I solved this problem with this:
:s3_credentials => {
:access_key_id => 'mykey',
:secret_access_key => 'mykey'

Resources