From 4b501ca084442769d17f04e232ca34187929a528 Mon Sep 17 00:00:00 2001 From: Trevor Rowe Date: Wed, 29 Jul 2015 12:29:09 -0700 Subject: [PATCH] Added support for non-standard ports with sigv4. Fixes #883. --- CHANGELOG.md | 6 ++++++ aws-sdk-core/lib/aws-sdk-core/signers/v4.rb | 17 +++++++++++++++-- aws-sdk-core/spec/aws/signers/v4_spec.rb | 9 +++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2abf3ebc94..841a7a3850c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Unreleased Changes ------------------ +* Feature - Signature Version 4 - Added support for signing requests against + hosts that do not use the standard port for the given HTTP scheme. This + makes it possible to use the signer against test endpoints. + + See [related GitHub issue #883](https://github.com/aws/aws-sdk-ruby/issues/883). + 2.1.10 (2015-07-29) ------------------ diff --git a/aws-sdk-core/lib/aws-sdk-core/signers/v4.rb b/aws-sdk-core/lib/aws-sdk-core/signers/v4.rb index 5da7bf2d7b6..8ab8e7915c5 100644 --- a/aws-sdk-core/lib/aws-sdk-core/signers/v4.rb +++ b/aws-sdk-core/lib/aws-sdk-core/signers/v4.rb @@ -31,7 +31,7 @@ def sign(req) datetime = Time.now.utc.strftime("%Y%m%dT%H%M%SZ") body_digest = req.headers['X-Amz-Content-Sha256'] || hexdigest(req.body) req.headers['X-Amz-Date'] = datetime - req.headers['Host'] = req.endpoint.host + req.headers['Host'] = host(req.endpoint) req.headers['X-Amz-Security-Token'] = @credentials.session_token if @credentials.session_token req.headers['X-Amz-Content-Sha256'] ||= body_digest @@ -51,7 +51,7 @@ def presigned_url(request, options = {}) now = Time.now.utc.strftime("%Y%m%dT%H%M%SZ") body_digest = options[:body_digest] || hexdigest(request.body) - request.headers['Host'] = request.endpoint.host + request.headers['Host'] = host(request.endpoint) request.headers.delete('User-Agent') params = Aws::Query::ParamList.new @@ -179,6 +179,19 @@ def canonical_header_value(value) value.match(/^".*"$/) ? value : value.gsub(/\s+/, ' ').strip end + def host(uri) + if standard_port?(uri) + uri.host + else + "#{uri.host}:#{uri.port}" + end + end + + def standard_port?(uri) + (uri.scheme == 'http' && uri.port == 80) || + (uri.scheme == 'https' && uri.port == 443) + end + def hexdigest(value) digest = OpenSSL::Digest::SHA256.new if value.respond_to?(:read) diff --git a/aws-sdk-core/spec/aws/signers/v4_spec.rb b/aws-sdk-core/spec/aws/signers/v4_spec.rb index 648980f7e47..4790670782b 100644 --- a/aws-sdk-core/spec/aws/signers/v4_spec.rb +++ b/aws-sdk-core/spec/aws/signers/v4_spec.rb @@ -32,6 +32,15 @@ module Signers expect(sign.headers['Host']).to eq('domain.com') end + it "includes port in host when non stadard" do + endpoint.scheme = 'http' + endpoint.port = 3000 + expect(sign.headers['Host']).to eq('domain.com:3000') + endpoint.scheme = 'https' + endpoint.port = 3000 + expect(sign.headers['Host']).to eq('domain.com:3000') + end + it "populates the 'X-Amz-Date' header" do datetime = '20120102:10:11:12Z' expect(utc).to receive(:strftime).with("%Y%m%dT%H%M%SZ") { datetime }