rack-attack/spec/fail2ban_spec.rb
2019-10-01 17:19:44 -03:00

146 lines
4.1 KiB
Ruby

# frozen_string_literal: true
require_relative 'spec_helper'
describe 'Rack::Attack.Fail2Ban' do
before do
# Use a long findtime; failures due to cache key rotation less likely
@cache = Rack::Attack.cache
@findtime = 60
@bantime = 60
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
@f2b_options = { bantime: @bantime, findtime: @findtime, maxretry: 2 }
Rack::Attack.blocklist('pentest') do |req|
Rack::Attack::Fail2Ban.filter(req.ip, @f2b_options) { req.query_string =~ /OMGHAX/ }
end
end
describe 'discriminator has not been banned' do
describe 'making ok request' do
it 'succeeds' do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
_(last_response.status).must_equal 200
end
end
describe 'making failing request' do
describe 'when not at maxretry' do
before { get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4' }
it 'fails' do
_(last_response.status).must_equal 403
end
it 'increases fail count' do
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
_(@cache.store.read(key)).must_equal 1
end
it 'is not banned' do
key = "rack::attack:fail2ban:1.2.3.4"
_(@cache.store.read(key)).must_be_nil
end
end
describe 'when at maxretry' do
before do
# maxretry is 2 - so hit with an extra failed request first
get '/?test=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
end
it 'fails' do
_(last_response.status).must_equal 403
end
it 'increases fail count' do
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
_(@cache.store.read(key)).must_equal 2
end
it 'is banned' do
key = "rack::attack:fail2ban:ban:1.2.3.4"
_(@cache.store.read(key)).must_equal 1
end
end
describe 'reset after success' do
before do
get '/?test=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
Rack::Attack::Fail2Ban.reset('1.2.3.4', @f2b_options)
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
end
it 'succeeds' do
_(last_response.status).must_equal 200
end
it 'resets fail count' do
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
assert_nil @cache.store.read(key)
end
it 'IP is not banned' do
_(Rack::Attack::Fail2Ban.banned?('1.2.3.4')).must_equal false
end
end
end
end
describe 'discriminator has been banned' do
before do
# maxretry is 2 - so hit enough times to get banned
get '/?test=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
end
describe 'making request for other discriminator' do
it 'succeeds' do
get '/', {}, 'REMOTE_ADDR' => '2.2.3.4'
_(last_response.status).must_equal 200
end
end
describe 'making ok request' do
before do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
end
it 'fails' do
_(last_response.status).must_equal 403
end
it 'does not increase fail count' do
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
_(@cache.store.read(key)).must_equal 2
end
it 'is still banned' do
key = "rack::attack:fail2ban:ban:1.2.3.4"
_(@cache.store.read(key)).must_equal 1
end
end
describe 'making failing request' do
before do
get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
end
it 'fails' do
_(last_response.status).must_equal 403
end
it 'does not increase fail count' do
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
_(@cache.store.read(key)).must_equal 2
end
it 'is still banned' do
key = "rack::attack:fail2ban:ban:1.2.3.4"
_(@cache.store.read(key)).must_equal 1
end
end
end
end