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 +4 -4
- data/lib/escher/base.rb +20 -20
- data/lib/escher/request.rb +7 -1
- data/lib/escher/version.rb +1 -1
- data/spec/escher_spec.rb +35 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba40c7a7b12bb5aec126c7151b4a8cf81eaa3f51
|
4
|
+
data.tar.gz: 3fa09ffdec0d12b2bb7deaaf9aa30cecc23dfe63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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!(
|
25
|
-
|
26
|
-
|
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.
|
29
|
-
|
30
|
-
request.
|
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,
|
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),
|
data/lib/escher/request.rb
CHANGED
@@ -3,7 +3,9 @@ class EscherRequest
|
|
3
3
|
|
4
4
|
def initialize(request)
|
5
5
|
@request = request
|
6
|
-
|
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
|
data/lib/escher/version.rb
CHANGED
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
|
-
|
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
|
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,
|
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',
|
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',
|
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',
|
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.
|
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-
|
11
|
+
date: 2014-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|