I am generating a form using the ruby code below (passing the CSV file with credentials downloads from the AWS console as the argument). If I submit a file using this form, I get The request signature we calculated does not match the signature you provided. Check your key and signing method.
. I have copied the signing code from http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-ruby. I've looked at Amazon MWS - request signature calculated does not match the signature provided and s3 "signature doesn't match" client side post jquery-file-upload, but these don't seem to apply in my case. Where am I going wrong?
#!/usr/bin/env ruby
require 'nokogiri'
require 'csv'
require 'ostruct'
require 'base64'
require 'json'
require 'openssl'
header = nil
data = nil
CSV.foreach(ARGV[0]) do |row|
if header.nil?
header = row.collect{|c| c.strip.gsub(/\s/, '') }
else
data = row
end
end
creds = OpenStruct.new(Hash[*(header.zip(data).flatten)])
bucket = 'zotplus'
region = 'eu-central-1'
service = 's3'
dateStamp = Time.now.strftime('%Y%m%d')
policy = {
'expiration' => '2029-01-01T00:00:00Z',
'conditions' => [
{'bucket' => bucket},
['starts-with', '$key', 'uploads/'],
{'acl' => 'private'},
{'success_action_redirect' => 'http://zotplus.github.io/submitted.html'},
['starts-with', '$Content-Type', 'multipart/form-data'],
['content-length-range', 0, 1048576],
{'x-amz-date' => "#{dateStamp}T000000Z"},
{'x-amz-credential' => "#{creds.AccessKeyId}/#{dateStamp}/#{region}/#{service}/aws4_request"}
]
}
form = {}
%w{acl success_action_redirect bucket x-amz-date x-amz-credential}.each{|eq|
form[eq] = policy['conditions'].detect{|c| c.is_a?(Hash) && c[eq] }[eq]
}
form['key'] = policy['conditions'].detect{|c| c.is_a?(Array) && c[0,2] = ['starts-with', '$key']}[2] + '${filename}'
policy_string = Base64.encode64(policy.to_json).gsub("\n","")
kDate = OpenSSL::HMAC.digest('sha256', "AWS4" + creds.SecretAccessKey, dateStamp)
kRegion = OpenSSL::HMAC.digest('sha256', kDate, region)
kService = OpenSSL::HMAC.digest('sha256', kRegion, service)
kSigning = OpenSSL::HMAC.digest('sha256', kService, 'aws4_request')
signature = Base64.encode64(OpenSSL::HMAC.digest('sha256', kSigning, policy_string)).gsub("\n","")
form['policy'] = policy_string
form['x-amz-signature'] = signature
form['x-amz-algorithm'] = 'AWS4-HMAC-SHA256'
builder = Nokogiri::HTML::Builder.new do |doc|
doc.html {
doc.head {
doc.title {
doc.text 'submit file'
}
doc.meta('http-equiv' => "Content-Type", content: "text/html; charset=UTF-8")
}
doc.body {
doc.form(action: "http://zotplus-964ec2b7-379e-49a4-9c8a-edcb20db343f.s3.amazonaws.com/", method: "post", enctype: "multipart/form-data") {
form.each_pair{|k, v|
doc.input(type: "hidden", name: k, value: v)
}
doc.text 'File: '
doc.input(type: "file", name: "file")
doc.input(type: "submit", name: "submit", value: "Upload to Amazon S3")
}
}
}
end
puts builder.to_html