11 def __init__ (self, event_type) : |
11 def __init__ (self, event_type) : |
12 self.event_type = event_type |
12 self.event_type = event_type |
13 |
13 |
14 def test (self, line) : |
14 def test (self, line) : |
15 """ |
15 """ |
16 Match against the given line, and return one of: |
16 Match against the given line. See match() for return codes |
|
17 """ |
17 |
18 |
|
19 raise NotImplementedError() |
|
20 |
|
21 def match (self, msg) : |
|
22 """ |
|
23 Match against the given SyslogMessage, and return one of: |
18 None - filter did not match, continue |
24 None - filter did not match, continue |
19 False - filter matched, line should be dropped |
25 False - filter matched, line should be dropped |
20 (type, <str>) |
26 (type, <str>) |
21 - filter matched, pass formatted output |
27 - filter matched, pass formatted output |
22 """ |
28 """ |
23 |
29 |
24 raise NotImplementedError() |
30 # default to a full-line match |
|
31 return self.test(str(msg)) |
25 |
32 |
26 class FullFilter (BaseFilter) : |
33 class FullFilter (BaseFilter) : |
27 """ |
34 """ |
28 A trivial filter that matches every possible line as-is |
35 A trivial filter that matches every possible line as-is |
29 """ |
36 """ |
35 class NullFilter (BaseFilter) : |
42 class NullFilter (BaseFilter) : |
36 """ |
43 """ |
37 A filter that drops every line matching a given regexp |
44 A filter that drops every line matching a given regexp |
38 """ |
45 """ |
39 |
46 |
40 def __init__ (self, pattern, flags=None) : |
47 def __init__ (self, pattern, flags=0) : |
41 # don't need an event_type |
48 # don't need an event_type |
42 |
49 |
43 self.regexp = re.compile(pattern, flags) |
50 self.regexp = re.compile(pattern, flags) |
44 |
51 |
45 def test (self, line) : |
52 def test (self, line) : |
77 |
84 |
78 else : |
85 else : |
79 # match as-is |
86 # match as-is |
80 return self.event_type, line |
87 return self.event_type, line |
81 |
88 |
|
89 class SyslogFilter (BaseFilter) : |
|
90 """ |
|
91 A more advanced filter that can match against fields in the syslog message. |
|
92 """ |
|
93 |
|
94 def __init__ (self, label, pattern=None, program=None, drop=False, format=None, re_flags=0) : |
|
95 """ |
|
96 Filter using the given criteria: |
|
97 |
|
98 label - label match output with given label |
|
99 |
|
100 pattern - match message content against given regexp |
|
101 program - (optional) case-insensitive match against message tag's program component |
|
102 May also be False to indicate no tag |
|
103 |
|
104 drop - drop this message if this matches |
|
105 format - (optional) format output with given format string |
|
106 |
|
107 re_flags - (optional) flags for regular expression |
|
108 """ |
|
109 |
|
110 # XXX: super(SyslogFilter, self).__init__(label) |
|
111 self.label = label |
|
112 |
|
113 # store |
|
114 self.regexp = re.compile(pattern, re_flags) |
|
115 self.program = program |
|
116 |
|
117 self.drop = drop |
|
118 self.format = format |
|
119 |
|
120 def match (self, msg) : |
|
121 """ |
|
122 Evaluate match on given message |
|
123 """ |
|
124 |
|
125 # use the SyslogMessage's match method |
|
126 match = msg.match(self.regexp, self.program) |
|
127 |
|
128 # handle result |
|
129 if match is False : |
|
130 # nack |
|
131 return None |
|
132 |
|
133 elif self.drop : |
|
134 # halt processing |
|
135 return False |
|
136 |
|
137 elif self.format : |
|
138 # the messages properties |
|
139 params = msg.properties() |
|
140 |
|
141 # the regexp'd matched params |
|
142 params.update(match) |
|
143 |
|
144 # formatted output |
|
145 return self.label, self.format % params |
|
146 |
|
147 else : |
|
148 # boring output |
|
149 return self.label, str(msg) |
|
150 |
|
151 |
82 # matches a timestamp prefix |
152 # matches a timestamp prefix |
83 _timestamp = "\w{3} [0-9 ]\d \d{2}:\d{2}:\d{2}" |
153 _timestamp = "\w{3} [0-9 ]\d \d{2}:\d{2}:\d{2}" |
84 |
154 |
85 |
155 |
86 # matches all lines |
156 # matches all lines |
92 "^" + _timestamp + " (?P<line>.+)$", |
162 "^" + _timestamp + " (?P<line>.+)$", |
93 "%(line)s" |
163 "%(line)s" |
94 ) |
164 ) |
95 |
165 |
96 # match sudo invocations, reformatting them nicely |
166 # match sudo invocations, reformatting them nicely |
97 sudo = SimpleFilter( |
167 sudo = SyslogFilter('sudo', |
98 "sudo", |
168 program = "sudo", |
99 "(?P<hostname>\S+)\s+sudo:\s*(?P<username>\S+) : TTY=(?P<tty>\S+) ; PWD=(?P<pwd>.+?) ; USER=(?P<target_user>\S+) ; COMMAND=(?P<command>.*)", |
169 pattern = "^\s*(?P<username>\S+) : TTY=(?P<tty>\S+) ; PWD=(?P<pwd>.+?) ; USER=(?P<target_user>\S+) ; COMMAND=(?P<command>.*)", |
100 "%(username)s:%(tty)s - %(target_user)s@%(hostname)s:%(pwd)s - %(command)r" |
170 format = "%(username)s:%(tty)s - %(target_user)s@%(hostname)s:%(pwd)s - %(command)r", |
101 ) |
171 ) |
|
172 |
|
173 #sudo = SimpleFilter( |
|
174 # "sudo", |
|
175 # "(?P<hostname>\S+)\s+sudo:\s*(?P<username>\S+) : TTY=(?P<tty>\S+) ; PWD=(?P<pwd>.+?) ; USER=(?P<target_user>\S+) ; COMMAND=(?P<command>.*)", |
|
176 # "%(username)s:%(tty)s - %(target_user)s@%(hostname)s:%(pwd)s - %(command)r" |
|
177 #) |
102 |
178 |
103 # match accepted ssh logins |
179 # match accepted ssh logins |
104 ssh = SimpleFilter( |
180 ssh = SimpleFilter( |
105 "ssh", |
181 "ssh", |
106 "(?P<hostname>\S+)\s+sshd\[\d+\]:\s*Accepted password for (?P<username>\S+) from (?P<ip>\S+) port (?P<port>\S+) (?P<proto>\S+)", |
182 "(?P<hostname>\S+)\s+sshd\[\d+\]:\s*Accepted password for (?P<username>\S+) from (?P<ip>\S+) port (?P<port>\S+) (?P<proto>\S+)", |