rack-attack 4.4.1 → 5.0.0.beta1
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 +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
|