Class: Aws4Signer::Signature

Inherits:
Object
  • Object
show all
Defined in:
lib/aws4_signer/signature.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(access_key_id, secret_access_key, region, service, verb, uri, headers, body) ⇒ Signature

Returns a new instance of Signature.



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/aws4_signer/signature.rb', line 3

def initialize(access_key_id, secret_access_key, region, service, verb, uri, headers, body)
  @access_key_id = access_key_id
  @secret_access_key = secret_access_key
  @region = region
  @service = service
  @verb = verb
  @uri = uri
  @headers = headers.dup
  @body = body

  @headers.each do |name, value|
    if value.kind_of?(Array)
      @headers[name] = value.first
    end
  end

  @headers["x-amz-date"] ||= @headers.delete("X-Amz-Date")
  unless @headers["x-amz-date"]
    @date = Time.now.utc
    @headers["x-amz-date"] = @date.strftime("%Y%m%dT%H%M%SZ")
  end
  @headers["Host"] ||= @headers.delete("host") || uri.host
end

Instance Attribute Details

#access_key_idObject (readonly)

Returns the value of attribute access_key_id.



27
28
29
# File 'lib/aws4_signer/signature.rb', line 27

def access_key_id
  @access_key_id
end

#bodyObject (readonly)

Returns the value of attribute body.



27
28
29
# File 'lib/aws4_signer/signature.rb', line 27

def body
  @body
end

#headersObject (readonly)

Returns the value of attribute headers.



27
28
29
# File 'lib/aws4_signer/signature.rb', line 27

def headers
  @headers
end

#regionObject (readonly)

Returns the value of attribute region.



27
28
29
# File 'lib/aws4_signer/signature.rb', line 27

def region
  @region
end

#secret_access_keyObject (readonly)

Returns the value of attribute secret_access_key.



27
28
29
# File 'lib/aws4_signer/signature.rb', line 27

def secret_access_key
  @secret_access_key
end

#serviceObject (readonly)

Returns the value of attribute service.



27
28
29
# File 'lib/aws4_signer/signature.rb', line 27

def service
  @service
end

#uriObject (readonly)

Returns the value of attribute uri.



27
28
29
# File 'lib/aws4_signer/signature.rb', line 27

def uri
  @uri
end

#verbObject (readonly)

Returns the value of attribute verb.



27
28
29
# File 'lib/aws4_signer/signature.rb', line 27

def verb
  @verb
end

Instance Method Details

#attach_to_http_request(req) ⇒ Object



29
30
31
32
33
34
35
36
37
38
# File 'lib/aws4_signer/signature.rb', line 29

def attach_to_http_request(req)
  headers.each do |name, value|
    req[name.downcase] = value
  end

  req["x-amz-content-sha256"] = Digest::SHA2.hexdigest(req.body || '', 256)
  req["authorization"] = authorization_header

  req
end

#authorization_headerObject



40
41
42
43
44
45
# File 'lib/aws4_signer/signature.rb', line 40

def authorization_header
  "AWS4-HMAC-SHA256 " \
    "Credential=#{@access_key_id}/#{scope}," \
    "SignedHeaders=#{signed_headers}," \
    "Signature=#{signature}"
end

#canonical_headersObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/aws4_signer/signature.rb', line 55

def canonical_headers
  @canonical_headers ||= begin
    signed = []
    hs = headers.sort_by { |name, _| name.downcase }.flat_map { |name, value|
      next if name == "Authorization"

      signed << name.downcase
      case value
      when Array
        value.each do |v|
          "#{name.downcase}:#{v.to_s.strip}\n"
        end
      else
        "#{name.downcase}:#{value.to_s.strip}\n"
      end
    }.compact.join.freeze

    @signed_headers = signed.join(";").freeze
    hs
  end
end

#canonical_requestObject



85
86
87
88
89
90
91
92
93
94
# File 'lib/aws4_signer/signature.rb', line 85

def canonical_request
  @canonical_request ||= [
    @verb.upcase,
    @uri.path,
    @uri.query,
    canonical_headers,
    signed_headers,
    hashed_payload,
  ].join("\n")
end

#dateObject



47
48
49
50
51
52
53
# File 'lib/aws4_signer/signature.rb', line 47

def date
  @date ||= begin
    time = Time.strptime(headers["x-amz-date"],"%Y%m%dT%H%M%SZ")
    time += time.utc_offset
    time.utc
  end
end

#date_keyObject



109
110
111
# File 'lib/aws4_signer/signature.rb', line 109

def date_key
  @date_key ||= hmac("AWS4#{@secret_access_key}", date.strftime("%Y%m%d"))
end

#date_region_keyObject



113
114
115
# File 'lib/aws4_signer/signature.rb', line 113

def date_region_key
  @date_region_key ||= hmac(date_key, region)
end

#date_region_service_keyObject



117
118
119
# File 'lib/aws4_signer/signature.rb', line 117

def date_region_service_key
  @date_region_service_key ||= hmac(date_region_key, service)
end

#hashed_payloadObject



81
82
83
# File 'lib/aws4_signer/signature.rb', line 81

def hashed_payload
  @hashed_payload ||= Digest::SHA2.hexdigest(body, 256)
end

#scopeObject



96
97
98
# File 'lib/aws4_signer/signature.rb', line 96

def scope
  "#{date.strftime("%Y%m%d")}/#{@region}/#{service}/aws4_request"
end

#signatureObject



125
126
127
# File 'lib/aws4_signer/signature.rb', line 125

def signature
  @signature ||= hmac(signing_key, string_to_sign, :hex)
end

#signed_headersObject



77
78
79
# File 'lib/aws4_signer/signature.rb', line 77

def signed_headers
  canonical_headers; @signed_headers
end

#signing_keyObject



121
122
123
# File 'lib/aws4_signer/signature.rb', line 121

def signing_key
  @signing_key ||= hmac(date_region_service_key, 'aws4_request')
end

#string_to_signObject



100
101
102
103
104
105
106
107
# File 'lib/aws4_signer/signature.rb', line 100

def string_to_sign
  @string_to_sign ||= [
    "AWS4-HMAC-SHA256",
    headers["x-amz-date"],
    scope,
    Digest::SHA2.hexdigest(canonical_request, 256),
  ].join("\n")
end