grok 0.0.1 → 0.0.2
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.
- data/README.rdoc +21 -3
- data/VERSION +1 -1
- data/examples/ssh_sentry.rb +1 -1
- data/lib/grok.rb +1 -0
- data/lib/grok/time.rb +57 -0
- data/lib/grok/watcher.rb +19 -3
- metadata +2 -1
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
|
-
==
|
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.
|
41
|
-
|
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
|
+
0.0.2
|
data/examples/ssh_sentry.rb
CHANGED
data/lib/grok.rb
CHANGED
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
|
-
|
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
|
-
|
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.
|
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
|