spanx 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ script: "bundle exec rspec"
5
+ notifications:
6
+ email: false
data/README.md CHANGED
@@ -1,9 +1,13 @@
1
- # Spanx
1
+ Spanx
2
+ =====
3
+
4
+ [![Build status](https://secure.travis-ci.org/wanelo/spanx.png)](http://travis-ci.org/wanelo/spanx)
2
5
 
3
6
  Spank down IP spam: IP-based rate limiting for web applications behind HTTP server such as nginx or Apache.
4
7
 
5
- Spanx is a simple Redis-based web request rate limiter, which integrates into any web application simply by monitoring
6
- one or more HTTP server access log file(s) in real time (think Apache/nginx access.log).
8
+ Spanx integrates into any web application simply by monitoring one or more HTTP server access log file(s)
9
+ in real time (think Apache/nginx access.log). Spanx is built on top of the gem Pause, which is a simple Redis-based rate
10
+ limiter.
7
11
 
8
12
  Basic flow is as follows:
9
13
 
@@ -38,13 +38,12 @@ module Spanx
38
38
  def analyze_all_ips
39
39
  return unless Spanx::IPChecker.enabled?
40
40
 
41
- @previously_blocked_ips = Spanx::IPChecker.blocked_identifiers
42
-
41
+ @previously_blocked_ips = Spanx::IPChecker.rate_limited_identifiers
43
42
  ips = Spanx::IPChecker.tracked_identifiers
44
43
 
45
44
  Logger.logging "analyzed #{ips.size} IPs" do
46
45
  ips.each do |ip|
47
- blocked_ip = analyze_ip(ip)
46
+ blocked_ip = Spanx::IPChecker.new(ip).analyze
48
47
  blocked_ips << blocked_ip if blocked_ip
49
48
  end
50
49
  end
@@ -54,12 +53,6 @@ module Spanx
54
53
  blocked_ips.clear
55
54
  end
56
55
 
57
- # Analyze individual IP for all defined periods. As soon as one
58
- # rule is triggered, exit the method
59
- def analyze_ip(ip)
60
- Spanx::IPChecker.new(ip).analyze
61
- end
62
-
63
56
  private
64
57
 
65
58
  def initialize_notifiers(config)
@@ -39,7 +39,7 @@ module Spanx
39
39
  semaphore.synchronize {
40
40
  Logger.logging "flushing cache with [#{cache.keys.size}] keys" do
41
41
  cache.each_pair do |key, count|
42
- Spanx::IPChecker.new(key[0]).increment!(key[1], count)
42
+ Spanx::IPChecker.new(key[0]).increment!(count, key[1])
43
43
  end
44
44
  reset_cache
45
45
  end
@@ -26,7 +26,7 @@ module Spanx
26
26
 
27
27
  def write
28
28
  if Spanx::IPChecker.enabled?
29
- ips = Spanx::IPChecker.blocked_identifiers
29
+ ips = Spanx::IPChecker.rate_limited_identifiers
30
30
  else
31
31
  Logger.log "writing empty block file due to disabled state"
32
32
  ips = []
data/lib/spanx/config.rb CHANGED
@@ -25,7 +25,7 @@ module Spanx
25
25
 
26
26
  if self.has_key?(:analyzer) && self[:analyzer].has_key?(:period_checks)
27
27
  self[:analyzer][:period_checks].each do |check|
28
- Spanx::IPChecker.check check[:period_seconds].to_i, check[:max_allowed].to_i, check[:block_ttl].to_i
28
+ Spanx::IPChecker.check(check)
29
29
  end
30
30
  end
31
31
 
@@ -1,5 +1,5 @@
1
1
  require 'pause'
2
2
 
3
3
  class Spanx::IPChecker < Pause::Action
4
- scope "spanx:ip"
4
+ scope "ip"
5
5
  end
data/lib/spanx/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Spanx
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/spanx.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = %w(lib)
16
16
  gem.version = Spanx::VERSION
17
17
 
18
- gem.add_dependency 'pause', '~> 0.0.3'
18
+ gem.add_dependency 'pause', '~> 0.0.4'
19
19
  gem.add_dependency 'file-tail'
20
20
  gem.add_dependency 'mixlib-cli'
21
21
  gem.add_dependency 'daemons'
@@ -36,24 +36,24 @@ describe Spanx::Actor::Analyzer do
36
36
  let(:ip1) { "127.0.0.1" }
37
37
  let(:ip2) { "192.168.0.1" }
38
38
 
39
- describe "#analyze_ip" do
39
+ describe "#RateLimitedEvent" do
40
40
 
41
41
  let(:now) { period_marker(10, Time.now.to_i) + 1 }
42
42
 
43
43
  context "IP blocking rules are not matched" do
44
44
  it "returns nil" do
45
- analyzer.analyze_ip(ip1).should be_nil
45
+ Spanx::IPChecker.new(ip1).analyze.should be_nil
46
46
  end
47
47
  end
48
48
 
49
49
  context "IP blocking rules are matched" do
50
50
  before do
51
- Spanx::IPChecker.new(ip1).increment!(now - 5, 2)
52
- Spanx::IPChecker.new(ip1).increment!(now - 15, 1)
51
+ Spanx::IPChecker.new(ip1).increment!(2, now - 5)
52
+ Spanx::IPChecker.new(ip1).increment!(1, now - 15)
53
53
  end
54
54
 
55
- it "returns a Pause::BlockedAction" do
56
- analyzer.analyze_ip(ip1).should be_a(Pause::BlockedAction)
55
+ it "returns a Pause::RateLimitedEvent" do
56
+ Spanx::IPChecker.new(ip1).analyze.should be_a(Pause::RateLimitedEvent)
57
57
  end
58
58
  end
59
59
  end
@@ -61,7 +61,7 @@ describe Spanx::Actor::Analyzer do
61
61
  describe "#analyze_all_ips" do
62
62
  context "checker is disabled" do
63
63
  before do
64
- Spanx::IPChecker.stub(:blocked_identifiers).and_return([ip1, ip2])
64
+ Spanx::IPChecker.stub(:rate_limited_identifiers).and_return([ip1, ip2])
65
65
  Spanx::IPChecker.stub(:enabled?).and_return(false)
66
66
  analyzer.should_not_receive(:analyze_ip)
67
67
  end
@@ -73,12 +73,11 @@ describe Spanx::Actor::Analyzer do
73
73
 
74
74
  context "adapter is enabled" do
75
75
  let(:period_check) { double(period_seconds: 1, max_allowed: 1, block_ttl: nil) }
76
- let(:blocked_ip) { Pause::BlockedAction.new(mock(identifier:ip2), period_check, 200, 1234566) }
77
76
 
78
77
  before do
79
78
  Spanx::IPChecker.should_receive(:tracked_identifiers).and_return([ip1, ip2])
80
- analyzer.should_receive(:analyze_ip).with(ip1)
81
- analyzer.should_receive(:analyze_ip).with(ip2)
79
+ Spanx::IPChecker.should_receive(:new).with(ip1).and_return(mock(analyze: nil))
80
+ Spanx::IPChecker.should_receive(:new).with(ip2).and_return(mock(analyze: nil))
82
81
  end
83
82
 
84
83
  it "analyzes each IP found" do
@@ -105,8 +104,8 @@ describe Spanx::Actor::Analyzer do
105
104
  end
106
105
 
107
106
  it "should publish to notifiers on blocking IP" do
108
- fake_notifier.should_receive(:publish).with(an_instance_of(Pause::BlockedAction))
109
- Spanx::IPChecker.new(ip1).increment!(Time.now.to_i - 5, 50000)
107
+ fake_notifier.should_receive(:publish).with(an_instance_of(Pause::RateLimitedEvent))
108
+ Spanx::IPChecker.new(ip1).increment!(50000, Time.now.to_i - 5)
110
109
  analyzer.analyze_all_ips
111
110
  end
112
111
  end
@@ -19,7 +19,7 @@ describe Spanx::Actor::Writer do
19
19
  end
20
20
 
21
21
  before do
22
- Spanx::IPChecker.stub(:blocked_identifiers).and_return(["1.2.3.4", "127.0.0.1"])
22
+ Spanx::IPChecker.stub(:rate_limited_identifiers).and_return(["1.2.3.4", "127.0.0.1"])
23
23
  end
24
24
 
25
25
  context "when adapter is enabled" do
@@ -6,7 +6,7 @@ describe Spanx::Notifier::Base do
6
6
  let(:time) { Time.now }
7
7
  let(:ip_check) { Spanx::IPChecker.new("1.2.3.4") }
8
8
  let(:period_check) { Pause::PeriodCheck.new(60, 100, 80)}
9
- let(:blocked_action) { Pause::BlockedAction.new(ip_check, period_check, 500, time.to_i)}
9
+ let(:blocked_action) { Pause::RateLimitedEvent.new(ip_check, period_check, 500, time.to_i)}
10
10
 
11
11
  it "should set the correct message content" do
12
12
  Spanx::Notifier::Base.new.send(:generate_block_ip_message, blocked_action).should ==
@@ -47,7 +47,7 @@ describe Spanx::Notifier::Email, "#publish" do
47
47
  let(:time_blocked) { Time.now }
48
48
  let(:period) { mock() }
49
49
  let(:action) { Spanx::IPChecker.new("1.2.3.4") }
50
- let(:blocked_ip) { Pause::BlockedAction.new(action, period, 50, time_blocked) }
50
+ let(:blocked_ip) { Pause::RateLimitedEvent.new(action, period, 50, time_blocked) }
51
51
 
52
52
  before { Spanx::Notifier::Email.any_instance.stub(:configure_email_gateway) }
53
53
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spanx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -19,7 +19,7 @@ dependencies:
19
19
  requirements:
20
20
  - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: 0.0.3
22
+ version: 0.0.4
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,7 +27,7 @@ dependencies:
27
27
  requirements:
28
28
  - - ~>
29
29
  - !ruby/object:Gem::Version
30
- version: 0.0.3
30
+ version: 0.0.4
31
31
  - !ruby/object:Gem::Dependency
32
32
  name: file-tail
33
33
  requirement: !ruby/object:Gem::Requirement
@@ -201,6 +201,7 @@ files:
201
201
  - .pairs
202
202
  - .rspec
203
203
  - .rvmrc
204
+ - .travis.yml
204
205
  - Gemfile
205
206
  - Guardfile
206
207
  - LICENSE
@@ -299,4 +300,3 @@ test_files:
299
300
  - spec/spec_helper.rb
300
301
  - spec/support/fakeredis.rb
301
302
  - spec/support/mail.rb
302
- has_rdoc: