lib/EC2.rb in amazon-ec2-0.3.2 vs lib/EC2.rb in amazon-ec2-0.3.4
- old
+ new
@@ -26,27 +26,39 @@
# Builds the canonical string for signing. This strips out all '&', '?', and '='
# from the query string to be signed.
# Note: The parameters in the path passed in must already be sorted in
# case-insensitive alphabetical order and must not be url encoded.
- def EC2.canonical_string(path)
- buf = ""
- path.split('&').each { |field|
- buf << field.gsub(/\&|\?/,"").sub(/=/,"")
- }
- return buf
+ def EC2.canonical_string(params, host = DEFAULT_HOST, method="POST", base="/")
+ # Sort, and encode parameters into a canonical string.
+ sorted_params = params.sort {|x,y| x[0] <=> y[0]}
+ encoded_params = sorted_params.collect do |p|
+ encoded = (CGI::escape(p[0].to_s) +
+ "=" + CGI::escape(p[1].to_s))
+ # Ensure spaces are encoded as '%20', not '+'
+ encoded.gsub('+', '%20')
+ end
+ sigquery = encoded_params.join("&")
+
+ # Generate the request description string
+ req_desc =
+ method + "\n" +
+ host + "\n" +
+ base + "\n" +
+ sigquery
+
end
# Encodes the given string with the secret_access_key, by taking the
# hmac-sha1 sum, and then base64 encoding it. Optionally, it will also
# url encode the result of that to protect the string if it's going to
# be used as a query string parameter.
def EC2.encode(secret_access_key, str, urlencode=true)
digest = OpenSSL::Digest::Digest.new('sha1')
b64_hmac =
Base64.encode64(
- OpenSSL::HMAC.digest(digest, secret_access_key, str)).strip
+ OpenSSL::HMAC.digest(digest, secret_access_key, str)).gsub("\n","")
if urlencode
return CGI::escape(b64_hmac)
else
return b64_hmac
@@ -150,19 +162,18 @@
# remove any keys that have nil or empty values
params.reject! { |key, value| value.nil? or value.empty?}
params.merge!( {"Action" => action,
- "SignatureVersion" => "1",
+ "SignatureVersion" => "2",
+ "SignatureMethod" => 'HmacSHA1',
"AWSAccessKeyId" => @access_key_id,
"Version" => API_VERSION,
"Timestamp"=>Time.now.getutc.iso8601} )
- sigquery = params.sort_by { |param| param[0].downcase }.collect { |param| param.join("=") }.join("&")
+ sig = get_aws_auth_param(params, @secret_access_key)
- sig = get_aws_auth_param(sigquery, @secret_access_key)
-
query = params.sort.collect do |param|
CGI::escape(param[0]) + "=" + CGI::escape(param[1])
end.join("&") + "&Signature=" + sig
req = Net::HTTP::Post.new("/")
@@ -180,11 +191,11 @@
end
end
# Set the Authorization header using AWS signed header authentication
- def get_aws_auth_param(path, secret_access_key)
- canonical_string = EC2.canonical_string(path)
+ def get_aws_auth_param(params, secret_access_key)
+ canonical_string = EC2.canonical_string(params)
encoded_canonical = EC2.encode(secret_access_key, canonical_string)
end
# allow us to have a one line call in each method which will do all of the work
# in making the actual request to AWS.