rack-attack 4.4.1 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +28 -28
- data/Rakefile +1 -0
- data/lib/rack/attack.rb +60 -20
- data/lib/rack/attack/{whitelist.rb → blocklist.rb} +2 -2
- data/lib/rack/attack/fail2ban.rb +1 -1
- data/lib/rack/attack/request.rb +1 -1
- data/lib/rack/attack/{blacklist.rb → safelist.rb} +2 -3
- data/lib/rack/attack/version.rb +1 -1
- data/spec/allow2ban_spec.rb +1 -1
- data/spec/fail2ban_spec.rb +1 -1
- data/spec/rack_attack_request_spec.rb +1 -1
- data/spec/rack_attack_spec.rb +49 -13
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f610566e30822bb7e044db96673364461ab144bc
|
4
|
+
data.tar.gz: 0c455cc58bdc60917bcf26f8d9a50323c96f9237
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23256e856a36a8a0b37d2617f33ef2ba21032de6053a062d77f2ac035c5e5bde34c463c44d2d3b1c0546b079d7a01a0e005be0cf142d54870eaef64af4f56c6e
|
7
|
+
data.tar.gz: 9645bcc5b224881e1348e4c97e8ada425ea768c0d7e851c3d022863ba6a01bb31b9e0b942e35c914152ee17775c4d305f893820f3df32392d1d46dd372670371
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
*Rack middleware for blocking & throttling abusive requests*
|
3
3
|
|
4
4
|
Rack::Attack is a rack middleware to protect your web app from bad clients.
|
5
|
-
It allows *
|
5
|
+
It allows *safelisting*, *blocklisting*, *throttling*, and *tracking* based on arbitrary properties of the request.
|
6
6
|
|
7
7
|
Throttle and fail2ban state is stored in a configurable cache (e.g. `Rails.cache`), presumably backed by memcached or redis ([at least gem v3.0.0](https://rubygems.org/gems/redis)).
|
8
8
|
|
@@ -53,14 +53,14 @@ Optionally configure the cache store for throttling or fail2ban filtering:
|
|
53
53
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # defaults to Rails.cache
|
54
54
|
```
|
55
55
|
|
56
|
-
Note that `Rack::Attack.cache` is only used for throttling and fail2ban filtering; not
|
56
|
+
Note that `Rack::Attack.cache` is only used for throttling and fail2ban filtering; not blocklisting & safelisting. Your cache store must implement `increment` and `write` like [ActiveSupport::Cache::Store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html).
|
57
57
|
|
58
58
|
## How it works
|
59
59
|
|
60
|
-
The Rack::Attack middleware compares each request against *
|
60
|
+
The Rack::Attack middleware compares each request against *safelists*, *blocklists*, *throttles*, and *tracks* that you define. There are none by default.
|
61
61
|
|
62
|
-
* If the request matches any **
|
63
|
-
* Otherwise, if the request matches any **
|
62
|
+
* If the request matches any **safelist**, it is allowed.
|
63
|
+
* Otherwise, if the request matches any **blocklist**, it is blocked.
|
64
64
|
* Otherwise, if the request matches any **throttle**, a counter is incremented in the Rack::Attack.cache. If any throttle's limit is exceeded, the request is blocked.
|
65
65
|
* Otherwise, all **tracks** are checked, and the request is allowed.
|
66
66
|
|
@@ -70,10 +70,10 @@ The algorithm is actually more concise in code: See [Rack::Attack.call](https://
|
|
70
70
|
def call(env)
|
71
71
|
req = Rack::Attack::Request.new(env)
|
72
72
|
|
73
|
-
if
|
73
|
+
if safelisted?(req)
|
74
74
|
@app.call(env)
|
75
|
-
elsif
|
76
|
-
self.class.
|
75
|
+
elsif blocklisted?(req)
|
76
|
+
self.class.blocklisted_response.call(env)
|
77
77
|
elsif throttled?(req)
|
78
78
|
self.class.throttled_response.call(env)
|
79
79
|
else
|
@@ -93,61 +93,61 @@ can cleanly monkey patch helper methods onto the
|
|
93
93
|
|
94
94
|
## Usage
|
95
95
|
|
96
|
-
Define
|
96
|
+
Define safelists, blocklists, throttles, and tracks as blocks that return truthy values if matched, falsy otherwise. In a Rails app
|
97
97
|
these go in an initializer in `config/initializers/`.
|
98
98
|
A [Rack::Request](http://www.rubydoc.info/gems/rack/Rack/Request) object is passed to the block (named 'req' in the examples).
|
99
99
|
|
100
|
-
###
|
100
|
+
### Safelists
|
101
101
|
|
102
102
|
```ruby
|
103
103
|
# Always allow requests from localhost
|
104
|
-
# (
|
105
|
-
Rack::Attack.
|
104
|
+
# (blocklist & throttles are skipped)
|
105
|
+
Rack::Attack.safelist('allow from localhost') do |req|
|
106
106
|
# Requests are allowed if the return value is truthy
|
107
107
|
'127.0.0.1' == req.ip || '::1' == req.ip
|
108
108
|
end
|
109
109
|
```
|
110
110
|
|
111
|
-
###
|
111
|
+
### Blocklists
|
112
112
|
|
113
113
|
```ruby
|
114
114
|
# Block requests from 1.2.3.4
|
115
|
-
Rack::Attack.
|
115
|
+
Rack::Attack.blocklist('block 1.2.3.4') do |req|
|
116
116
|
# Requests are blocked if the return value is truthy
|
117
117
|
'1.2.3.4' == req.ip
|
118
118
|
end
|
119
119
|
|
120
120
|
# Block logins from a bad user agent
|
121
|
-
Rack::Attack.
|
121
|
+
Rack::Attack.blocklist('block bad UA logins') do |req|
|
122
122
|
req.path == '/login' && req.post? && req.user_agent == 'BadUA'
|
123
123
|
end
|
124
124
|
```
|
125
125
|
|
126
126
|
#### Fail2Ban
|
127
127
|
|
128
|
-
`Fail2Ban.filter` can be used within a
|
128
|
+
`Fail2Ban.filter` can be used within a blocklist to block all requests from misbehaving clients.
|
129
129
|
This pattern is inspired by [fail2ban](http://www.fail2ban.org/wiki/index.php/Main_Page).
|
130
130
|
See the [fail2ban documentation](http://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Jail_Options) for more details on
|
131
|
-
how the parameters work. For multiple filters, be sure to put each filter in a separate
|
131
|
+
how the parameters work. For multiple filters, be sure to put each filter in a separate blocklist and use a unique discriminator for each fail2ban filter.
|
132
132
|
|
133
133
|
```ruby
|
134
134
|
# Block suspicious requests for '/etc/password' or wordpress specific paths.
|
135
135
|
# After 3 blocked requests in 10 minutes, block all requests from that IP for 5 minutes.
|
136
|
-
Rack::Attack.
|
136
|
+
Rack::Attack.blocklist('fail2ban pentesters') do |req|
|
137
137
|
# `filter` returns truthy value if request fails, or if it's from a previously banned IP
|
138
138
|
# so the request is blocked
|
139
139
|
Rack::Attack::Fail2Ban.filter("pentesters-#{req.ip}", :maxretry => 3, :findtime => 10.minutes, :bantime => 5.minutes) do
|
140
140
|
# The count for the IP is incremented if the return value is truthy
|
141
|
-
CGI.unescape(req.query_string) =~ %r{/etc/passwd} ||
|
141
|
+
CGI.unescape(req.query_string) =~ %r{/etc/passwd} ||
|
142
142
|
req.path.include?('/etc/passwd') ||
|
143
|
-
req.path.include?('wp-admin') ||
|
143
|
+
req.path.include?('wp-admin') ||
|
144
144
|
req.path.include?('wp-login')
|
145
|
-
|
145
|
+
|
146
146
|
end
|
147
147
|
end
|
148
148
|
```
|
149
149
|
|
150
|
-
Note that `Fail2Ban` filters are not automatically scoped to the
|
150
|
+
Note that `Fail2Ban` filters are not automatically scoped to the blocklist, so when using multiple filters in an application the scoping must be added to the discriminator e.g. `"pentest:#{req.ip}"`.
|
151
151
|
|
152
152
|
#### Allow2Ban
|
153
153
|
`Allow2Ban.filter` works the same way as the `Fail2Ban.filter` except that it *allows* requests from misbehaving
|
@@ -155,7 +155,7 @@ clients until such time as they reach maxretry at which they are cut off as per
|
|
155
155
|
```ruby
|
156
156
|
# Lockout IP addresses that are hammering your login page.
|
157
157
|
# After 20 requests in 1 minute, block all requests from that IP for 1 hour.
|
158
|
-
Rack::Attack.
|
158
|
+
Rack::Attack.blocklist('allow2ban login scrapers') do |req|
|
159
159
|
# `filter` returns false value if request is to your login page (but still
|
160
160
|
# increments the count) so request below the limit are not blocked until
|
161
161
|
# they hit the limit. At that point, filter will return true and block.
|
@@ -220,12 +220,12 @@ end
|
|
220
220
|
|
221
221
|
## Responses
|
222
222
|
|
223
|
-
Customize the response of
|
223
|
+
Customize the response of blocklisted and throttled requests using an object that adheres to the [Rack app interface](http://rack.rubyforge.org/doc/SPEC.html).
|
224
224
|
|
225
225
|
```ruby
|
226
|
-
Rack::Attack.
|
226
|
+
Rack::Attack.blocklisted_response = lambda do |env|
|
227
227
|
# Using 503 because it may make attacker think that they have successfully
|
228
|
-
# DOSed the site. Rack::Attack returns 403 for
|
228
|
+
# DOSed the site. Rack::Attack returns 403 for blocklists by default
|
229
229
|
[ 503, {}, ['Blocked']]
|
230
230
|
end
|
231
231
|
|
@@ -274,7 +274,7 @@ but it depends on how many checks you've configured, and how long they take.
|
|
274
274
|
Throttles usually require a network roundtrip to your cache server(s),
|
275
275
|
so try to keep the number of throttle checks per request low.
|
276
276
|
|
277
|
-
If a request is
|
277
|
+
If a request is blocklisted or throttled, the response is a very simple Rack response.
|
278
278
|
A single typical ruby web server thread can block several hundred requests per second.
|
279
279
|
|
280
280
|
Rack::Attack complements tools like `iptables` and nginx's [limit_conn_zone module](http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_conn_zone).
|
@@ -304,6 +304,6 @@ New releases of Rack::Attack are announced on
|
|
304
304
|
|
305
305
|
## License
|
306
306
|
|
307
|
-
Copyright Kickstarter,
|
307
|
+
Copyright Kickstarter, PBC.
|
308
308
|
|
309
309
|
Released under an [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
data/lib/rack/attack.rb
CHANGED
@@ -6,8 +6,8 @@ class Rack::Attack
|
|
6
6
|
autoload :PathNormalizer, 'rack/attack/path_normalizer'
|
7
7
|
autoload :Check, 'rack/attack/check'
|
8
8
|
autoload :Throttle, 'rack/attack/throttle'
|
9
|
-
autoload :
|
10
|
-
autoload :
|
9
|
+
autoload :Safelist, 'rack/attack/safelist'
|
10
|
+
autoload :Blocklist, 'rack/attack/blocklist'
|
11
11
|
autoload :Track, 'rack/attack/track'
|
12
12
|
autoload :StoreProxy, 'rack/attack/store_proxy'
|
13
13
|
autoload :DalliProxy, 'rack/attack/store_proxy/dalli_proxy'
|
@@ -19,14 +19,24 @@ class Rack::Attack
|
|
19
19
|
|
20
20
|
class << self
|
21
21
|
|
22
|
-
attr_accessor :notifier, :
|
22
|
+
attr_accessor :notifier, :blocklisted_response, :throttled_response
|
23
|
+
|
24
|
+
def safelist(name, &block)
|
25
|
+
self.safelists[name] = Safelist.new(name, block)
|
26
|
+
end
|
23
27
|
|
24
28
|
def whitelist(name, &block)
|
25
|
-
|
29
|
+
warn "[DEPRECATION] 'Rack::Attack.whitelist' is deprecated. Please use 'safelist' instead."
|
30
|
+
safelist(name, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def blocklist(name, &block)
|
34
|
+
self.blocklists[name] = Blocklist.new(name, block)
|
26
35
|
end
|
27
36
|
|
28
37
|
def blacklist(name, &block)
|
29
|
-
|
38
|
+
warn "[DEPRECATION] 'Rack::Attack.blacklist' is deprecated. Please use 'blocklist' instead."
|
39
|
+
blocklist(name, &block)
|
30
40
|
end
|
31
41
|
|
32
42
|
def throttle(name, options, &block)
|
@@ -37,23 +47,43 @@ class Rack::Attack
|
|
37
47
|
self.tracks[name] = Track.new(name, options, block)
|
38
48
|
end
|
39
49
|
|
40
|
-
def
|
41
|
-
def
|
50
|
+
def safelists; @safelists ||= {}; end
|
51
|
+
def blocklists; @blocklists ||= {}; end
|
42
52
|
def throttles; @throttles ||= {}; end
|
43
53
|
def tracks; @tracks ||= {}; end
|
44
54
|
|
45
|
-
def
|
46
|
-
whitelists.
|
47
|
-
|
55
|
+
def whitelists
|
56
|
+
warn "[DEPRECATION] 'Rack::Attack.whitelists' is deprecated. Please use 'safelists' instead."
|
57
|
+
safelists
|
58
|
+
end
|
59
|
+
|
60
|
+
def blacklists
|
61
|
+
warn "[DEPRECATION] 'Rack::Attack.blacklists' is deprecated. Please use 'blocklists' instead."
|
62
|
+
blocklists
|
63
|
+
end
|
64
|
+
|
65
|
+
def safelisted?(req)
|
66
|
+
safelists.any? do |name, safelist|
|
67
|
+
safelist[req]
|
48
68
|
end
|
49
69
|
end
|
50
70
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
71
|
+
def whitelisted?
|
72
|
+
warn "[DEPRECATION] 'Rack::Attack.whitelisted?' is deprecated. Please use 'safelisted?' instead."
|
73
|
+
safelisted?
|
74
|
+
end
|
75
|
+
|
76
|
+
def blocklisted?(req)
|
77
|
+
blocklists.any? do |name, blocklist|
|
78
|
+
blocklist[req]
|
54
79
|
end
|
55
80
|
end
|
56
81
|
|
82
|
+
def blacklisted?
|
83
|
+
warn "[DEPRECATION] 'Rack::Attack.blacklisted?' is deprecated. Please use 'blocklisted?' instead."
|
84
|
+
blocklisted?
|
85
|
+
end
|
86
|
+
|
57
87
|
def throttled?(req)
|
58
88
|
throttles.any? do |name, throttle|
|
59
89
|
throttle[req]
|
@@ -75,14 +105,24 @@ class Rack::Attack
|
|
75
105
|
end
|
76
106
|
|
77
107
|
def clear!
|
78
|
-
@
|
108
|
+
@safelists, @blocklists, @throttles, @tracks = {}, {}, {}, {}
|
109
|
+
end
|
110
|
+
|
111
|
+
def blacklisted_response=(res)
|
112
|
+
warn "[DEPRECATION] 'Rack::Attack.blacklisted_response=' is deprecated. Please use 'blocklisted_response=' instead."
|
113
|
+
self.blocklisted_response=(res)
|
114
|
+
end
|
115
|
+
|
116
|
+
def blacklisted_response
|
117
|
+
warn "[DEPRECATION] 'Rack::Attack.blacklisted_response' is deprecated. Please use 'blocklisted_response' instead."
|
118
|
+
self.blocklisted_response
|
79
119
|
end
|
80
120
|
|
81
121
|
end
|
82
122
|
|
83
123
|
# Set defaults
|
84
124
|
@notifier = ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
|
85
|
-
@
|
125
|
+
@blocklisted_response = lambda {|env| [403, {'Content-Type' => 'text/plain'}, ["Forbidden\n"]] }
|
86
126
|
@throttled_response = lambda {|env|
|
87
127
|
retry_after = (env['rack.attack.match_data'] || {})[:period]
|
88
128
|
[429, {'Content-Type' => 'text/plain', 'Retry-After' => retry_after.to_s}, ["Retry later\n"]]
|
@@ -96,10 +136,10 @@ class Rack::Attack
|
|
96
136
|
env['PATH_INFO'] = PathNormalizer.normalize_path(env['PATH_INFO'])
|
97
137
|
req = Rack::Attack::Request.new(env)
|
98
138
|
|
99
|
-
if
|
139
|
+
if safelisted?(req)
|
100
140
|
@app.call(env)
|
101
|
-
elsif
|
102
|
-
self.class.
|
141
|
+
elsif blocklisted?(req)
|
142
|
+
self.class.blocklisted_response.call(env)
|
103
143
|
elsif throttled?(req)
|
104
144
|
self.class.throttled_response.call(env)
|
105
145
|
else
|
@@ -109,8 +149,8 @@ class Rack::Attack
|
|
109
149
|
end
|
110
150
|
|
111
151
|
extend Forwardable
|
112
|
-
def_delegators self, :
|
113
|
-
:
|
152
|
+
def_delegators self, :safelisted?,
|
153
|
+
:blocklisted?,
|
114
154
|
:throttled?,
|
115
155
|
:tracked?
|
116
156
|
end
|
data/lib/rack/attack/fail2ban.rb
CHANGED
@@ -8,7 +8,7 @@ module Rack
|
|
8
8
|
maxretry = options[:maxretry] or raise ArgumentError, "Must pass maxretry option"
|
9
9
|
|
10
10
|
if banned?(discriminator)
|
11
|
-
# Return true for
|
11
|
+
# Return true for blocklist
|
12
12
|
true
|
13
13
|
elsif yield
|
14
14
|
fail!(discriminator, bantime, findtime, maxretry)
|
data/lib/rack/attack/request.rb
CHANGED
data/lib/rack/attack/version.rb
CHANGED
data/spec/allow2ban_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe 'Rack::Attack.Allow2Ban' do
|
|
7
7
|
@bantime = 60
|
8
8
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
9
9
|
@f2b_options = {:bantime => @bantime, :findtime => @findtime, :maxretry => 2}
|
10
|
-
Rack::Attack.
|
10
|
+
Rack::Attack.blocklist('pentest') do |req|
|
11
11
|
Rack::Attack::Allow2Ban.filter(req.ip, @f2b_options){req.query_string =~ /OMGHAX/}
|
12
12
|
end
|
13
13
|
end
|
data/spec/fail2ban_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
7
7
|
@bantime = 60
|
8
8
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
9
9
|
@f2b_options = {:bantime => @bantime, :findtime => @findtime, :maxretry => 2}
|
10
|
-
Rack::Attack.
|
10
|
+
Rack::Attack.blocklist('pentest') do |req|
|
11
11
|
Rack::Attack::Fail2Ban.filter(req.ip, @f2b_options){req.query_string =~ /OMGHAX/}
|
12
12
|
end
|
13
13
|
end
|
data/spec/rack_attack_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe 'Rack::Attack' do
|
|
5
5
|
|
6
6
|
describe 'normalizing paths' do
|
7
7
|
before do
|
8
|
-
Rack::Attack.
|
8
|
+
Rack::Attack.blocklist("banned_path") {|req| req.path == '/foo' }
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'blocks requests with trailing slash' do
|
@@ -14,50 +14,86 @@ describe 'Rack::Attack' do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
describe '
|
17
|
+
describe 'blocklist' do
|
18
18
|
before do
|
19
19
|
@bad_ip = '1.2.3.4'
|
20
|
-
Rack::Attack.
|
20
|
+
Rack::Attack.blocklist("ip #{@bad_ip}") {|req| req.ip == @bad_ip }
|
21
21
|
end
|
22
22
|
|
23
|
-
it('has a
|
24
|
-
Rack::Attack.
|
23
|
+
it('has a blocklist') {
|
24
|
+
Rack::Attack.blocklists.key?("ip #{@bad_ip}").must_equal true
|
25
|
+
}
|
26
|
+
|
27
|
+
it('has a blacklist with a deprication warning') {
|
28
|
+
_, stderror = capture_io do
|
29
|
+
Rack::Attack.blacklists.key?("ip #{@bad_ip}").must_equal true
|
30
|
+
end
|
31
|
+
assert_match "[DEPRECATION] 'Rack::Attack.blacklists' is deprecated. Please use 'blocklists' instead.", stderror
|
25
32
|
}
|
26
33
|
|
27
34
|
describe "a bad request" do
|
28
35
|
before { get '/', {}, 'REMOTE_ADDR' => @bad_ip }
|
29
|
-
it "should return a
|
36
|
+
it "should return a blocklist response" do
|
30
37
|
get '/', {}, 'REMOTE_ADDR' => @bad_ip
|
31
38
|
last_response.status.must_equal 403
|
32
39
|
last_response.body.must_equal "Forbidden\n"
|
33
40
|
end
|
34
41
|
it "should tag the env" do
|
35
42
|
last_request.env['rack.attack.matched'].must_equal "ip #{@bad_ip}"
|
36
|
-
last_request.env['rack.attack.match_type'].must_equal :
|
43
|
+
last_request.env['rack.attack.match_type'].must_equal :blocklist
|
37
44
|
end
|
38
45
|
|
39
46
|
allow_ok_requests
|
40
47
|
end
|
41
48
|
|
42
|
-
describe "and
|
49
|
+
describe "and safelist" do
|
43
50
|
before do
|
44
51
|
@good_ua = 'GoodUA'
|
45
|
-
Rack::Attack.
|
52
|
+
Rack::Attack.safelist("good ua") {|req| req.user_agent == @good_ua }
|
46
53
|
end
|
47
54
|
|
48
|
-
it('has a
|
49
|
-
|
55
|
+
it('has a safelist'){ Rack::Attack.safelists.key?("good ua") }
|
56
|
+
|
57
|
+
it('has a whitelist with a deprication warning') {
|
58
|
+
_, stderror = capture_io do
|
59
|
+
Rack::Attack.whitelists.key?("good ua")
|
60
|
+
end
|
61
|
+
assert_match "[DEPRECATION] 'Rack::Attack.whitelists' is deprecated. Please use 'safelists' instead.", stderror
|
62
|
+
}
|
63
|
+
|
64
|
+
describe "with a request match both safelist & blocklist" do
|
50
65
|
before { get '/', {}, 'REMOTE_ADDR' => @bad_ip, 'HTTP_USER_AGENT' => @good_ua }
|
51
|
-
it "should allow
|
66
|
+
it "should allow safelists before blocklists" do
|
52
67
|
get '/', {}, 'REMOTE_ADDR' => @bad_ip, 'HTTP_USER_AGENT' => @good_ua
|
53
68
|
last_response.status.must_equal 200
|
54
69
|
end
|
55
70
|
it "should tag the env" do
|
56
71
|
last_request.env['rack.attack.matched'].must_equal 'good ua'
|
57
|
-
last_request.env['rack.attack.match_type'].must_equal :
|
72
|
+
last_request.env['rack.attack.match_type'].must_equal :safelist
|
58
73
|
end
|
59
74
|
end
|
60
75
|
end
|
76
|
+
|
77
|
+
describe '#blocklisted_response' do
|
78
|
+
it 'should exist' do
|
79
|
+
Rack::Attack.blocklisted_response.must_respond_to :call
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should give a deprication warning for blacklisted_response' do
|
83
|
+
_, stderror = capture_io do
|
84
|
+
Rack::Attack.blacklisted_response
|
85
|
+
end
|
86
|
+
assert_match "[DEPRECATION] 'Rack::Attack.blacklisted_response' is deprecated. Please use 'blocklisted_response' instead.", stderror
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#throttled_response' do
|
92
|
+
it 'should exist' do
|
93
|
+
Rack::Attack.throttled_response.must_respond_to :call
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
61
97
|
end
|
62
98
|
|
63
99
|
end
|
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: 5.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Suggs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -174,12 +174,13 @@ files:
|
|
174
174
|
- Rakefile
|
175
175
|
- lib/rack/attack.rb
|
176
176
|
- lib/rack/attack/allow2ban.rb
|
177
|
-
- lib/rack/attack/
|
177
|
+
- lib/rack/attack/blocklist.rb
|
178
178
|
- lib/rack/attack/cache.rb
|
179
179
|
- lib/rack/attack/check.rb
|
180
180
|
- lib/rack/attack/fail2ban.rb
|
181
181
|
- lib/rack/attack/path_normalizer.rb
|
182
182
|
- lib/rack/attack/request.rb
|
183
|
+
- lib/rack/attack/safelist.rb
|
183
184
|
- lib/rack/attack/store_proxy.rb
|
184
185
|
- lib/rack/attack/store_proxy/dalli_proxy.rb
|
185
186
|
- lib/rack/attack/store_proxy/mem_cache_proxy.rb
|
@@ -187,7 +188,6 @@ files:
|
|
187
188
|
- lib/rack/attack/throttle.rb
|
188
189
|
- lib/rack/attack/track.rb
|
189
190
|
- lib/rack/attack/version.rb
|
190
|
-
- lib/rack/attack/whitelist.rb
|
191
191
|
- spec/allow2ban_spec.rb
|
192
192
|
- spec/fail2ban_spec.rb
|
193
193
|
- spec/integration/offline_spec.rb
|
@@ -215,9 +215,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
215
215
|
version: 2.0.0
|
216
216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
217
217
|
requirements:
|
218
|
-
- - "
|
218
|
+
- - ">"
|
219
219
|
- !ruby/object:Gem::Version
|
220
|
-
version:
|
220
|
+
version: 1.3.1
|
221
221
|
requirements: []
|
222
222
|
rubyforge_project:
|
223
223
|
rubygems_version: 2.5.1
|