escher 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2c7d0c11568986e6d42c2d60a853da006ce45484
4
- data.tar.gz: 867865591e198f3466bfe1872ab87e17cdb47429
3
+ metadata.gz: ba40c7a7b12bb5aec126c7151b4a8cf81eaa3f51
4
+ data.tar.gz: 3fa09ffdec0d12b2bb7deaaf9aa30cecc23dfe63
5
5
  SHA512:
6
- metadata.gz: 674aadece40c90e9affccc8a23a1ed12ee2c86512bd627134cb266ce8cbf4ace7693201114e5ff451b49fc6ca80eca074b4ca4969481d210284ed3b9eba04cf7
7
- data.tar.gz: 92c61fbad4a295131b23fae67e1429e10e53b807c4e474fcd1357d72fe896782650bcea4865c0f1d690c83d724a175779c836955e1412c44f0e60d1e9e36096c
6
+ metadata.gz: b5060b34740b6300e7f9abef1ee5ef32c4470336dbf956d74047a9e9048e5990b9755738f650221db734493d3a0ad27101905c669111edbda9e9b52f9dbce555
7
+ data.tar.gz: 4fdcfda5426410a5ba9b465099630d626a72ce105bffdd968765ac284bdbfe79057a594f942822cbb2b9c351a72c94a702f86ad4134de81a965cf56f839ec07d
data/lib/escher/base.rb CHANGED
@@ -21,13 +21,26 @@ class Escher
21
21
  @clock_skew = options[:clock_skew] || 900
22
22
  end
23
23
 
24
- def sign!(req, client)
25
- request = EscherRequest.new(req)
26
- auth_header = generate_auth_header(client, request.method, uri_parsed.host, uri_parsed.path, request.body || '', request.to_enum.to_a, [])
24
+ def sign!(request, client, headers_to_sign = [])
25
+ uri = Addressable::URI.parse(request[:uri])
26
+ body = request[:body] || ''
27
+ headers = request[:headers].map {|k, v| {k.downcase => v} }.reduce({}, &:merge)
28
+
29
+ host = headers['host'] || uri.host || request[:host]
30
+
31
+ unless headers.has_key? 'host'
32
+ headers['host'] = host
33
+ end
34
+ unless headers.has_key? @date_header_name
35
+ headers[@date_header_name] = format_date_for_header
36
+ end
37
+
38
+ headers_to_sign |= [@date_header_name.downcase, 'host']
39
+
27
40
 
28
- request.set_header('Host', request.host) # TODO: we shouldn't remove port from Host here
29
- request.set_header(@date_header_name, format_date_for_header)
30
- request.set_header(@auth_header_name, auth_header)
41
+ auth_header = generate_auth_header(client, request[:method], uri.path + (uri.query ? '?' + uri.query : ''), body, headers.map { |k, v| [k, v] }, headers_to_sign)
42
+
43
+ request[:headers] = headers.merge(@auth_header_name => auth_header)
31
44
  request
32
45
  end
33
46
 
@@ -101,10 +114,8 @@ class Escher
101
114
  )
102
115
  end
103
116
 
104
- def generate_auth_header(client, method, host, request_uri, body, headers, headers_to_sign)
117
+ def generate_auth_header(client, method, request_uri, body, headers, headers_to_sign)
105
118
  path, query_parts = parse_uri(request_uri)
106
- headers = add_defaults_to(headers, host)
107
- headers_to_sign |= [@date_header_name.downcase, 'host']
108
119
  signature = generate_signature(client[:api_secret], body, headers, method, headers_to_sign, path, query_parts)
109
120
  "#{get_algorithm_id} Credential=#{client[:api_key_id]}/#{short_date(@current_time)}/#{@credential_scope}, SignedHeaders=#{prepare_headers_to_sign headers_to_sign}, Signature=#{signature}"
110
121
  end
@@ -182,21 +193,10 @@ class Escher
182
193
  Digest::HMAC.hexdigest(string_to_sign, signing_key, create_algo)
183
194
  end
184
195
 
185
- def add_defaults_to(headers, host)
186
- [['host', host], [@date_header_name, format_date_for_header]]
187
- .each { |k, v| headers = add_if_missing headers, k, v }
188
- headers
189
- end
190
-
191
196
  def format_date_for_header
192
197
  @date_header_name.downcase == 'date' ? @current_time.utc.rfc2822.sub('-0000', 'GMT') : long_date(@current_time)
193
198
  end
194
199
 
195
- def add_if_missing(headers, header_to_find, value)
196
- headers += [header_to_find, value] unless headers.find { |header| header[0].downcase == header_to_find.downcase }
197
- headers
198
- end
199
-
200
200
  def canonicalize(method, path, query_parts, body, headers, headers_to_sign) [
201
201
  method,
202
202
  canonicalize_path(path),
@@ -3,7 +3,9 @@ class EscherRequest
3
3
 
4
4
  def initialize(request)
5
5
  @request = request
6
- @request_uri = Addressable::URI.parse(uri)
6
+ request_uri = Addressable::URI.parse(uri)
7
+ raise "Invalid request URI: #{request_uri}" unless request_uri
8
+ @request_uri = request_uri
7
9
  prepare_request_headers
8
10
  end
9
11
 
@@ -66,6 +68,10 @@ class EscherRequest
66
68
  end
67
69
  end
68
70
 
71
+ def host
72
+ @request_uri.host
73
+ end
74
+
69
75
  def path
70
76
  @request_uri.path
71
77
  end
@@ -1,3 +1,3 @@
1
1
  class Escher
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.1'
3
3
  end
data/spec/escher_spec.rb CHANGED
@@ -45,10 +45,12 @@ ESCHER_AWS4_OPTIONS = {
45
45
  algo_prefix: 'AWS4', vendor_key: 'AWS4', hash_algo: 'SHA256', auth_header_name: 'Authorization', date_header_name: 'Date'
46
46
  }
47
47
 
48
- ESCHER_EMARSYS_OPTIONS = {
48
+ ESCHER_MIXED_OPTIONS = {
49
49
  algo_prefix: 'EMS', vendor_key: 'EMS', hash_algo: 'SHA256', auth_header_name: 'Authorization', date_header_name: 'Date', clock_skew: 10
50
50
  }
51
51
 
52
+ ESCHER_EMARSYS_OPTIONS = ESCHER_MIXED_OPTIONS.merge(auth_header_name: 'X-Ems-Auth', date_header_name: 'X-Ems-Date')
53
+
52
54
  GOOD_AUTH_HEADER = 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470'
53
55
 
54
56
  # noinspection RubyStringKeysInHashInspection
@@ -98,17 +100,44 @@ describe 'Escher' do
98
100
  test_suites.each do |suite, tests|
99
101
  tests.each do |test|
100
102
  it "should calculate auth header for #{test} in #{suite}" do
101
- method, request_uri, body, headers, date, host = read_request(suite, test)
103
+ method, request_uri, body, headers, date = read_request(suite, test)
102
104
  escher = Escher.new('us-east-1/host/aws4_request', ESCHER_AWS4_OPTIONS.merge(current_time: Time.parse(date)))
103
105
  headers_to_sign = headers.map {|k| k[0].downcase }
104
- auth_header = escher.generate_auth_header(client, method, host, request_uri, body, headers, headers_to_sign)
106
+ auth_header = escher.generate_auth_header(client, method, request_uri, body, headers, headers_to_sign)
105
107
  expect(auth_header).to eq(fixture(suite, test, 'authz'))
106
108
  end
107
109
  end
108
110
  end
109
111
 
112
+ it 'should sign request' do
113
+ escher = Escher.new('us-east-1/iam/aws4_request', ESCHER_EMARSYS_OPTIONS.merge(current_time: Time.parse('20110909T233600Z')))
114
+ client = { :api_key_id => 'AKIDEXAMPLE', :api_secret => 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY' }
115
+
116
+ input_headers = {
117
+ 'content-type' => 'application/x-www-form-urlencoded; charset=utf-8'
118
+ }
119
+
120
+ expected_headers = {
121
+ 'content-type' => 'application/x-www-form-urlencoded; charset=utf-8',
122
+ 'host' => 'iam.amazonaws.com',
123
+ 'x-ems-date' => '20110909T233600Z',
124
+ 'x-ems-auth' => 'EMS-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/iam/aws4_request, SignedHeaders=content-type;host;x-ems-date, Signature=f36c21c6e16a71a6e8dc56673ad6354aeef49c577a22fd58a190b5fcf8891dbd',
125
+ }
126
+ headers_to_sign = %w(content-type)
127
+
128
+ request = {
129
+ method: 'POST',
130
+ uri: 'http://iam.amazonaws.com/',
131
+ body: 'Action=ListUsers&Version=2010-05-08',
132
+ headers: input_headers,
133
+ }
134
+
135
+ downcase = escher.sign!(request, client, headers_to_sign)[:headers].map { |k, v| { k.downcase => v } }.reduce({}, &:merge)
136
+ expect(downcase).to eq expected_headers
137
+ end
138
+
110
139
  it 'should generate presigned url' do
111
- escher = Escher.new('us-east-1/host/aws4_request', ESCHER_EMARSYS_OPTIONS.merge(current_time: Time.parse('2011/05/11 12:00:00 UTC')))
140
+ escher = Escher.new('us-east-1/host/aws4_request', ESCHER_MIXED_OPTIONS.merge(current_time: Time.parse('2011/05/11 12:00:00 UTC')))
112
141
  expected_url =
113
142
  'http://example.com/something?foo=bar&' + 'baz=barbaz&' +
114
143
  'X-EMS-Algorithm=EMS-HMAC-SHA256&' +
@@ -123,7 +152,7 @@ describe 'Escher' do
123
152
  end
124
153
 
125
154
  it 'should validate presigned url' do
126
- escher = Escher.new('us-east-1/host/aws4_request', ESCHER_EMARSYS_OPTIONS.merge(current_time: Time.parse('2011/05/12 21:59:00 UTC')))
155
+ escher = Escher.new('us-east-1/host/aws4_request', ESCHER_MIXED_OPTIONS.merge(current_time: Time.parse('2011/05/12 21:59:00 UTC')))
127
156
  presigned_uri =
128
157
  '/something?foo=bar&' + 'baz=barbaz&' +
129
158
  'X-EMS-Algorithm=EMS-HMAC-SHA256&' +
@@ -143,7 +172,7 @@ describe 'Escher' do
143
172
  end
144
173
 
145
174
  it 'should validate expiration' do
146
- escher = Escher.new('us-east-1/host/aws4_request', ESCHER_EMARSYS_OPTIONS.merge(current_time: Time.parse('2011/05/12 22:20:00 UTC')))
175
+ escher = Escher.new('us-east-1/host/aws4_request', ESCHER_MIXED_OPTIONS.merge(current_time: Time.parse('2011/05/12 22:20:00 UTC')))
147
176
  presigned_uri =
148
177
  '/something?foo=bar&' + 'baz=barbaz&' +
149
178
  'X-EMS-Algorithm=EMS-HMAC-SHA256&' +
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: escher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andras Barthazi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-17 00:00:00.000000000 Z
11
+ date: 2014-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler