diff --git a/spec/allow2ban_spec.rb b/spec/allow2ban_spec.rb index 3e3cf47..9eeae9c 100644 --- a/spec/allow2ban_spec.rb +++ b/spec/allow2ban_spec.rb @@ -1,4 +1,5 @@ require_relative 'spec_helper' + describe 'Rack::Attack.Allow2Ban' do before do # Use a long findtime; failures due to cache key rotation less likely @@ -7,6 +8,7 @@ describe 'Rack::Attack.Allow2Ban' do @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::Allow2Ban.filter(req.ip, @f2b_options){req.query_string =~ /OMGHAX/} end @@ -23,6 +25,7 @@ describe 'Rack::Attack.Allow2Ban' do describe 'making qualifying request' do describe 'when not at maxretry' do before { get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4' } + it 'succeeds' do last_response.status.must_equal 200 end @@ -58,7 +61,6 @@ describe 'Rack::Attack.Allow2Ban' do key = "rack::attack:allow2ban:ban:1.2.3.4" @cache.store.read(key).must_equal 1 end - end end end @@ -116,6 +118,5 @@ describe 'Rack::Attack.Allow2Ban' do @cache.store.read(key).must_equal 1 end end - end end diff --git a/spec/fail2ban_spec.rb b/spec/fail2ban_spec.rb index 0f24524..f9235d3 100644 --- a/spec/fail2ban_spec.rb +++ b/spec/fail2ban_spec.rb @@ -1,4 +1,5 @@ require_relative 'spec_helper' + describe 'Rack::Attack.Fail2Ban' do before do # Use a long findtime; failures due to cache key rotation less likely @@ -7,6 +8,7 @@ describe 'Rack::Attack.Fail2Ban' do @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 @@ -23,6 +25,7 @@ describe 'Rack::Attack.Fail2Ban' do 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 @@ -136,6 +139,5 @@ describe 'Rack::Attack.Fail2Ban' do @cache.store.read(key).must_equal 1 end end - end end diff --git a/spec/integration/offline_spec.rb b/spec/integration/offline_spec.rb index 95598d4..f47fb31 100644 --- a/spec/integration/offline_spec.rb +++ b/spec/integration/offline_spec.rb @@ -4,7 +4,6 @@ require 'dalli' require_relative '../spec_helper' OfflineExamples = Minitest::SharedExamples.new do - it 'should write' do @cache.write('cache-test-key', 'foobar', 1) end @@ -16,7 +15,6 @@ OfflineExamples = Minitest::SharedExamples.new do it 'should count' do @cache.send(:do_count, 'rack::attack::cache-test-key', 1) end - end describe 'when Redis is offline' do @@ -27,7 +25,6 @@ describe 'when Redis is offline' do # Use presumably unused port for Redis client @cache.store = ActiveSupport::Cache::RedisStore.new(:host => '127.0.0.1', :port => 3333) } - end describe 'when Memcached is offline' do @@ -43,5 +40,4 @@ describe 'when Memcached is offline' do after { Dalli.logger.level = Logger::INFO } - end diff --git a/spec/integration/rack_attack_cache_spec.rb b/spec/integration/rack_attack_cache_spec.rb index 6eb27ef..b819907 100644 --- a/spec/integration/rack_attack_cache_spec.rb +++ b/spec/integration/rack_attack_cache_spec.rb @@ -1,7 +1,6 @@ require_relative '../spec_helper' describe Rack::Attack::Cache do - # A convenience method for deleting a key from cache. # Slightly differnet than @cache.delete, which adds a prefix. def delete(key) @@ -20,6 +19,7 @@ describe Rack::Attack::Cache do require 'active_support/cache/mem_cache_store' require 'active_support/cache/redis_store' require 'connection_pool' + cache_stores = [ ActiveSupport::Cache::MemoryStore.new, ActiveSupport::Cache::DalliStore.new("127.0.0.1"), @@ -32,8 +32,8 @@ describe Rack::Attack::Cache do cache_stores.each do |store| store = Rack::Attack::StoreProxy.build(store) - describe "with #{store.class}" do + describe "with #{store.class}" do before { @cache = Rack::Attack::Cache.new @key = "rack::attack:cache-test-key" @@ -117,6 +117,5 @@ describe Rack::Attack::Cache do end end end - end end diff --git a/spec/rack_attack_spec.rb b/spec/rack_attack_spec.rb index 8b2f942..e2232b3 100644 --- a/spec/rack_attack_spec.rb +++ b/spec/rack_attack_spec.rb @@ -33,11 +33,13 @@ describe 'Rack::Attack' do describe "a bad request" do before { get '/', {}, 'REMOTE_ADDR' => @bad_ip } + it "should return a blocklist response" do get '/', {}, 'REMOTE_ADDR' => @bad_ip last_response.status.must_equal 403 last_response.body.must_equal "Forbidden\n" end + it "should tag the env" do last_request.env['rack.attack.matched'].must_equal "ip #{@bad_ip}" last_request.env['rack.attack.match_type'].must_equal :blocklist @@ -52,7 +54,7 @@ describe 'Rack::Attack' do Rack::Attack.safelist("good ua") {|req| req.user_agent == @good_ua } end - it('has a safelist'){ Rack::Attack.safelists.key?("good ua") } + it('has a safelist') { Rack::Attack.safelists.key?("good ua") } it('has a whitelist with a deprication warning') { _, stderror = capture_io do @@ -63,10 +65,12 @@ describe 'Rack::Attack' do describe "with a request match both safelist & blocklist" do before { get '/', {}, 'REMOTE_ADDR' => @bad_ip, 'HTTP_USER_AGENT' => @good_ua } + it "should allow safelists before blocklists" do get '/', {}, 'REMOTE_ADDR' => @bad_ip, 'HTTP_USER_AGENT' => @good_ua last_response.status.must_equal 200 end + it "should tag the env" do last_request.env['rack.attack.matched'].must_equal 'good ua' last_request.env['rack.attack.match_type'].must_equal :safelist @@ -84,7 +88,6 @@ describe 'Rack::Attack' do Rack::Attack.blacklisted_response end assert_match "[DEPRECATION] 'Rack::Attack.blacklisted_response' is deprecated. Please use 'blocklisted_response' instead.", stderror - end end @@ -93,7 +96,5 @@ describe 'Rack::Attack' do Rack::Attack.throttled_response.must_respond_to :call end end - end - end diff --git a/spec/rack_attack_throttle_spec.rb b/spec/rack_attack_throttle_spec.rb index d64a27d..cd2c2bd 100644 --- a/spec/rack_attack_throttle_spec.rb +++ b/spec/rack_attack_throttle_spec.rb @@ -1,4 +1,5 @@ require_relative 'spec_helper' + describe 'Rack::Attack.throttle' do before do @period = 60 # Use a long period; failures due to cache key rotation less likely @@ -6,11 +7,13 @@ describe 'Rack::Attack.throttle' do Rack::Attack.throttle('ip/sec', :limit => 1, :period => @period) { |req| req.ip } end - it('should have a throttle'){ Rack::Attack.throttles.key?('ip/sec') } + it('should have a throttle') { Rack::Attack.throttles.key?('ip/sec') } + allow_ok_requests describe 'a single request' do before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' } + it 'should set the counter for one request' do key = "rack::attack:#{Time.now.to_i/@period}:ip/sec:1.2.3.4" Rack::Attack.cache.store.read(key).must_equal 1 @@ -21,19 +24,23 @@ describe 'Rack::Attack.throttle' do last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data end end + describe "with 2 requests" do before do 2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' } end + it 'should block the last request' do last_response.status.must_equal 429 end + it 'should tag the env' do last_request.env['rack.attack.matched'].must_equal 'ip/sec' last_request.env['rack.attack.match_type'].must_equal :throttle last_request.env['rack.attack.match_data'].must_equal({:count => 2, :limit => 1, :period => @period}) last_request.env['rack.attack.match_discriminator'].must_equal('1.2.3.4') end + it 'should set a Retry-After header' do last_response.headers['Retry-After'].must_equal @period.to_s end @@ -51,6 +58,7 @@ describe 'Rack::Attack.throttle with limit as proc' do describe 'a single request' do before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' } + it 'should set the counter for one request' do key = "rack::attack:#{Time.now.to_i/@period}:ip/sec:1.2.3.4" Rack::Attack.cache.store.read(key).must_equal 1 @@ -74,6 +82,7 @@ describe 'Rack::Attack.throttle with period as proc' do describe 'a single request' do before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' } + it 'should set the counter for one request' do key = "rack::attack:#{Time.now.to_i/@period}:ip/sec:1.2.3.4" Rack::Attack.cache.store.read(key).must_equal 1 @@ -97,6 +106,7 @@ describe 'Rack::Attack.throttle with block retuning nil' do describe 'a single request' do before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' } + it 'should not set the counter' do key = "rack::attack:#{Time.now.to_i/@period}:ip/sec:1.2.3.4" Rack::Attack.cache.store.read(key).must_equal nil @@ -106,4 +116,4 @@ describe 'Rack::Attack.throttle with block retuning nil' do last_request.env['rack.attack.throttle_data'].must_equal nil end end -end \ No newline at end of file +end diff --git a/spec/rack_attack_track_spec.rb b/spec/rack_attack_track_spec.rb index 9f9ca9c..6bd38f3 100644 --- a/spec/rack_attack_track_spec.rb +++ b/spec/rack_attack_track_spec.rb @@ -18,7 +18,9 @@ describe 'Rack::Attack.track' do before do Rack::Attack.track("everything"){ |req| true } end + allow_ok_requests + it "should tag the env" do get '/' last_request.env['rack.attack.matched'].must_equal 'everything' @@ -34,6 +36,7 @@ describe 'Rack::Attack.track' do ActiveSupport::Notifications.subscribe("rack.attack") do |*args| Counter.incr end + get "/" end