escher 0.0.2 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +21 -0
  6. data/README.md +8 -0
  7. data/Rakefile +11 -0
  8. data/escher.gemspec +26 -0
  9. data/lib/escher/version.rb +3 -0
  10. data/lib/escher.rb +254 -110
  11. data/spec/aws4_testsuite/get-header-key-duplicate.authz +1 -0
  12. data/spec/aws4_testsuite/get-header-key-duplicate.creq +9 -0
  13. data/spec/aws4_testsuite/get-header-key-duplicate.req +7 -0
  14. data/spec/aws4_testsuite/get-header-key-duplicate.sreq +8 -0
  15. data/spec/aws4_testsuite/get-header-key-duplicate.sts +4 -0
  16. data/spec/aws4_testsuite/get-header-value-multiline.req +7 -0
  17. data/spec/aws4_testsuite/get-header-value-order.authz +1 -0
  18. data/spec/aws4_testsuite/get-header-value-order.creq +9 -0
  19. data/spec/aws4_testsuite/get-header-value-order.req +8 -0
  20. data/spec/aws4_testsuite/get-header-value-order.sreq +9 -0
  21. data/spec/aws4_testsuite/get-header-value-order.sts +4 -0
  22. data/spec/aws4_testsuite/get-header-value-trim.authz +1 -0
  23. data/spec/aws4_testsuite/get-header-value-trim.creq +9 -0
  24. data/spec/aws4_testsuite/get-header-value-trim.req +5 -0
  25. data/spec/aws4_testsuite/get-header-value-trim.sreq +6 -0
  26. data/spec/aws4_testsuite/get-header-value-trim.sts +4 -0
  27. data/spec/aws4_testsuite/get-relative-relative.authz +1 -0
  28. data/spec/aws4_testsuite/get-relative-relative.creq +8 -0
  29. data/spec/aws4_testsuite/get-relative-relative.req +4 -0
  30. data/spec/aws4_testsuite/get-relative-relative.sreq +5 -0
  31. data/spec/aws4_testsuite/get-relative-relative.sts +4 -0
  32. data/spec/aws4_testsuite/get-relative.authz +1 -0
  33. data/spec/aws4_testsuite/get-relative.creq +8 -0
  34. data/spec/aws4_testsuite/get-relative.req +4 -0
  35. data/spec/aws4_testsuite/get-relative.sreq +5 -0
  36. data/spec/aws4_testsuite/get-relative.sts +4 -0
  37. data/spec/aws4_testsuite/get-slash-dot-slash.authz +1 -0
  38. data/spec/aws4_testsuite/get-slash-dot-slash.creq +8 -0
  39. data/spec/aws4_testsuite/get-slash-dot-slash.req +4 -0
  40. data/spec/aws4_testsuite/get-slash-dot-slash.sreq +5 -0
  41. data/spec/aws4_testsuite/get-slash-dot-slash.sts +4 -0
  42. data/spec/aws4_testsuite/get-slash-pointless-dot.authz +1 -0
  43. data/spec/aws4_testsuite/get-slash-pointless-dot.creq +8 -0
  44. data/spec/aws4_testsuite/get-slash-pointless-dot.req +4 -0
  45. data/spec/aws4_testsuite/get-slash-pointless-dot.sreq +5 -0
  46. data/spec/aws4_testsuite/get-slash-pointless-dot.sts +4 -0
  47. data/spec/aws4_testsuite/get-slash.authz +1 -0
  48. data/spec/aws4_testsuite/get-slash.creq +8 -0
  49. data/spec/aws4_testsuite/get-slash.req +4 -0
  50. data/spec/aws4_testsuite/get-slash.sreq +5 -0
  51. data/spec/aws4_testsuite/get-slash.sts +4 -0
  52. data/spec/aws4_testsuite/get-slashes.authz +1 -0
  53. data/spec/aws4_testsuite/get-slashes.creq +8 -0
  54. data/spec/aws4_testsuite/get-slashes.req +4 -0
  55. data/spec/aws4_testsuite/get-slashes.sreq +5 -0
  56. data/spec/aws4_testsuite/get-slashes.sts +4 -0
  57. data/spec/aws4_testsuite/get-space.authz +1 -0
  58. data/spec/aws4_testsuite/get-space.creq +8 -0
  59. data/spec/aws4_testsuite/get-space.req +4 -0
  60. data/spec/aws4_testsuite/get-space.sreq +5 -0
  61. data/spec/aws4_testsuite/get-space.sts +4 -0
  62. data/spec/aws4_testsuite/get-unreserved.authz +1 -0
  63. data/spec/aws4_testsuite/get-unreserved.creq +8 -0
  64. data/spec/aws4_testsuite/get-unreserved.req +4 -0
  65. data/spec/aws4_testsuite/get-unreserved.sreq +5 -0
  66. data/spec/aws4_testsuite/get-unreserved.sts +4 -0
  67. data/spec/aws4_testsuite/get-utf8.authz +1 -0
  68. data/spec/aws4_testsuite/get-utf8.creq +8 -0
  69. data/spec/aws4_testsuite/get-utf8.req +4 -0
  70. data/spec/aws4_testsuite/get-utf8.sreq +5 -0
  71. data/spec/aws4_testsuite/get-utf8.sts +4 -0
  72. data/spec/aws4_testsuite/get-vanilla-empty-query-key.authz +1 -0
  73. data/spec/aws4_testsuite/get-vanilla-empty-query-key.creq +8 -0
  74. data/spec/aws4_testsuite/get-vanilla-empty-query-key.req +4 -0
  75. data/spec/aws4_testsuite/get-vanilla-empty-query-key.sreq +5 -0
  76. data/spec/aws4_testsuite/get-vanilla-empty-query-key.sts +4 -0
  77. data/spec/aws4_testsuite/get-vanilla-query-order-key-case.authz +1 -0
  78. data/spec/aws4_testsuite/get-vanilla-query-order-key-case.creq +8 -0
  79. data/spec/aws4_testsuite/get-vanilla-query-order-key-case.req +4 -0
  80. data/spec/aws4_testsuite/get-vanilla-query-order-key-case.sreq +5 -0
  81. data/spec/aws4_testsuite/get-vanilla-query-order-key-case.sts +4 -0
  82. data/spec/aws4_testsuite/get-vanilla-query-order-key.authz +1 -0
  83. data/spec/aws4_testsuite/get-vanilla-query-order-key.creq +8 -0
  84. data/spec/aws4_testsuite/get-vanilla-query-order-key.req +4 -0
  85. data/spec/aws4_testsuite/get-vanilla-query-order-key.sreq +5 -0
  86. data/spec/aws4_testsuite/get-vanilla-query-order-key.sts +4 -0
  87. data/spec/aws4_testsuite/get-vanilla-query-order-value.authz +1 -0
  88. data/spec/aws4_testsuite/get-vanilla-query-order-value.creq +8 -0
  89. data/spec/aws4_testsuite/get-vanilla-query-order-value.req +4 -0
  90. data/spec/aws4_testsuite/get-vanilla-query-order-value.sreq +5 -0
  91. data/spec/aws4_testsuite/get-vanilla-query-order-value.sts +4 -0
  92. data/spec/aws4_testsuite/get-vanilla-query-unreserved.authz +1 -0
  93. data/spec/aws4_testsuite/get-vanilla-query-unreserved.creq +8 -0
  94. data/spec/aws4_testsuite/get-vanilla-query-unreserved.req +4 -0
  95. data/spec/aws4_testsuite/get-vanilla-query-unreserved.sreq +5 -0
  96. data/spec/aws4_testsuite/get-vanilla-query-unreserved.sts +4 -0
  97. data/spec/aws4_testsuite/get-vanilla-query.authz +1 -0
  98. data/spec/aws4_testsuite/get-vanilla-query.creq +8 -0
  99. data/spec/aws4_testsuite/get-vanilla-query.req +4 -0
  100. data/spec/aws4_testsuite/get-vanilla-query.sreq +5 -0
  101. data/spec/aws4_testsuite/get-vanilla-query.sts +4 -0
  102. data/spec/aws4_testsuite/get-vanilla-ut8-query.authz +1 -0
  103. data/spec/aws4_testsuite/get-vanilla-ut8-query.creq +8 -0
  104. data/spec/aws4_testsuite/get-vanilla-ut8-query.req +4 -0
  105. data/spec/aws4_testsuite/get-vanilla-ut8-query.sreq +5 -0
  106. data/spec/aws4_testsuite/get-vanilla-ut8-query.sts +4 -0
  107. data/spec/aws4_testsuite/get-vanilla.authz +1 -0
  108. data/spec/aws4_testsuite/get-vanilla.creq +8 -0
  109. data/spec/aws4_testsuite/get-vanilla.req +4 -0
  110. data/spec/aws4_testsuite/get-vanilla.sreq +5 -0
  111. data/spec/aws4_testsuite/get-vanilla.sts +4 -0
  112. data/spec/aws4_testsuite/post-header-key-case.authz +1 -0
  113. data/spec/aws4_testsuite/post-header-key-case.creq +8 -0
  114. data/spec/aws4_testsuite/post-header-key-case.req +4 -0
  115. data/spec/aws4_testsuite/post-header-key-case.sreq +5 -0
  116. data/spec/aws4_testsuite/post-header-key-case.sts +4 -0
  117. data/spec/aws4_testsuite/post-header-key-sort.authz +1 -0
  118. data/spec/aws4_testsuite/post-header-key-sort.creq +9 -0
  119. data/spec/aws4_testsuite/post-header-key-sort.req +5 -0
  120. data/spec/aws4_testsuite/post-header-key-sort.sreq +6 -0
  121. data/spec/aws4_testsuite/post-header-key-sort.sts +4 -0
  122. data/spec/aws4_testsuite/post-header-value-case.authz +1 -0
  123. data/spec/aws4_testsuite/post-header-value-case.creq +9 -0
  124. data/spec/aws4_testsuite/post-header-value-case.req +5 -0
  125. data/spec/aws4_testsuite/post-header-value-case.sreq +6 -0
  126. data/spec/aws4_testsuite/post-header-value-case.sts +4 -0
  127. data/spec/aws4_testsuite/post-vanilla-empty-query-value.authz +1 -0
  128. data/spec/aws4_testsuite/post-vanilla-empty-query-value.creq +8 -0
  129. data/spec/aws4_testsuite/post-vanilla-empty-query-value.req +4 -0
  130. data/spec/aws4_testsuite/post-vanilla-empty-query-value.sreq +5 -0
  131. data/spec/aws4_testsuite/post-vanilla-empty-query-value.sts +4 -0
  132. data/spec/aws4_testsuite/post-vanilla-query-nonunreserved.authz +1 -0
  133. data/spec/aws4_testsuite/post-vanilla-query-nonunreserved.creq +8 -0
  134. data/spec/aws4_testsuite/post-vanilla-query-nonunreserved.req +4 -0
  135. data/spec/aws4_testsuite/post-vanilla-query-nonunreserved.sreq +5 -0
  136. data/spec/aws4_testsuite/post-vanilla-query-nonunreserved.sts +4 -0
  137. data/spec/aws4_testsuite/post-vanilla-query-space.authz +1 -0
  138. data/spec/aws4_testsuite/post-vanilla-query-space.creq +8 -0
  139. data/spec/aws4_testsuite/post-vanilla-query-space.req +4 -0
  140. data/spec/aws4_testsuite/post-vanilla-query-space.sreq +5 -0
  141. data/spec/aws4_testsuite/post-vanilla-query-space.sts +4 -0
  142. data/spec/aws4_testsuite/post-vanilla-query.authz +1 -0
  143. data/spec/aws4_testsuite/post-vanilla-query.creq +8 -0
  144. data/spec/aws4_testsuite/post-vanilla-query.req +4 -0
  145. data/spec/aws4_testsuite/post-vanilla-query.sreq +5 -0
  146. data/spec/aws4_testsuite/post-vanilla-query.sts +4 -0
  147. data/spec/aws4_testsuite/post-vanilla.authz +1 -0
  148. data/spec/aws4_testsuite/post-vanilla.creq +8 -0
  149. data/spec/aws4_testsuite/post-vanilla.req +4 -0
  150. data/spec/aws4_testsuite/post-vanilla.sreq +5 -0
  151. data/spec/aws4_testsuite/post-vanilla.sts +4 -0
  152. data/spec/aws4_testsuite/post-x-www-form-urlencoded-parameters.authz +1 -0
  153. data/spec/aws4_testsuite/post-x-www-form-urlencoded-parameters.creq +9 -0
  154. data/spec/aws4_testsuite/post-x-www-form-urlencoded-parameters.req +6 -0
  155. data/spec/aws4_testsuite/post-x-www-form-urlencoded-parameters.sreq +7 -0
  156. data/spec/aws4_testsuite/post-x-www-form-urlencoded-parameters.sts +4 -0
  157. data/spec/aws4_testsuite/post-x-www-form-urlencoded.authz +1 -0
  158. data/spec/aws4_testsuite/post-x-www-form-urlencoded.creq +9 -0
  159. data/spec/aws4_testsuite/post-x-www-form-urlencoded.req +6 -0
  160. data/spec/aws4_testsuite/post-x-www-form-urlencoded.sreq +7 -0
  161. data/spec/aws4_testsuite/post-x-www-form-urlencoded.sts +4 -0
  162. data/spec/emarsys_testsuite/get-header-key-duplicate.authz +1 -0
  163. data/spec/emarsys_testsuite/get-header-key-duplicate.creq +9 -0
  164. data/spec/emarsys_testsuite/get-header-key-duplicate.req +7 -0
  165. data/spec/emarsys_testsuite/get-header-key-duplicate.sreq +8 -0
  166. data/spec/emarsys_testsuite/get-header-key-duplicate.sts +4 -0
  167. data/spec/emarsys_testsuite/get-header-value-order.authz +1 -0
  168. data/spec/emarsys_testsuite/get-header-value-order.creq +9 -0
  169. data/spec/emarsys_testsuite/get-header-value-order.req +8 -0
  170. data/spec/emarsys_testsuite/get-header-value-order.sreq +9 -0
  171. data/spec/emarsys_testsuite/get-header-value-order.sts +4 -0
  172. data/spec/emarsys_testsuite/post-header-key-order.authz +1 -0
  173. data/spec/emarsys_testsuite/post-header-key-order.creq +9 -0
  174. data/spec/emarsys_testsuite/post-header-key-order.req +6 -0
  175. data/spec/emarsys_testsuite/post-header-key-order.sreq +7 -0
  176. data/spec/emarsys_testsuite/post-header-key-order.sts +4 -0
  177. data/spec/emarsys_testsuite/post-header-value-spaces-within-quotes.authz +1 -0
  178. data/spec/emarsys_testsuite/post-header-value-spaces-within-quotes.creq +9 -0
  179. data/spec/emarsys_testsuite/post-header-value-spaces-within-quotes.req +5 -0
  180. data/spec/emarsys_testsuite/post-header-value-spaces-within-quotes.sreq +6 -0
  181. data/spec/emarsys_testsuite/post-header-value-spaces-within-quotes.sts +4 -0
  182. data/spec/emarsys_testsuite/post-header-value-spaces.authz +1 -0
  183. data/spec/emarsys_testsuite/post-header-value-spaces.creq +9 -0
  184. data/spec/emarsys_testsuite/post-header-value-spaces.req +6 -0
  185. data/spec/emarsys_testsuite/post-header-value-spaces.sreq +7 -0
  186. data/spec/emarsys_testsuite/post-header-value-spaces.sts +4 -0
  187. data/spec/escher_spec.rb +306 -0
  188. data/spec/spec_helper.rb +1 -0
  189. metadata +402 -31
@@ -0,0 +1,306 @@
1
+ require'spec_helper'
2
+
3
+ test_suites = {
4
+ # 'get-header-key-duplicate',
5
+ # 'get-header-value-order',
6
+ aws4: %w(
7
+ get-header-value-trim
8
+ get-relative
9
+ get-relative-relative
10
+ get-slash
11
+ get-slash-dot-slash
12
+ get-slash-pointless-dot
13
+ get-slashes
14
+ get-space
15
+ get-unreserved
16
+ get-utf8
17
+ get-vanilla
18
+ get-vanilla-empty-query-key
19
+ get-vanilla-query
20
+ get-vanilla-query-order-key
21
+ get-vanilla-query-order-key-case
22
+ get-vanilla-query-order-value
23
+ get-vanilla-query-unreserved
24
+ get-vanilla-ut8-query
25
+ post-header-key-case
26
+ post-header-key-sort
27
+ post-header-value-case
28
+ post-vanilla
29
+ post-vanilla-empty-query-value
30
+ post-vanilla-query
31
+ post-vanilla-query-nonunreserved
32
+ post-vanilla-query-space
33
+ post-x-www-form-urlencoded
34
+ post-x-www-form-urlencoded-parameters
35
+ ),
36
+ emarsys: %w(
37
+ get-header-key-duplicate
38
+ post-header-key-order
39
+ post-header-value-spaces
40
+ post-header-value-spaces-within-quotes
41
+ )
42
+ }
43
+
44
+ ESCHER_AWS4_OPTIONS = {
45
+ algo_prefix: 'AWS4', vendor_key: 'AWS4', hash_algo: 'SHA256', auth_header_name: 'Authorization', date_header_name: 'Date'
46
+ }
47
+
48
+ ESCHER_EMARSYS_OPTIONS = {
49
+ algo_prefix: 'EMS', vendor_key: 'EMS', hash_algo: 'SHA256', auth_header_name: 'Authorization', date_header_name: 'Date', clock_skew: 10
50
+ }
51
+
52
+ GOOD_AUTH_HEADER = 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470'
53
+
54
+ # noinspection RubyStringKeysInHashInspection
55
+ def key_db
56
+ {
57
+ 'AKIDEXAMPLE' => 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY',
58
+ 'th3K3y' => 'very_secure',
59
+ }
60
+ end
61
+
62
+ def credential_scope
63
+ %w(us-east-1 host aws4_request)
64
+ end
65
+
66
+ def client
67
+ {:api_key_id => 'AKIDEXAMPLE', :api_secret => 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'}
68
+ end
69
+
70
+ describe 'Escher' do
71
+ test_suites.each do |suite, tests|
72
+ tests.each do |test|
73
+ it "should calculate canonicalized request for #{test} in #{suite}" do
74
+ escher = Escher.new('us-east-1/host/aws4_request', ESCHER_AWS4_OPTIONS)
75
+ method, request_uri, body, headers = read_request(suite, test)
76
+ headers_to_sign = headers.map {|k| k[0].downcase }
77
+ path, query_parts = escher.parse_uri(request_uri)
78
+ canonicalized_request = escher.canonicalize(method, path, query_parts, body, headers, headers_to_sign)
79
+ check_canonicalized_request(canonicalized_request, suite, test)
80
+ end
81
+ end
82
+ end
83
+
84
+ test_suites.each do |suite, tests|
85
+ tests.each do |test|
86
+ it "should calculate string to sign for #{test} in #{suite}" do
87
+ method, request_uri, body, headers, date = read_request(suite, test)
88
+ escher = Escher.new('us-east-1/host/aws4_request', ESCHER_AWS4_OPTIONS.merge(current_time: Time.parse(date)))
89
+ headers_to_sign = headers.map {|k| k[0].downcase }
90
+ path, query_parts = escher.parse_uri(request_uri)
91
+ canonicalized_request = escher.canonicalize(method, path, query_parts, body, headers, headers_to_sign)
92
+ string_to_sign = escher.get_string_to_sign(canonicalized_request)
93
+ expect(string_to_sign).to eq(fixture(suite, test, 'sts'))
94
+ end
95
+ end
96
+ end
97
+
98
+ test_suites.each do |suite, tests|
99
+ tests.each do |test|
100
+ it "should calculate auth header for #{test} in #{suite}" do
101
+ method, request_uri, body, headers, date, host = read_request(suite, test)
102
+ escher = Escher.new('us-east-1/host/aws4_request', ESCHER_AWS4_OPTIONS.merge(current_time: Time.parse(date)))
103
+ 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)
105
+ expect(auth_header).to eq(fixture(suite, test, 'authz'))
106
+ end
107
+ end
108
+ end
109
+
110
+ 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')))
112
+ expected_url =
113
+ 'http://example.com/something?foo=bar&' + 'baz=barbaz&' +
114
+ 'X-EMS-Algorithm=EMS-HMAC-SHA256&' +
115
+ 'X-EMS-Credentials=th3K3y%2F20110511%2Fus-east-1%2Fhost%2Faws4_request&' +
116
+ 'X-EMS-Date=20110511T120000Z&' +
117
+ 'X-EMS-Expires=123456&' +
118
+ 'X-EMS-SignedHeaders=host&' +
119
+ 'X-EMS-Signature=fbc9dbb91670e84d04ad2ae7505f4f52ab3ff9e192b8233feeae57e9022c2b67'
120
+
121
+ client = {:api_key_id => 'th3K3y', :api_secret => 'very_secure'}
122
+ expect(escher.generate_signed_url('http://example.com/something?foo=bar&baz=barbaz', client, 123456)).to eq expected_url
123
+ end
124
+
125
+ 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')))
127
+ presigned_uri =
128
+ '/something?foo=bar&' + 'baz=barbaz&' +
129
+ 'X-EMS-Algorithm=EMS-HMAC-SHA256&' +
130
+ 'X-EMS-Credentials=th3K3y%2F20110511%2Fus-east-1%2Fhost%2Faws4_request&' +
131
+ 'X-EMS-Date=20110511T120000Z&' +
132
+ 'X-EMS-Expires=123456&' +
133
+ 'X-EMS-SignedHeaders=host&' +
134
+ 'X-EMS-Signature=fbc9dbb91670e84d04ad2ae7505f4f52ab3ff9e192b8233feeae57e9022c2b67'
135
+
136
+ client = {:api_key_id => 'th3K3y', :api_secret => 'very_secure'}
137
+ expect { escher.validate_request(key_db, 'GET', presigned_uri, 'IRRELEVANT', [%w(host example.com)]) }.not_to raise_error
138
+ end
139
+
140
+ it 'should validate expiration' do
141
+ escher = Escher.new('us-east-1/host/aws4_request', ESCHER_EMARSYS_OPTIONS.merge(current_time: Time.parse('2011/05/12 22:20:00 UTC')))
142
+ presigned_uri =
143
+ '/something?foo=bar&' + 'baz=barbaz&' +
144
+ 'X-EMS-Algorithm=EMS-HMAC-SHA256&' +
145
+ 'X-EMS-Credentials=th3K3y%2F20110511%2Fus-east-1%2Fhost%2Faws4_request&' +
146
+ 'X-EMS-Date=20110511T120000Z&' +
147
+ 'X-EMS-Expires=123456&' +
148
+ 'X-EMS-SignedHeaders=host&' +
149
+ 'X-EMS-Signature=fbc9dbb91670e84d04ad2ae7505f4f52ab3ff9e192b8233feeae57e9022c2b67'
150
+
151
+ client = {:api_key_id => 'th3K3y', :api_secret => 'very_secure'}
152
+ expect { escher.validate_request(key_db, 'GET', presigned_uri, 'IRRELEVANT', [%w(host example.com)]) }
153
+ .to raise_error(EscherError, 'The request date is not within the accepted time range')
154
+ end
155
+
156
+ it 'should validate request' do
157
+ headers = [
158
+ %w(Host host.foo.com),
159
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
160
+ ['Authorization', GOOD_AUTH_HEADER],
161
+ ]
162
+ expect { call_validate_request(headers) }.not_to raise_error
163
+ end
164
+
165
+ it 'should detect if signatures do not match' do
166
+ headers = [
167
+ %w(Host host.foo.com),
168
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
169
+ ['Authorization', 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'],
170
+ ]
171
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'The signatures do not match')
172
+ end
173
+
174
+ it 'should detect if dates are not on the same day' do
175
+ yesterday = '08'
176
+ headers = [
177
+ %w(Host host.foo.com),
178
+ ['Date', "Mon, #{yesterday} Sep 2011 23:36:00 GMT"],
179
+ ['Authorization', GOOD_AUTH_HEADER],
180
+ ]
181
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Invalid request date')
182
+ end
183
+
184
+ it 'should detect if date is not within the 15 minutes range' do
185
+ long_ago = '00'
186
+ headers = [
187
+ %w(Host host.foo.com),
188
+ ['Date', "Mon, 09 Sep 2011 23:#{long_ago}:00 GMT"],
189
+ ['Authorization', GOOD_AUTH_HEADER],
190
+ ]
191
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'The request date is not within the accepted time range')
192
+ end
193
+
194
+ it 'should detect missing host header' do
195
+ headers = [
196
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
197
+ ['Authorization', GOOD_AUTH_HEADER],
198
+ ]
199
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Missing header: Host')
200
+ end
201
+
202
+ it 'should detect missing date header' do
203
+ headers = [
204
+ %w(Host host.foo.com),
205
+ ['Authorization', GOOD_AUTH_HEADER],
206
+ ]
207
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Missing header: Date')
208
+ end
209
+
210
+ it 'should detect missing auth header' do
211
+ headers = [
212
+ %w(Host host.foo.com),
213
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
214
+ ]
215
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Missing header: Authorization')
216
+ end
217
+
218
+ it 'should detect malformed auth header' do
219
+ headers = [
220
+ %w(Host host.foo.com),
221
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
222
+ ['Authorization', 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=UNPARSABLE'],
223
+ ]
224
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Malformed authorization header')
225
+ end
226
+
227
+ it 'should detect malformed credential scope' do
228
+ headers = [
229
+ %w(Host host.foo.com),
230
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
231
+ ['Authorization', 'AWS4-HMAC-SHA256 Credential=BAD-CREDENTIAL-SCOPE, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470'],
232
+ ]
233
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Malformed authorization header')
234
+ end
235
+
236
+ it 'should check mandatory signed headers: host' do
237
+ headers = [
238
+ %w(Host host.foo.com),
239
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
240
+ ['Authorization', 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470'],
241
+ ]
242
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Host header is not signed')
243
+ end
244
+
245
+ it 'should check mandatory signed headers: date' do
246
+ headers = [
247
+ %w(Host host.foo.com),
248
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
249
+ ['Authorization', 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470'],
250
+ ]
251
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Date header is not signed')
252
+ end
253
+
254
+ it 'should check algorithm' do
255
+ headers = [
256
+ %w(Host host.foo.com),
257
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
258
+ ['Authorization', 'AWS4-HMAC-INVALID Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470'],
259
+ ]
260
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Only SHA256 and SHA512 hash algorithms are allowed')
261
+ end
262
+
263
+ it 'should check credential scope' do
264
+ headers = [
265
+ %w(Host host.foo.com),
266
+ ['Date', 'Mon, 09 Sep 2011 23:36:00 GMT'],
267
+ ['Authorization', 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/INVALID/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470'],
268
+ ]
269
+ expect { call_validate_request(headers) }.to raise_error(EscherError, 'Invalid credentials')
270
+ end
271
+
272
+ it 'should convert dates' do
273
+ date_str = 'Fri, 09 Sep 2011 23:36:00 GMT'
274
+ expect(Escher.new('irrelevant', date_header_name: 'date', current_time: Time.parse(date_str)).format_date_for_header).to eq date_str
275
+ end
276
+
277
+ def call_validate_request(headers)
278
+ escher = Escher.new('us-east-1/host/aws4_request', ESCHER_AWS4_OPTIONS.merge(current_time: Time.parse('Mon, 09 Sep 2011 23:40:00 GMT')))
279
+ escher.validate_request(key_db, 'GET', '/', '', headers)
280
+ end
281
+
282
+ end
283
+
284
+ def fixture(suite, test, extension)
285
+ open("spec/#{suite}_testsuite/#{test}.#{extension}").read
286
+ end
287
+
288
+ def get_host(headers)
289
+ headers.detect {|header| header[0].downcase == 'host'}[1]
290
+ end
291
+
292
+ def get_date(headers)
293
+ headers.detect {|header| header[0].downcase == 'date'}[1]
294
+ end
295
+
296
+ def read_request(suite, test, extension = 'req')
297
+ lines = (fixture(suite, test, extension) + "\n").lines.map(&:chomp)
298
+ method, request_uri = lines[0].split ' '
299
+ headers = lines[1..-3].map { |header| k, v = header.split(':', 2); [k, v] }
300
+ request_body = lines[-1]
301
+ [method, request_uri, request_body, headers, get_date(headers), get_host(headers)]
302
+ end
303
+
304
+ def check_canonicalized_request(creq, suite, test)
305
+ expect(creq).to eq(fixture(suite, test, 'creq'))
306
+ end
@@ -0,0 +1 @@
1
+ require 'escher'