2012-09-01 11:42:02 -04:00
|
|
|
# See http://docs.amazonwebservices.com/general/latest/gr/signature-version-4.html
|
|
|
|
#
|
|
|
|
module Fog
|
|
|
|
module AWS
|
|
|
|
class SignatureV4
|
|
|
|
def initialize(aws_access_key_id, secret_key, region,service)
|
|
|
|
@region = region
|
|
|
|
@service = service
|
|
|
|
@aws_access_key_id = aws_access_key_id
|
|
|
|
@hmac = Fog::HMAC.new('sha256', 'AWS4' + secret_key)
|
|
|
|
end
|
|
|
|
|
|
|
|
def sign(params, date)
|
|
|
|
canonical_request = <<-DATA
|
|
|
|
#{params[:method].to_s.upcase}
|
|
|
|
#{params[:path]}
|
|
|
|
#{canonical_query_string(params[:query])}
|
|
|
|
#{canonical_headers(params[:headers])}
|
|
|
|
#{signed_headers(params[:headers])}
|
|
|
|
#{Digest::SHA256.hexdigest(params[:body] || '')}
|
|
|
|
DATA
|
|
|
|
canonical_request.chop!
|
|
|
|
credential_scope = "#{date.utc.strftime('%Y%m%d')}/#{@region}/#{@service}/aws4_request"
|
|
|
|
string_to_sign = <<-DATA
|
|
|
|
AWS4-HMAC-SHA256
|
|
|
|
#{date.to_iso8601_basic}
|
|
|
|
#{credential_scope}
|
|
|
|
#{Digest::SHA256.hexdigest(canonical_request)}
|
|
|
|
DATA
|
|
|
|
|
|
|
|
string_to_sign.chop!
|
|
|
|
|
|
|
|
signature = derived_hmac(date).sign(string_to_sign)
|
|
|
|
|
|
|
|
"AWS4-HMAC-SHA256 Credential=#{@aws_access_key_id}/#{credential_scope}, SignedHeaders=#{signed_headers(params[:headers])}, Signature=#{signature.unpack('H*').first}"
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def canonical_query_string(query)
|
|
|
|
canonical_query_string = []
|
2012-09-07 12:13:19 -04:00
|
|
|
for key in (query || {}).keys.sort_by {|k| k.to_s}
|
|
|
|
component = "#{Fog::AWS.escape(key.to_s)}=#{Fog::AWS.escape(query[key].to_s)}"
|
2012-09-01 11:42:02 -04:00
|
|
|
canonical_query_string << component
|
|
|
|
end
|
|
|
|
canonical_query_string.join("&")
|
|
|
|
end
|
|
|
|
|
|
|
|
def canonical_headers(headers)
|
|
|
|
canonical_headers = ''
|
|
|
|
|
2012-09-07 12:13:19 -04:00
|
|
|
for key in headers.keys.sort_by {|k| k.to_s}
|
|
|
|
canonical_headers << "#{key.to_s.downcase}:#{headers[key].to_s.strip}\n"
|
2012-09-01 11:42:02 -04:00
|
|
|
end
|
|
|
|
canonical_headers
|
|
|
|
end
|
|
|
|
|
|
|
|
def signed_headers(headers)
|
2012-09-07 12:13:19 -04:00
|
|
|
headers.keys.collect {|key| key.to_s}.sort.collect {|key| key.downcase}.join(';')
|
2012-09-01 11:42:02 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def derived_hmac(date)
|
|
|
|
kDate = @hmac.sign(date.utc.strftime('%Y%m%d'))
|
|
|
|
kRegion = Fog::HMAC.new('sha256', kDate).sign(@region)
|
|
|
|
kService = Fog::HMAC.new('sha256', kRegion).sign(@service)
|
|
|
|
kSigning = Fog::HMAC.new('sha256', kService).sign('aws4_request')
|
|
|
|
Fog::HMAC.new('sha256', kSigning)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
2012-11-29 17:25:37 -05:00
|
|
|
end
|