Class: REC::Rule

Inherits:
Object
  • Object
show all
Defined in:
lib/rec/rule.rb

Overview

A Rule specifies which log entries to match, what to remember, and what to do about them.

Constant Summary collapse

@@rules =
[]
@@index =

hash index of rules to allow lookup of messages etc.

{}
@@checked =
{}
@@matched =
{}
@@created =
{}
@@reacted =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rid, params = {}, &action) ⇒ Rule

Creates a new rule. rid must be unique.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/rec/rule.rb', line 77

def initialize(rid, params={}, &action)
	@rid = rid
	@pattern = params[:pattern] || raise("No pattern specified for rule #{@ruleId}")
	@message = params[:message] || ""	# no message means no state created - ie. ignore event
	@lifespan = params[:lifespan] || 0
	@alert = params[:alert] || @message
	@allstates = params[:allstates] || []
	@anystates = params[:anystates] || []
	@notstates = params[:notstates] || []
	@details = params[:details] || []
	@params = params
	@action = action
	@matches = nil
	Rule << self
end

Instance Attribute Details

#actionObject (readonly)

block to be executed when #react is called. For example: Rule.new(10035, { :pattern => /^sw+sFirewall:sSkype is listening from 0.0.0.0:(d+)/, :details => [”port“], :message => ”Skype conversation started on port %port$d“, :alert => ”Skype running on port %port$d“, :lifespan => 479 }) { |state| state.alert_first_only() }



74
75
76
# File 'lib/rec/rule.rb', line 74

def action
  @action
end

#alertObject (readonly)

the template for an alert message to be generated should it be necessary



61
62
63
# File 'lib/rec/rule.rb', line 61

def alert
  @alert
end

#lifespanObject (readonly)

the time in seconds for a created state to persist



59
60
61
# File 'lib/rec/rule.rb', line 59

def lifespan
  @lifespan
end

#messageObject (readonly)

the template for the title of any state created. :message => “sudo activity for user %userid$s”, will create states with titles like “sudo activity for user richard”



57
58
59
# File 'lib/rec/rule.rb', line 57

def message
  @message
end

#paramsObject (readonly)

hash of the rules parameters, passed in when creating the rule



63
64
65
# File 'lib/rec/rule.rb', line 63

def params
  @params
end

#patternObject (readonly)

the regexp pattern to match an original log entry against :pattern => /^sw+sFirewall:sSkype is listening from 0.0.0.0:(d+)/, :details => [”port“], Note that regexp captures must correspond to customer field names in details



53
54
55
# File 'lib/rec/rule.rb', line 53

def pattern
  @pattern
end

#ridObject (readonly)

the unique ID of the rule



48
49
50
# File 'lib/rec/rule.rb', line 48

def rid
  @rid
end

Class Method Details

.<<(rule) ⇒ Object

Adds a rule to the ruleset



22
23
24
25
26
27
28
29
# File 'lib/rec/rule.rb', line 22

def self.<<(rule)
	@@rules << rule
	@@index[rule.rid] = rule
	@@checked[rule.rid] = 0
	@@matched[rule.rid] = 0
	@@created[rule.rid] = 0
	@@reacted[rule.rid] = 0
end

.[](rid) ⇒ Object

Get a rule belonging to the key of rid



32
33
34
# File 'lib/rec/rule.rb', line 32

def self.[](rid)
	@@index[rid]
end

.each(&block) ⇒ Object

Convenience method to iterate through the ruleset



17
18
19
# File 'lib/rec/rule.rb', line 17

def self.each(&block)
	@@rules.each(&block)
end

.statsObject

Returns some summary statistics in a 5-element array, the first four elements a hash keyed on rule ID, the fifth is an array of rules:

  1. number of times each rule was checked

  2. number of times each rule was matched

  3. number of states created by each rule

  4. number of times #react was called on each rule

  5. list of rules, evaluated in sequence for each event



43
44
45
# File 'lib/rec/rule.rb', line 43

def self.stats()
	[@@checked, @@matched, @@created, @@reacted, @@rules]
end

Instance Method Details

#check(logMessage) ⇒ Object

Checks the original logMessage against the rule, looking for a match.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/rec/rule.rb', line 94

def check(logMessage)
	@@checked[@rid] += 1
	matchData = @pattern.match(logMessage) || return
	@matches = Hash[@details.zip(matchData.to_a()[1..-1])]	# map matched values to detail keys
	# if any notstates are specified, make sure none are present
	@notstates.each { |str| return if State[str.sprinth(@matches)]	}
	# if any allstates are specified, they all need to be present
	@allstates.each { |str| return unless State[str.sprinth(@matches)]	}
	# if anystates are specified, we must find one that matches
	return unless @anystates.empty? or @anystates.detect {|str| State[str.sprinth(@matches)] }
	title = @message.sprinth(@matches)
	@@matched[@rid] += 1
	return(title)
end

#continueObject

Returns the continue parameter. If false, stop processing rules for this event.



125
126
127
# File 'lib/rec/rule.rb', line 125

def continue()
	@params[:continue]
end

#create_state(title, time) ⇒ Object

Creates a state with the given title at the specified time



110
111
112
113
114
# File 'lib/rec/rule.rb', line 110

def create_state(title, time)
	@@created[@rid] += 1
	$stderr.puts("+ Creating new state  #{title}") if $debug
	State.new(title, time, @lifespan, @params)
end

#react(state, time, logLine) ⇒ Object

Executes any action specified by the rule



117
118
119
120
121
122
# File 'lib/rec/rule.rb', line 117

def react(state, time, logLine)
	@@reacted[@rid] += 1
	state.update(time, @rid, @matches, @alert, logLine)
	$stderr.puts("~ Rule #{@rid}, state = #{state.inspect()}") if $debug
	@action.call(state) if @action
end