class MonitorScheduler(threading.Thread): def __init__(self): self.monitor_list = EventList() threading.Thread.__init__(self) def new_monitor(self, type, plugin, watch_rule): if type in ('socket', 'unix_socket'): from MonitorSocket import MonitorSocket monitor = MonitorSocket(plugin, watch_rule) self.monitor_list.appendRule(monitor) elif type == 'database': from MonitorDatabase import MonitorDatabase monitor = MonitorDatabase(plugin, watch_rule) self.monitor_list.appendRule(monitor) elif type == ('command'): from MonitorCommand import MonitorCommand monitor = MonitorCommand(plugin, watch_rule) self.monitor_list.appendRule(monitor) elif type == ('http'): from MonitorHTTP import MonitorHTTP monitor = MonitorHTTP(plugin, watch_rule) self.monitor_list.appendRule(monitor) elif type == ('session'): from MonitorSession import MonitorSession monitor = MonitorSession(plugin, watch_rule) self.monitor_list.appendRule(monitor) # # TODO: still not implemented # # elif type in ('log', 'file'): # from MonitorFile import MonitorFile # monitor = MonitorFile(plugin, watch_rule) # self.monitor_list.appendRule(monitor) # def run(self): logger.debug("Monitor Scheduler started") while 1: remove_monitors = [] for monitor in self.monitor_list: # get monitor from monitor list # process watch-rule and remove from list # TODO: check if monitor is a Monitor instance # if isinstance(monitor, Monitor) if monitor.process(): remove_monitors.append(monitor) for m in remove_monitors: self.monitor_list.removeRule(m) # don't overload agent time.sleep(2)
class EventConsolidation: # name of consolidation section at config.cfg CONSOLIDATION_SECTION = "event-consolidation" MAX_TIME = 60.0 EVENT_OCCURRENCES = "occurrences" # event field for occurrences value def __init__(self, conf): self._conf = conf self.__event_list = EventList() self.start_time = time.time() self.enable = self.__is_consolidation_enable() def __is_consolidation_enable(self): section = EventConsolidation.CONSOLIDATION_SECTION for option in ("enable", "time"): if not self._conf.has_option(section, option): logger.warning("There is no %s option in %s section" % \ (option, EventConsolidation.CONSOLIDATION_SECTION)) return False # exit if enable = False if not self._conf.getboolean(section, "enable"): logger.info("Consolidation is not enabled") return False # "time" must be a float number if not self._conf.getfloat(section, "time"): logger.warning("There is no time variable in %s section" % \ (EventConsolidation.CONSOLIDATION_SECTION)) return False return True def __pass_filters(self, event): section = EventConsolidation.CONSOLIDATION_SECTION # 1) consolidation by plugin if self._conf.has_option(section, "by_plugin"): plugins = Config.split_sids(self._conf.get(section, "by_plugin")) if str(event["plugin_id"]) in plugins: return True # 2) consolidation by src_ip for target in ("src_ip", "dst_ip", "sensor"): option = "by_" + target if self._conf.has_option(section, option): ips = Config.split_sids(self._conf.get(section, option)) if event[target]: if str(event[target]) in ips: return True return False def insert(self, event): if not self.enable: return False if not self.__pass_filters(event): return False self.__event_list.appendRule(event) logger.debug("Added event (id:%s, sid:%s) to consolidation queue" % \ (event["plugin_id"], event["plugin_sid"])) Stats.consolidation['total'] += 1 return True # clear consolidation queue processing its events # and removing them from the list def clear(self): events_to_remove = [] for event in self.__event_list: Output.event(event) events_to_remove.append(event) Stats.consolidation['consolidated'] += 1 for e in events_to_remove: self.__event_list.removeRule(e) del events_to_remove def __process(self): # tmp set to store event representation event_tmp = {} events_to_remove = [] for event in self.__event_list: # save non comparable attributes date = event["date"] log = event["log"] event["date"] = event["log"] = "" str_event = str(event).strip() if event_tmp.has_key(str_event): events_to_remove.append(event) event_tmp[str_event] += 1 else: event_tmp[str_event] = 1 # restore non comparable attributes if date: event["date"] = date if log: event["log"] = log # remove duplicated events for e in events_to_remove: self.__event_list.removeRule(e) del events_to_remove # fill "occurrences" field for event in self.__event_list: date = event["date"] log = event["log"] event["date"] = event["log"] = "" str_event = str(event).strip() if event_tmp.has_key(str_event): occurrences = int(event_tmp[str_event]) if occurrences > 1: event[EventConsolidation.EVENT_OCCURRENCES] = \ str(occurrences) if date: event["date"] = date if log: event["log"] = log self.clear() def process(self): if not self.enable: return False section = EventConsolidation.CONSOLIDATION_SECTION restart_time = self._conf.getfloat(section, "time") if restart_time > EventConsolidation.MAX_TIME: restart_time = EventConsolidation.MAX_TIME current_time = time.time() if self.start_time + restart_time < current_time: if len(self) > 0: self.__process() # back to begining self.start_time = time.time() def __len__(self): return len(self.__event_list)