rack-attack 5.4.1 → 6.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +78 -27
  3. data/Rakefile +3 -1
  4. data/lib/rack/attack.rb +138 -149
  5. data/lib/rack/attack/allow2ban.rb +2 -0
  6. data/lib/rack/attack/blocklist.rb +3 -1
  7. data/lib/rack/attack/cache.rb +9 -4
  8. data/lib/rack/attack/check.rb +5 -2
  9. data/lib/rack/attack/fail2ban.rb +2 -0
  10. data/lib/rack/attack/path_normalizer.rb +22 -18
  11. data/lib/rack/attack/railtie.rb +13 -0
  12. data/lib/rack/attack/request.rb +2 -0
  13. data/lib/rack/attack/safelist.rb +3 -1
  14. data/lib/rack/attack/store_proxy.rb +12 -14
  15. data/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +39 -0
  16. data/lib/rack/attack/store_proxy/dalli_proxy.rb +27 -13
  17. data/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb +3 -1
  18. data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +23 -9
  19. data/lib/rack/attack/store_proxy/redis_proxy.rb +16 -10
  20. data/lib/rack/attack/store_proxy/redis_store_proxy.rb +5 -5
  21. data/lib/rack/attack/throttle.rb +12 -8
  22. data/lib/rack/attack/track.rb +9 -6
  23. data/lib/rack/attack/version.rb +3 -1
  24. data/spec/acceptance/allow2ban_spec.rb +2 -0
  25. data/spec/acceptance/blocking_ip_spec.rb +4 -2
  26. data/spec/acceptance/blocking_spec.rb +45 -3
  27. data/spec/acceptance/blocking_subnet_spec.rb +4 -2
  28. data/spec/acceptance/cache_store_config_for_allow2ban_spec.rb +50 -39
  29. data/spec/acceptance/cache_store_config_for_fail2ban_spec.rb +38 -29
  30. data/spec/acceptance/cache_store_config_for_throttle_spec.rb +2 -0
  31. data/spec/acceptance/cache_store_config_with_rails_spec.rb +2 -0
  32. data/spec/acceptance/customizing_blocked_response_spec.rb +2 -0
  33. data/spec/acceptance/customizing_throttled_response_spec.rb +2 -0
  34. data/spec/acceptance/extending_request_object_spec.rb +2 -0
  35. data/spec/acceptance/fail2ban_spec.rb +2 -0
  36. data/spec/acceptance/rails_middleware_spec.rb +35 -0
  37. data/spec/acceptance/safelisting_ip_spec.rb +4 -2
  38. data/spec/acceptance/safelisting_spec.rb +57 -3
  39. data/spec/acceptance/safelisting_subnet_spec.rb +4 -2
  40. data/spec/acceptance/stores/active_support_dalli_store_spec.rb +2 -0
  41. data/spec/acceptance/stores/active_support_mem_cache_store_pooled_spec.rb +1 -3
  42. data/spec/acceptance/stores/active_support_mem_cache_store_spec.rb +2 -0
  43. data/spec/acceptance/stores/active_support_memory_store_spec.rb +2 -0
  44. data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +9 -1
  45. data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +8 -1
  46. data/spec/acceptance/stores/active_support_redis_store_spec.rb +3 -1
  47. data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +5 -3
  48. data/spec/acceptance/stores/dalli_client_spec.rb +2 -0
  49. data/spec/acceptance/stores/redis_store_spec.rb +2 -0
  50. data/spec/acceptance/throttling_spec.rb +7 -5
  51. data/spec/acceptance/track_spec.rb +5 -3
  52. data/spec/acceptance/track_throttle_spec.rb +5 -3
  53. data/spec/allow2ban_spec.rb +20 -15
  54. data/spec/fail2ban_spec.rb +20 -17
  55. data/spec/integration/offline_spec.rb +3 -1
  56. data/spec/rack_attack_dalli_proxy_spec.rb +2 -0
  57. data/spec/rack_attack_instrumentation_spec.rb +42 -0
  58. data/spec/rack_attack_path_normalizer_spec.rb +4 -2
  59. data/spec/rack_attack_request_spec.rb +2 -0
  60. data/spec/rack_attack_spec.rb +38 -34
  61. data/spec/rack_attack_throttle_spec.rb +50 -19
  62. data/spec/rack_attack_track_spec.rb +12 -7
  63. data/spec/spec_helper.rb +12 -8
  64. data/spec/support/cache_store_helper.rb +2 -0
  65. metadata +44 -28
  66. data/lib/rack/attack/store_proxy/mem_cache_proxy.rb +0 -50
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'spec_helper'
2
4
 
3
5
  describe 'Rack::Attack.track' do
@@ -23,8 +25,9 @@ describe 'Rack::Attack.track' do
23
25
 
24
26
  it "should tag the env" do
25
27
  get '/'
26
- last_request.env['rack.attack.matched'].must_equal 'everything'
27
- last_request.env['rack.attack.match_type'].must_equal :track
28
+
29
+ _(last_request.env['rack.attack.matched']).must_equal 'everything'
30
+ _(last_request.env['rack.attack.match_type']).must_equal :track
28
31
  end
29
32
 
30
33
  describe "with a notification subscriber and two tracks" do
@@ -33,7 +36,7 @@ describe 'Rack::Attack.track' do
33
36
  # A second track
34
37
  Rack::Attack.track("homepage") { |req| req.path == "/" }
35
38
 
36
- ActiveSupport::Notifications.subscribe("rack.attack") do |*_args|
39
+ ActiveSupport::Notifications.subscribe("track.rack_attack") do |*_args|
37
40
  Counter.incr
38
41
  end
39
42
 
@@ -41,21 +44,23 @@ describe 'Rack::Attack.track' do
41
44
  end
42
45
 
43
46
  it "should notify twice" do
44
- Counter.check.must_equal 2
47
+ _(Counter.check).must_equal 2
45
48
  end
46
49
  end
47
50
 
48
51
  describe "without limit and period options" do
49
52
  it "should assign the track filter to a Check instance" do
50
53
  track = Rack::Attack.track("homepage") { |req| req.path == "/" }
51
- track.filter.class.must_equal Rack::Attack::Check
54
+
55
+ _(track.filter.class).must_equal Rack::Attack::Check
52
56
  end
53
57
  end
54
58
 
55
59
  describe "with limit and period options" do
56
60
  it "should assign the track filter to a Throttle instance" do
57
- track = Rack::Attack.track("homepage", :limit => 10, :period => 10) { |req| req.path == "/" }
58
- track.filter.class.must_equal Rack::Attack::Throttle
61
+ track = Rack::Attack.track("homepage", limit: 10, period: 10) { |req| req.path == "/" }
62
+
63
+ _(track.filter.class).must_equal Rack::Attack::Throttle
59
64
  end
60
65
  end
61
66
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/setup"
2
4
 
3
5
  require "minitest/autorun"
4
6
  require "minitest/pride"
5
7
  require "rack/test"
6
- require 'active_support'
7
- require 'action_dispatch'
8
+ require "rails"
8
9
 
9
10
  require "rack/attack"
10
11
 
@@ -13,10 +14,9 @@ if RUBY_ENGINE == "ruby"
13
14
  end
14
15
 
15
16
  def safe_require(name)
16
- begin
17
- require name
18
- rescue LoadError
19
- end
17
+ require name
18
+ rescue LoadError
19
+ nil
20
20
  end
21
21
 
22
22
  safe_require "connection_pool"
@@ -29,6 +29,7 @@ class MiniTest::Spec
29
29
  include Rack::Test::Methods
30
30
 
31
31
  before do
32
+ Rails.cache = nil
32
33
  @_original_throttled_response = Rack::Attack.throttled_response
33
34
  @_original_blocklisted_response = Rack::Attack.blocklisted_response
34
35
  end
@@ -45,6 +46,8 @@ class MiniTest::Spec
45
46
  Rack::Builder.new do
46
47
  # Use Rack::Lint to test that rack-attack is complying with the rack spec
47
48
  use Rack::Lint
49
+ # Intentionally added twice to test idempotence property
50
+ use Rack::Attack
48
51
  use Rack::Attack
49
52
  use Rack::Lint
50
53
 
@@ -55,8 +58,9 @@ class MiniTest::Spec
55
58
  def self.it_allows_ok_requests
56
59
  it "must allow ok requests" do
57
60
  get '/', {}, 'REMOTE_ADDR' => '127.0.0.1'
58
- last_response.status.must_equal 200
59
- last_response.body.must_equal 'Hello World'
61
+
62
+ _(last_response.status).must_equal 200
63
+ _(last_response.body).must_equal 'Hello World'
60
64
  end
61
65
  end
62
66
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Minitest::Spec
2
4
  def self.it_works_for_cache_backed_features(options)
3
5
  fetch_from_store = options.fetch(:fetch_from_store)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-attack
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.1
4
+ version: 6.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Suggs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-29 00:00:00.000000000 Z
11
+ date: 2019-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -48,16 +48,22 @@ dependencies:
48
48
  name: bundler
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "~>"
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '1.17'
54
+ - - "<"
52
55
  - !ruby/object:Gem::Version
53
- version: '1.16'
56
+ version: '3.0'
54
57
  type: :development
55
58
  prerelease: false
56
59
  version_requirements: !ruby/object:Gem::Requirement
57
60
  requirements:
58
- - - "~>"
61
+ - - ">="
59
62
  - !ruby/object:Gem::Version
60
- version: '1.16'
63
+ version: '1.17'
64
+ - - "<"
65
+ - !ruby/object:Gem::Version
66
+ version: '3.0'
61
67
  - !ruby/object:Gem::Dependency
62
68
  name: minitest
63
69
  requirement: !ruby/object:Gem::Requirement
@@ -106,84 +112,90 @@ dependencies:
106
112
  requirements:
107
113
  - - "~>"
108
114
  - !ruby/object:Gem::Version
109
- version: '12.3'
115
+ version: '13.0'
110
116
  type: :development
111
117
  prerelease: false
112
118
  version_requirements: !ruby/object:Gem::Requirement
113
119
  requirements:
114
120
  - - "~>"
115
121
  - !ruby/object:Gem::Version
116
- version: '12.3'
122
+ version: '13.0'
117
123
  - !ruby/object:Gem::Dependency
118
124
  name: rubocop
119
125
  requirement: !ruby/object:Gem::Requirement
120
126
  requirements:
121
127
  - - '='
122
128
  - !ruby/object:Gem::Version
123
- version: 0.58.2
129
+ version: 0.75.0
124
130
  type: :development
125
131
  prerelease: false
126
132
  version_requirements: !ruby/object:Gem::Requirement
127
133
  requirements:
128
134
  - - '='
129
135
  - !ruby/object:Gem::Version
130
- version: 0.58.2
136
+ version: 0.75.0
131
137
  - !ruby/object:Gem::Dependency
132
- name: timecop
138
+ name: rubocop-performance
133
139
  requirement: !ruby/object:Gem::Requirement
134
140
  requirements:
135
141
  - - "~>"
136
142
  - !ruby/object:Gem::Version
137
- version: 0.9.1
143
+ version: 1.5.0
138
144
  type: :development
139
145
  prerelease: false
140
146
  version_requirements: !ruby/object:Gem::Requirement
141
147
  requirements:
142
148
  - - "~>"
143
149
  - !ruby/object:Gem::Version
144
- version: 0.9.1
150
+ version: 1.5.0
145
151
  - !ruby/object:Gem::Dependency
146
- name: byebug
152
+ name: timecop
147
153
  requirement: !ruby/object:Gem::Requirement
148
154
  requirements:
149
155
  - - "~>"
150
156
  - !ruby/object:Gem::Version
151
- version: '10.0'
157
+ version: 0.9.1
152
158
  type: :development
153
159
  prerelease: false
154
160
  version_requirements: !ruby/object:Gem::Requirement
155
161
  requirements:
156
162
  - - "~>"
157
163
  - !ruby/object:Gem::Version
158
- version: '10.0'
164
+ version: 0.9.1
159
165
  - !ruby/object:Gem::Dependency
160
- name: actionpack
166
+ name: byebug
161
167
  requirement: !ruby/object:Gem::Requirement
162
168
  requirements:
163
169
  - - "~>"
164
170
  - !ruby/object:Gem::Version
165
- version: '5.2'
171
+ version: '11.0'
166
172
  type: :development
167
173
  prerelease: false
168
174
  version_requirements: !ruby/object:Gem::Requirement
169
175
  requirements:
170
176
  - - "~>"
171
177
  - !ruby/object:Gem::Version
172
- version: '5.2'
178
+ version: '11.0'
173
179
  - !ruby/object:Gem::Dependency
174
- name: activesupport
180
+ name: railties
175
181
  requirement: !ruby/object:Gem::Requirement
176
182
  requirements:
177
- - - "~>"
183
+ - - ">="
178
184
  - !ruby/object:Gem::Version
179
- version: '5.2'
185
+ version: '4.2'
186
+ - - "<"
187
+ - !ruby/object:Gem::Version
188
+ version: '6.1'
180
189
  type: :development
181
190
  prerelease: false
182
191
  version_requirements: !ruby/object:Gem::Requirement
183
192
  requirements:
184
- - - "~>"
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '4.2'
196
+ - - "<"
185
197
  - !ruby/object:Gem::Version
186
- version: '5.2'
198
+ version: '6.1'
187
199
  description: A rack middleware for throttling and blocking abusive requests
188
200
  email: aaron@ktheory.com
189
201
  executables: []
@@ -200,11 +212,12 @@ files:
200
212
  - lib/rack/attack/check.rb
201
213
  - lib/rack/attack/fail2ban.rb
202
214
  - lib/rack/attack/path_normalizer.rb
215
+ - lib/rack/attack/railtie.rb
203
216
  - lib/rack/attack/request.rb
204
217
  - lib/rack/attack/safelist.rb
205
218
  - lib/rack/attack/store_proxy.rb
219
+ - lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb
206
220
  - lib/rack/attack/store_proxy/dalli_proxy.rb
207
- - lib/rack/attack/store_proxy/mem_cache_proxy.rb
208
221
  - lib/rack/attack/store_proxy/mem_cache_store_proxy.rb
209
222
  - lib/rack/attack/store_proxy/redis_cache_store_proxy.rb
210
223
  - lib/rack/attack/store_proxy/redis_proxy.rb
@@ -224,6 +237,7 @@ files:
224
237
  - spec/acceptance/customizing_throttled_response_spec.rb
225
238
  - spec/acceptance/extending_request_object_spec.rb
226
239
  - spec/acceptance/fail2ban_spec.rb
240
+ - spec/acceptance/rails_middleware_spec.rb
227
241
  - spec/acceptance/safelisting_ip_spec.rb
228
242
  - spec/acceptance/safelisting_spec.rb
229
243
  - spec/acceptance/safelisting_subnet_spec.rb
@@ -245,6 +259,7 @@ files:
245
259
  - spec/fail2ban_spec.rb
246
260
  - spec/integration/offline_spec.rb
247
261
  - spec/rack_attack_dalli_proxy_spec.rb
262
+ - spec/rack_attack_instrumentation_spec.rb
248
263
  - spec/rack_attack_path_normalizer_spec.rb
249
264
  - spec/rack_attack_request_spec.rb
250
265
  - spec/rack_attack_spec.rb
@@ -268,15 +283,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
268
283
  requirements:
269
284
  - - ">="
270
285
  - !ruby/object:Gem::Version
271
- version: '2.2'
286
+ version: '2.3'
272
287
  required_rubygems_version: !ruby/object:Gem::Requirement
273
288
  requirements:
274
289
  - - ">="
275
290
  - !ruby/object:Gem::Version
276
291
  version: '0'
277
292
  requirements: []
278
- rubyforge_project:
279
- rubygems_version: 2.7.7
293
+ rubygems_version: 3.0.6
280
294
  signing_key:
281
295
  specification_version: 4
282
296
  summary: Block & throttle abusive requests
@@ -284,6 +298,7 @@ test_files:
284
298
  - spec/integration/offline_spec.rb
285
299
  - spec/rack_attack_path_normalizer_spec.rb
286
300
  - spec/acceptance/safelisting_subnet_spec.rb
301
+ - spec/acceptance/rails_middleware_spec.rb
287
302
  - spec/acceptance/track_throttle_spec.rb
288
303
  - spec/acceptance/cache_store_config_for_fail2ban_spec.rb
289
304
  - spec/acceptance/cache_store_config_with_rails_spec.rb
@@ -314,6 +329,7 @@ test_files:
314
329
  - spec/acceptance/customizing_blocked_response_spec.rb
315
330
  - spec/spec_helper.rb
316
331
  - spec/allow2ban_spec.rb
332
+ - spec/rack_attack_instrumentation_spec.rb
317
333
  - spec/rack_attack_dalli_proxy_spec.rb
318
334
  - spec/rack_attack_spec.rb
319
335
  - spec/rack_attack_throttle_spec.rb
@@ -1,50 +0,0 @@
1
- module Rack
2
- class Attack
3
- module StoreProxy
4
- class MemCacheProxy < SimpleDelegator
5
- def self.handle?(store)
6
- defined?(::MemCache) && store.is_a?(::MemCache)
7
- end
8
-
9
- def initialize(store)
10
- super(store)
11
- stub_with_if_missing
12
- end
13
-
14
- def read(key)
15
- # Second argument: reading raw value
16
- get(key, true)
17
- rescue MemCache::MemCacheError
18
- end
19
-
20
- def write(key, value, options = {})
21
- # Third argument: writing raw value
22
- set(key, value, options.fetch(:expires_in, 0), true)
23
- rescue MemCache::MemCacheError
24
- end
25
-
26
- def increment(key, amount, _options = {})
27
- incr(key, amount)
28
- rescue MemCache::MemCacheError
29
- end
30
-
31
- def delete(key, _options = {})
32
- with do |client|
33
- client.delete(key)
34
- end
35
- rescue MemCache::MemCacheError
36
- end
37
-
38
- private
39
-
40
- def stub_with_if_missing
41
- unless __getobj__.respond_to?(:with)
42
- class << self
43
- def with; yield __getobj__; end
44
- end
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end