1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00
fog--fog/lib/fog/aws/signaturev4.rb
Paul Thornthwaite a72433d2f8 Remove duplicate requires from services
Following work on reorganising the requires, there was an inconsistent
approach to where service wrappers are required. (Fog::Compute...)

Since they should be standardised and shared across providers (although
they really aren't yet) they have been moved to `fog-core` gem.

Each provider has their own `lib/fog/{provider}/core` files that is
required by each of their services. These files should all require
`fog/core` which already required most or these.

So this removes the extra cases to concentrate them in core.
2014-02-13 17:44:48 +00:00

74 lines
2.3 KiB
Ruby

require 'fog/aws/core'
# 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 = []
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)}"
canonical_query_string << component
end
canonical_query_string.join("&")
end
def canonical_headers(headers)
canonical_headers = ''
for key in headers.keys.sort_by {|k| k.to_s}
canonical_headers << "#{key.to_s.downcase}:#{headers[key].to_s.strip}\n"
end
canonical_headers
end
def signed_headers(headers)
headers.keys.collect {|key| key.to_s}.sort.collect {|key| key.downcase}.join(';')
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
end