grok 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -3,7 +3,7 @@
3
3
  Grok aims to be a replacement for the now antiquated SEC (Simple Event
4
4
  Correlator).
5
5
 
6
- == Usage
6
+ == Getting started
7
7
  A simple Grok watcher needs very little in the way of configuration
8
8
  require 'grok'
9
9
 
@@ -37,8 +37,26 @@ RegExp functionality in the event handlers
37
37
  puts "SSH authentication failure for #{username} from #{ip}"
38
38
  end
39
39
 
40
- This is a bit better. You could go further to have it automatically block the
41
- IP with iptables if you wanted (see examples/ssh_sentry.rb).
40
+ This is a bit better. It seems a bit unfair to block someone for a single typo
41
+ though, so why don't we give them three tries before blocking them?
42
+
43
+ on /sshd\[\d+\]: Failed password for ([\d\w]+) from ([\d\.]+)/, :times => 3 do |username, ip|
44
+ puts "SSH authentication failure for #{username} from #{ip}"
45
+ end
46
+
47
+ Getting there. What if our user failed a couple of times over the past month?
48
+ We don't really want to him out for that, so we'll put a time limit on the rule
49
+ so only 3 incorrect login attempts within the past 2 minutes will trigger it.
50
+
51
+ on /sshd\[\d+\]: Failed password for ([\d\w]+) from ([\d\.]+)/, :times => 3, :withn => '2m' do |username, ip|
52
+ puts "SSH authentication failure for #{username} from #{ip}"
53
+ end
54
+
55
+ Your time string can be made of any combination of years (y), months (M),
56
+ weeks (w), days (d), hours (h), minutes (m) and seconds (s). For example
57
+
58
+ '1d2h3s' => 1 day, 2 hours and 3 seconds
59
+ '2y3m' => 2 years and 3 minutes
42
60
 
43
61
  == Note on Patches/Pull Requests
44
62
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -6,6 +6,6 @@ configure do |c|
6
6
  c.replay = 0
7
7
  end
8
8
 
9
- on /Failed password for root from ([\d\.]+)/ do |ip|
9
+ on /Failed password for root from ([\d\.]+)/, :times => 3, :within => '2m' do |ip|
10
10
  ret = `/sbin/iptables -I INPUT --source #{ip} -j REJECT`
11
11
  end
data/lib/grok.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'grok/watcher'
2
+ require 'grok/time'
2
3
 
3
4
  $watcher = Grok::Watcher.new
4
5
 
data/lib/grok/time.rb ADDED
@@ -0,0 +1,57 @@
1
+ # This bit of code has been shamelessly stolen from rufus-scheduler because
2
+ # it's awesome.
3
+
4
+ module Grok
5
+ def Grok.parse_time_string(string)
6
+ string = string.strip
7
+ index = -1
8
+ result = 0.0
9
+
10
+ number = ''
11
+ loop do
12
+ index = index+1
13
+
14
+ if index >= string.length
15
+ result += (Float(number) / 1000.0) if number.length > 0
16
+ break
17
+ end
18
+
19
+ c = string[index, 1]
20
+
21
+ if (c >= '0' and c <= '9')
22
+ number += c
23
+ next
24
+ end
25
+
26
+ value = Integer(number)
27
+ number = ''
28
+ multiplier = DURATIONS[c]
29
+
30
+ raise "unknown time char '#{c}'" unless multiplier
31
+
32
+ result += (value * multiplier)
33
+ end
34
+
35
+ result
36
+ end
37
+
38
+ protected
39
+
40
+ DURATIONS2M = [
41
+ [ 'y', 365 * 24 * 3600 ],
42
+ [ 'M', 30 * 24 * 3600 ],
43
+ [ 'w', 7 * 24 * 3600 ],
44
+ [ 'd', 24 * 3600 ],
45
+ [ 'h', 3600 ],
46
+ [ 'm', 60 ],
47
+ [ 's', 1 ]
48
+ ]
49
+
50
+ DURATIONS2 = DURATIONS2M.dup
51
+ DURATIONS2.delete_at(1)
52
+
53
+ DURATIONS = DURATIONS2M.inject({}) do |r, (k, v)|
54
+ r[k] = v
55
+ r
56
+ end
57
+ end
data/lib/grok/watcher.rb CHANGED
@@ -9,6 +9,7 @@ module Grok
9
9
 
10
10
  def initialize(&b)
11
11
  @events = {}
12
+ @event_log = {}
12
13
  @config = Config.new("/var/log/messages", 10)
13
14
 
14
15
  #instance_eval(&b) if block_given?
@@ -21,7 +22,8 @@ module Grok
21
22
  def on(match, opts={}, &block)
22
23
  event = :log
23
24
  match = match.to_s if match.is_a? Integer
24
- (@events[event] ||= []) << [Regexp.new(match), block]
25
+ within = opts[:within] ? Grok.parse_time_string(opts[:within]) : nil
26
+ (@events[event] ||= []) << [Regexp.new(match), block, opts[:times], within]
25
27
  end
26
28
 
27
29
  def start
@@ -61,9 +63,23 @@ module Grok
61
63
 
62
64
  def dispatch(event, log)
63
65
  if handler = find(event, log)
64
- regexp, block = *handler
66
+ regexp, block, times, within = *handler
65
67
  self.match = log.match(regexp).captures
66
- invoke block
68
+ (@event_log[match] ||= []) << Time.now.to_i
69
+ if @event_log[match].length >= times.to_i
70
+ if within:
71
+ times_within_range = @event_log[match].reject { |event_time|
72
+ event_time < (Time.now.to_i - within)
73
+ }
74
+ if times_within_range.length >= times.to_i
75
+ invoke block
76
+ @event_log[match].clear
77
+ end
78
+ else
79
+ invoke block
80
+ @event_log[match].clear
81
+ end
82
+ end
67
83
  end
68
84
  end
69
85
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grok
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Sharpe
@@ -50,6 +50,7 @@ files:
50
50
  - VERSION
51
51
  - examples/ssh_sentry.rb
52
52
  - lib/grok.rb
53
+ - lib/grok/time.rb
53
54
  - lib/grok/watcher.rb
54
55
  - test/helper.rb
55
56
  - test/test_grok.rb