diff --git a/lib/fog/aws/signaturev4.rb b/lib/fog/aws/signaturev4.rb index e6c745fea..1cd76704c 100644 --- a/lib/fog/aws/signaturev4.rb +++ b/lib/fog/aws/signaturev4.rb @@ -36,7 +36,7 @@ module Fog def signature_components(params, date, body_sha) canonical_request = <<-DATA #{params[:method].to_s.upcase} -#{params[:path]} +#{canonical_path(params[:path])} #{canonical_query_string(params[:query])} #{canonical_headers(params[:headers])} #{signed_headers(params[:headers])} @@ -78,6 +78,20 @@ DATA protected + def canonical_path(path) + components = path.split('/') + path = components.inject([]) do |acc, component| + case component + when '.' #canonicalize by removing . + when '..' then acc.pop#canonicalize by reducing .. + else + acc << component + end + acc + end.join('/') + path.empty? ? '/' : path + end + def canonical_query_string(query) canonical_query_string = [] for key in (query || {}).keys.sort_by {|k| k.to_s} diff --git a/tests/aws/signaturev4_tests.rb b/tests/aws/signaturev4_tests.rb index 29068a26d..daf3bfcd4 100644 --- a/tests/aws/signaturev4_tests.rb +++ b/tests/aws/signaturev4_tests.rb @@ -38,6 +38,18 @@ Shindo.tests('AWS | signaturev4', ['aws']) do end end + tests('get with relative path') do + returns(@signer.sign({:query => {}, :headers => {'Host' => 'host.foo.com', 'Date' => 'Mon, 09 Sep 2011 23:36:00 GMT'}, :method => :get, :path => '/foo/bar/../..'}, @now)) do + 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470' + end + end + + tests('get with pointless .') do + returns(@signer.sign({:query => {}, :headers => {'Host' => 'host.foo.com', 'Date' => 'Mon, 09 Sep 2011 23:36:00 GMT'}, :method => :get, :path => '/./foo'}, @now)) do + 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=910e4d6c9abafaf87898e1eb4c929135782ea25bb0279703146455745391e63a' + end + end + tests('get signature as components') do returns(@signer.signature_parameters({:query => {'a' => 'foo', 'b' => 'foo'}, :headers => {'Host' => 'host.foo.com', 'Date' => 'Mon, 09 Sep 2011 23:36:00 GMT'}, :method => :get, :path => '/'}, @now)) do {