400 Bad request InvalidArgument Missing access key

dreamobjects

#1

I read recently that you upgraded ceph which will allow to use signature v4, I was using version 2 with the old ruby aws-sdk and now I’ve update my aws-sdk gem to the last version which has only support for signature v4 and setup my code like that :

[code]Aws.config.update({

endpoint: ‘https://objects-us-west-1.dream.io’,

access_key_id: ‘XXXXXXXXXXXXXXXXX’,

secret_access_key: ‘XXXXXXXXXXXXXXXXXXXXXX’,

region: ‘us-east-1’

})

s3 = Aws::S3::Resource.new

reference an existing bucket by name

S3_BUCKET = s3.bucket(‘my_bucket’)[/code]

When I try to upload an image now using jquery file upload plugin, I get error in the console of type : (400 Bad request ) : InvalidArgument Missing access key

What can be wrong in this situation ?

Thanks


#2

I just did a quick test to verify v4 signatures worked with the ruby aws-sdk v2 and it worked as expected. Here’s the configuration I used:

[code]require ‘aws-sdk’

Aws.config.update({
endpoint: ‘https://objects-us-west-1.dream.io’,
access_key_id: ‘XXXXXXXXXXXXXXXXXX’,
secret_access_key: ‘YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY’,
region: ‘us-west-1’,
})

s3 = Aws::S3::Client.new

resp = s3.list_objects(bucket: ‘my_bucket’)
resp.contents.each do |object|
puts "#{object.key} => #{object.etag}"
end[/code]

If that doesn’t help, post some more code and I can try to dig further!


#3

Your code works on my machine as well, but the problem is occurring when I try to upload files directly with jquery file upload.

I followed this tutorial here : https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails#finished-jquery-file-upload-code

and this is a sample app with the code I made : https://bitbucket.org/technoblogueur/dreamobjects/src/1b18119099e3?at=master

The code is simple, in app/controllers/images I have the following (all you have to do is put in your access key and secret) :

[code]@image = Image.new

  Aws.config.update({
          endpoint: 'https://objects-us-west-1.dream.io',
          access_key_id: 'xxxxxxxxxxxxxxxxxxx',
          secret_access_key: 'yyyyyyyyyyyyyyyyy',
          region: 'us-west-1',
  })

  s3 = Aws::S3::Resource.new
  bucket = s3.bucket('my_bucket')


  @s3_direct_post = bucket.presigned_post(
  		key: "uploads/#{SecureRandom.uuid}/${filename}",
  		success_action_status: '201',
        #expires: Time.now() + 30,
        #content_length_range: 1...1024,
  		acl: 'public-read',
        content_type: 'image/png'
  	)[/code]

and the views ( app / views / images / index.html.erb) I have a form like this :

[code]<%= form_for(@image, html: { class: ‘directUpload’, data: { ‘form-data’ => (@s3_direct_post.fields), ‘url’ => @s3_direct_post.url, ‘host’ => URI.parse(@s3_direct_post.url).host } }) do |f| %>

<div class="field">

    <%= f.label :image %><br>

    <%= f.file_field :image %>

</div>

<% end %>[/code]

finally I use jquery file upload to do the uploading (app / assets / javascripts / image_uploads.coffee.erb) ----- (in case you’re not familiar with coffeeScript it’s just javascript without using “;” at the end of lines and replacing the keyword “function” with “->” nothing magic!) :

[code]jQuery ->

jqXHR = null

$('.directUpload').find("input:file").each (i, elem) ->

	fileInput    = $(elem)
	form         = $(fileInput.parents('form:first'))
	submitButton = form.find('input[type="submit"]')
	progressBar  = $("<div class='bar'></div>")
	barContainer = $("<div class='progress'></div>").append(progressBar)
	fileInput.after(barContainer)

	fileInput.fileupload({
		#$('form#add').serializeArray()
		formData:        form.data('form-data'),
		fileInput:       fileInput,
		url:             form.data('url')
		type:            'POST',
		autoUpload:       true,
		paramName:        'file', # S3 does not like nested name fields i.e. name="user[avatar_url]"
		dataType:         'XML',  # S3 returns XML if success_action_status is set to 201
		replaceFileInput: false,
		acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
		# maxFileSize: 999000,
        # acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i

		progressall: (e, data) ->

			progress = parseInt(data.loaded / data.total * 100, 10);
			progressBar.css('width', progress + '%')
		,
		start: (e, data) ->

			console.log("staaart")

			submitButton.prop('disabled', true)

			progressBar.
			  css('background', 'green').
			  css('display', 'block').
			  css('width', '0%').
				  text("Loading...")
		,
		done: (e, data) ->
			console.log("done")
			submitButton.prop('disabled', false)
			progressBar.text("Uploading done")
		,
		fail: (e, data) ->
			submitButton.prop('disabled', false)

			progressBar.
			  css("background", "red").
			  text("Failed")

	})[/code]

#4

I downloaded your code, setup CORS on my bucket, and was able to reproduce the same issue. I also tried the same code with AWS and it worked so I suspect we have a bug in the API server. I’ll make a ticket for our developers to dig deeper and work on a fix.


#5

Thank you for trying that out. Please let me know when it’s fixed.


#6

It’s been a while since I posted this thread and dreamobject still doesn’t support signature v4 for direct upload :frowning: any update about this ?


#7

I ran your code again and found that DreamObjects is still responding with a 400 bad request. I tested with a standard HTML post upload and it worked just fine so I’m not exactly sure what the problem is. The bug I created for this is still pending with a low priority (since a regular post upload works). I wish I had better news for you.


#8

Thank you for reply… I tested the code with other s3 compatible and it’s working, it only doesn’t work with dreamobjects… In the meantime I switched back to the old version (v2), hopefully this will be corrected soon… Thanks