rack-attack 5.4.2 → 6.0.0
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.
- checksums.yaml +4 -4
- data/README.md +65 -23
- data/Rakefile +3 -1
- data/lib/rack/attack.rb +46 -70
- data/lib/rack/attack/allow2ban.rb +2 -0
- data/lib/rack/attack/blocklist.rb +3 -1
- data/lib/rack/attack/cache.rb +5 -3
- data/lib/rack/attack/check.rb +3 -1
- data/lib/rack/attack/fail2ban.rb +2 -0
- data/lib/rack/attack/path_normalizer.rb +2 -0
- data/lib/rack/attack/request.rb +2 -0
- data/lib/rack/attack/safelist.rb +3 -1
- data/lib/rack/attack/store_proxy.rb +12 -14
- data/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +37 -0
- data/lib/rack/attack/store_proxy/dalli_proxy.rb +27 -13
- data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +2 -4
- data/lib/rack/attack/store_proxy/redis_proxy.rb +16 -10
- data/lib/rack/attack/store_proxy/redis_store_proxy.rb +5 -5
- data/lib/rack/attack/throttle.rb +8 -6
- data/lib/rack/attack/track.rb +5 -3
- data/lib/rack/attack/version.rb +3 -1
- data/spec/acceptance/allow2ban_spec.rb +2 -0
- data/spec/acceptance/blocking_ip_spec.rb +4 -2
- data/spec/acceptance/blocking_spec.rb +45 -3
- data/spec/acceptance/blocking_subnet_spec.rb +4 -2
- data/spec/acceptance/cache_store_config_for_allow2ban_spec.rb +8 -12
- data/spec/acceptance/cache_store_config_for_fail2ban_spec.rb +8 -12
- data/spec/acceptance/cache_store_config_for_throttle_spec.rb +2 -0
- data/spec/acceptance/cache_store_config_with_rails_spec.rb +2 -0
- data/spec/acceptance/customizing_blocked_response_spec.rb +2 -0
- data/spec/acceptance/customizing_throttled_response_spec.rb +2 -0
- data/spec/acceptance/extending_request_object_spec.rb +2 -0
- data/spec/acceptance/fail2ban_spec.rb +2 -0
- data/spec/acceptance/safelisting_ip_spec.rb +4 -2
- data/spec/acceptance/safelisting_spec.rb +57 -3
- data/spec/acceptance/safelisting_subnet_spec.rb +4 -2
- data/spec/acceptance/stores/active_support_dalli_store_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_mem_cache_store_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_memory_store_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_redis_store_spec.rb +3 -1
- data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +2 -0
- data/spec/acceptance/stores/dalli_client_spec.rb +2 -0
- data/spec/acceptance/stores/redis_store_spec.rb +2 -0
- data/spec/acceptance/throttling_spec.rb +7 -5
- data/spec/acceptance/track_spec.rb +5 -3
- data/spec/acceptance/track_throttle_spec.rb +5 -3
- data/spec/allow2ban_spec.rb +3 -1
- data/spec/fail2ban_spec.rb +3 -1
- data/spec/integration/offline_spec.rb +3 -1
- data/spec/rack_attack_dalli_proxy_spec.rb +2 -0
- data/spec/rack_attack_instrumentation_spec.rb +42 -0
- data/spec/rack_attack_path_normalizer_spec.rb +2 -0
- data/spec/rack_attack_request_spec.rb +2 -0
- data/spec/rack_attack_spec.rb +2 -21
- data/spec/rack_attack_throttle_spec.rb +10 -8
- data/spec/rack_attack_track_spec.rb +4 -2
- data/spec/spec_helper.rb +5 -4
- data/spec/support/cache_store_helper.rb +2 -0
- metadata +21 -14
- data/lib/rack/attack/store_proxy/mem_cache_proxy.rb +0 -50
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'spec_helper'
|
2
4
|
|
3
5
|
describe 'Rack::Attack.throttle' do
|
4
6
|
before do
|
5
7
|
@period = 60 # Use a long period; failures due to cache key rotation less likely
|
6
8
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
7
|
-
Rack::Attack.throttle('ip/sec', :
|
9
|
+
Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |req| req.ip }
|
8
10
|
end
|
9
11
|
|
10
12
|
it('should have a throttle') { Rack::Attack.throttles.key?('ip/sec') }
|
@@ -20,7 +22,7 @@ describe 'Rack::Attack.throttle' do
|
|
20
22
|
end
|
21
23
|
|
22
24
|
it 'should populate throttle data' do
|
23
|
-
data = { :
|
25
|
+
data = { count: 1, limit: 1, period: @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
|
24
26
|
last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
|
25
27
|
end
|
26
28
|
end
|
@@ -37,7 +39,7 @@ describe 'Rack::Attack.throttle' do
|
|
37
39
|
it 'should tag the env' do
|
38
40
|
last_request.env['rack.attack.matched'].must_equal 'ip/sec'
|
39
41
|
last_request.env['rack.attack.match_type'].must_equal :throttle
|
40
|
-
last_request.env['rack.attack.match_data'].must_equal(:
|
42
|
+
last_request.env['rack.attack.match_data'].must_equal(count: 2, limit: 1, period: @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i)
|
41
43
|
last_request.env['rack.attack.match_discriminator'].must_equal('1.2.3.4')
|
42
44
|
end
|
43
45
|
|
@@ -51,7 +53,7 @@ describe 'Rack::Attack.throttle with limit as proc' do
|
|
51
53
|
before do
|
52
54
|
@period = 60 # Use a long period; failures due to cache key rotation less likely
|
53
55
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
54
|
-
Rack::Attack.throttle('ip/sec', :
|
56
|
+
Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: @period) { |req| req.ip }
|
55
57
|
end
|
56
58
|
|
57
59
|
it_allows_ok_requests
|
@@ -65,7 +67,7 @@ describe 'Rack::Attack.throttle with limit as proc' do
|
|
65
67
|
end
|
66
68
|
|
67
69
|
it 'should populate throttle data' do
|
68
|
-
data = { :
|
70
|
+
data = { count: 1, limit: 1, period: @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
|
69
71
|
last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
|
70
72
|
end
|
71
73
|
end
|
@@ -75,7 +77,7 @@ describe 'Rack::Attack.throttle with period as proc' do
|
|
75
77
|
before do
|
76
78
|
@period = 60 # Use a long period; failures due to cache key rotation less likely
|
77
79
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
78
|
-
Rack::Attack.throttle('ip/sec', :
|
80
|
+
Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: lambda { |_req| @period }) { |req| req.ip }
|
79
81
|
end
|
80
82
|
|
81
83
|
it_allows_ok_requests
|
@@ -89,7 +91,7 @@ describe 'Rack::Attack.throttle with period as proc' do
|
|
89
91
|
end
|
90
92
|
|
91
93
|
it 'should populate throttle data' do
|
92
|
-
data = { :
|
94
|
+
data = { count: 1, limit: 1, period: @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
|
93
95
|
last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
|
94
96
|
end
|
95
97
|
end
|
@@ -99,7 +101,7 @@ describe 'Rack::Attack.throttle with block retuning nil' do
|
|
99
101
|
before do
|
100
102
|
@period = 60
|
101
103
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
102
|
-
Rack::Attack.throttle('ip/sec', :
|
104
|
+
Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |_| nil }
|
103
105
|
end
|
104
106
|
|
105
107
|
it_allows_ok_requests
|
@@ -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
|
@@ -33,7 +35,7 @@ describe 'Rack::Attack.track' do
|
|
33
35
|
# A second track
|
34
36
|
Rack::Attack.track("homepage") { |req| req.path == "/" }
|
35
37
|
|
36
|
-
ActiveSupport::Notifications.subscribe("
|
38
|
+
ActiveSupport::Notifications.subscribe("track.rack_attack") do |*_args|
|
37
39
|
Counter.incr
|
38
40
|
end
|
39
41
|
|
@@ -54,7 +56,7 @@ describe 'Rack::Attack.track' do
|
|
54
56
|
|
55
57
|
describe "with limit and period options" do
|
56
58
|
it "should assign the track filter to a Throttle instance" do
|
57
|
-
track = Rack::Attack.track("homepage", :
|
59
|
+
track = Rack::Attack.track("homepage", limit: 10, period: 10) { |req| req.path == "/" }
|
58
60
|
track.filter.class.must_equal Rack::Attack::Throttle
|
59
61
|
end
|
60
62
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler/setup"
|
2
4
|
|
3
5
|
require "minitest/autorun"
|
@@ -13,10 +15,9 @@ if RUBY_ENGINE == "ruby"
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def safe_require(name)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
18
|
+
require name
|
19
|
+
rescue LoadError
|
20
|
+
nil
|
20
21
|
end
|
21
22
|
|
22
23
|
safe_require "connection_pool"
|
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:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Suggs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-04-17 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: '
|
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
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '1.17'
|
64
|
+
- - "<"
|
59
65
|
- !ruby/object:Gem::Version
|
60
|
-
version: '
|
66
|
+
version: '3.0'
|
61
67
|
- !ruby/object:Gem::Dependency
|
62
68
|
name: minitest
|
63
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,14 +126,14 @@ dependencies:
|
|
120
126
|
requirements:
|
121
127
|
- - '='
|
122
128
|
- !ruby/object:Gem::Version
|
123
|
-
version: 0.
|
129
|
+
version: 0.67.2
|
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.
|
136
|
+
version: 0.67.2
|
131
137
|
- !ruby/object:Gem::Dependency
|
132
138
|
name: timecop
|
133
139
|
requirement: !ruby/object:Gem::Requirement
|
@@ -148,14 +154,14 @@ dependencies:
|
|
148
154
|
requirements:
|
149
155
|
- - "~>"
|
150
156
|
- !ruby/object:Gem::Version
|
151
|
-
version: '
|
157
|
+
version: '11.0'
|
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: '
|
164
|
+
version: '11.0'
|
159
165
|
- !ruby/object:Gem::Dependency
|
160
166
|
name: actionpack
|
161
167
|
requirement: !ruby/object:Gem::Requirement
|
@@ -203,8 +209,8 @@ files:
|
|
203
209
|
- lib/rack/attack/request.rb
|
204
210
|
- lib/rack/attack/safelist.rb
|
205
211
|
- lib/rack/attack/store_proxy.rb
|
212
|
+
- lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb
|
206
213
|
- lib/rack/attack/store_proxy/dalli_proxy.rb
|
207
|
-
- lib/rack/attack/store_proxy/mem_cache_proxy.rb
|
208
214
|
- lib/rack/attack/store_proxy/mem_cache_store_proxy.rb
|
209
215
|
- lib/rack/attack/store_proxy/redis_cache_store_proxy.rb
|
210
216
|
- lib/rack/attack/store_proxy/redis_proxy.rb
|
@@ -245,6 +251,7 @@ files:
|
|
245
251
|
- spec/fail2ban_spec.rb
|
246
252
|
- spec/integration/offline_spec.rb
|
247
253
|
- spec/rack_attack_dalli_proxy_spec.rb
|
254
|
+
- spec/rack_attack_instrumentation_spec.rb
|
248
255
|
- spec/rack_attack_path_normalizer_spec.rb
|
249
256
|
- spec/rack_attack_request_spec.rb
|
250
257
|
- spec/rack_attack_spec.rb
|
@@ -268,15 +275,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
268
275
|
requirements:
|
269
276
|
- - ">="
|
270
277
|
- !ruby/object:Gem::Version
|
271
|
-
version: '2.
|
278
|
+
version: '2.3'
|
272
279
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
273
280
|
requirements:
|
274
281
|
- - ">="
|
275
282
|
- !ruby/object:Gem::Version
|
276
283
|
version: '0'
|
277
284
|
requirements: []
|
278
|
-
|
279
|
-
rubygems_version: 2.7.6
|
285
|
+
rubygems_version: 3.0.3
|
280
286
|
signing_key:
|
281
287
|
specification_version: 4
|
282
288
|
summary: Block & throttle abusive requests
|
@@ -314,6 +320,7 @@ test_files:
|
|
314
320
|
- spec/acceptance/customizing_blocked_response_spec.rb
|
315
321
|
- spec/spec_helper.rb
|
316
322
|
- spec/allow2ban_spec.rb
|
323
|
+
- spec/rack_attack_instrumentation_spec.rb
|
317
324
|
- spec/rack_attack_dalli_proxy_spec.rb
|
318
325
|
- spec/rack_attack_spec.rb
|
319
326
|
- 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
|