jeudi 25 juin 2015

AWS authentication V4 signature failure; where am I going wrong in generating the signature?

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://ift.tt/1Cm4tRU. 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://ift.tt/1IAjFcQ'},
    ['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://ift.tt/1fEexO3", 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




Aucun commentaire:

Enregistrer un commentaire