From 01499ad0de00b2a0ca2d06959f8643ad0a2f5105 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Thu, 18 Apr 2013 22:07:19 +0100 Subject: [PATCH 1/7] NF: Filters now allow adding of [Init] section similar to actions --- fail2ban/client/actionreader.py | 72 +++++++++----------------- fail2ban/client/configreader.py | 37 +++++++++++++ fail2ban/client/filterreader.py | 45 +++++----------- fail2ban/client/jailreader.py | 47 +++++++++-------- fail2ban/tests/clientreadertestcase.py | 6 +-- 5 files changed, 103 insertions(+), 104 deletions(-) diff --git a/fail2ban/client/actionreader.py b/fail2ban/client/actionreader.py index 787a41c7..b9211a1b 100644 --- a/fail2ban/client/actionreader.py +++ b/fail2ban/client/actionreader.py @@ -28,66 +28,42 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" import logging -from configreader import ConfigReader +from configreader import ConfigReader, OptionConfigReader # Gets the instance of the logger. logSys = logging.getLogger(__name__) -class ActionReader(ConfigReader): - - def __init__(self, action, name, **kwargs): - ConfigReader.__init__(self, **kwargs) - self.__file = action[0] - self.__cInfo = action[1] - self.__name = name - - def setFile(self, fileName): - self.__file = fileName - - def getFile(self): - return self.__file - - def setName(self, name): - self.__name = name - - def getName(self): - return self.__name - +class ActionReader(OptionConfigReader): + + _configOpts = [ + ["string", "actionstart", ""], + ["string", "actionstop", ""], + ["string", "actioncheck", ""], + ["string", "actionban", ""], + ["string", "actionunban", ""], + ] + def read(self): - return ConfigReader.read(self, "action.d/" + self.__file) - - def getOptions(self, pOpts): - opts = [["string", "actionstart", ""], - ["string", "actionstop", ""], - ["string", "actioncheck", ""], - ["string", "actionban", ""], - ["string", "actionunban", ""]] - self.__opts = ConfigReader.getOptions(self, "Definition", opts, pOpts) - - if self.has_section("Init"): - for opt in self.options("Init"): - if not self.__cInfo.has_key(opt): - self.__cInfo[opt] = self.get("Init", opt) - + return ConfigReader.read(self, "action.d/" + self._file) + def convert(self): - head = ["set", self.__name] + head = ["set", self._name] stream = list() - stream.append(head + ["addaction", self.__file]) - for opt in self.__opts: + stream.append(head + ["addaction", self._file]) + for opt in self._opts: if opt == "actionstart": - stream.append(head + ["actionstart", self.__file, self.__opts[opt]]) + stream.append(head + ["actionstart", self._file, self._opts[opt]]) elif opt == "actionstop": - stream.append(head + ["actionstop", self.__file, self.__opts[opt]]) + stream.append(head + ["actionstop", self._file, self._opts[opt]]) elif opt == "actioncheck": - stream.append(head + ["actioncheck", self.__file, self.__opts[opt]]) + stream.append(head + ["actioncheck", self._file, self._opts[opt]]) elif opt == "actionban": - stream.append(head + ["actionban", self.__file, self.__opts[opt]]) + stream.append(head + ["actionban", self._file, self._opts[opt]]) elif opt == "actionunban": - stream.append(head + ["actionunban", self.__file, self.__opts[opt]]) + stream.append(head + ["actionunban", self._file, self._opts[opt]]) # cInfo - if self.__cInfo: - for p in self.__cInfo: - stream.append(head + ["setcinfo", self.__file, p, self.__cInfo[p]]) + if self._initOpts: + for p in self._initOpts: + stream.append(head + ["setcinfo", self._file, p, self._initOpts[p]]) return stream - diff --git a/fail2ban/client/configreader.py b/fail2ban/client/configreader.py index 6f1e7740..4cb9cd69 100644 --- a/fail2ban/client/configreader.py +++ b/fail2ban/client/configreader.py @@ -130,3 +130,40 @@ class ConfigReader(SafeConfigParserWithIncludes): "'. Using default one: '" + `option[2]` + "'") values[option[1]] = option[2] return values + +class OptionConfigReader(ConfigReader): + + _configOpts = [] + + def __init__(self, file_, jailName, initOpts, **kwargs): + ConfigReader.__init__(self, **kwargs) + self._file = file_ + self._name = jailName + self._initOpts = initOpts + + def setFile(self, fileName): + self._file = fileName + + def getFile(self): + return self.__file + + def setName(self, name): + self._name = name + + def getName(self): + return self._name + + def read(self): + return ConfigReader.read(self, self._file) + + def getOptions(self, pOpts): + self._opts = ConfigReader.getOptions( + self, "Definition", self._configOpts, pOpts) + + if self.has_section("Init"): + for opt in self.options("Init"): + if not self._initOpts.has_key(opt): + self._initOpts[opt] = self.get("Init", opt) + + def convert(self): + raise NotImplementedError diff --git a/fail2ban/client/filterreader.py b/fail2ban/client/filterreader.py index 8b00446e..bdfba4d0 100644 --- a/fail2ban/client/filterreader.py +++ b/fail2ban/client/filterreader.py @@ -28,50 +28,33 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" import logging -from configreader import ConfigReader +from configreader import ConfigReader, OptionConfigReader # Gets the instance of the logger. logSys = logging.getLogger(__name__) -class FilterReader(ConfigReader): - - def __init__(self, fileName, name, **kwargs): - ConfigReader.__init__(self, **kwargs) - self.__file = fileName - self.__name = name - - def setFile(self, fileName): - self.__file = fileName - - def getFile(self): - return self.__file - - def setName(self, name): - self.__name = name - - def getName(self): - return self.__name - +class FilterReader(OptionConfigReader): + + _configOpts = [ + ["string", "ignoreregex", ""], + ["string", "failregex", ""], + ] + def read(self): - return ConfigReader.read(self, "filter.d/" + self.__file) - - def getOptions(self, pOpts): - opts = [["string", "ignoreregex", ""], - ["string", "failregex", ""]] - self.__opts = ConfigReader.getOptions(self, "Definition", opts, pOpts) + return ConfigReader.read(self, "filter.d/" + self._file) def convert(self): stream = list() - for opt in self.__opts: + for opt in self._opts: if opt == "failregex": - for regex in self.__opts[opt].split('\n'): + for regex in self._opts[opt].split('\n'): # Do not send a command if the rule is empty. if regex != '': - stream.append(["set", self.__name, "addfailregex", regex]) + stream.append(["set", self._name, "addfailregex", regex]) elif opt == "ignoreregex": - for regex in self.__opts[opt].split('\n'): + for regex in self._opts[opt].split('\n'): # Do not send a command if the rule is empty. if regex != '': - stream.append(["set", self.__name, "addignoreregex", regex]) + stream.append(["set", self._name, "addignoreregex", regex]) return stream diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index 6e35bc0b..f6ac09b3 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -38,7 +38,7 @@ logSys = logging.getLogger(__name__) class JailReader(ConfigReader): - actionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$") + optionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$") def __init__(self, name, force_enable=False, **kwargs): ConfigReader.__init__(self, **kwargs) @@ -78,8 +78,10 @@ class JailReader(ConfigReader): if self.isEnabled(): # Read filter - self.__filter = FilterReader(self.__opts["filter"], self.__name, - basedir=self.getBaseDir()) + filterName, filterOpt = JailReader.splitOption( + self.__opts["filter"]) + self.__filter = FilterReader( + filterName, self.__name, filterOpt, basedir=self.getBaseDir()) ret = self.__filter.read() if ret: self.__filter.getOptions(self.__opts) @@ -92,8 +94,9 @@ class JailReader(ConfigReader): try: if not act: # skip empty actions continue - splitAct = JailReader.splitAction(act) - action = ActionReader(splitAct, self.__name, basedir=self.getBaseDir()) + actName, actOpt = JailReader.splitOption(act) + action = ActionReader( + actName, self.__name, actOpt, basedir=self.getBaseDir()) ret = action.read() if ret: action.getOptions(self.__opts) @@ -151,23 +154,23 @@ class JailReader(ConfigReader): return stream #@staticmethod - def splitAction(action): - m = JailReader.actionCRE.match(action) + def splitOption(option): + m = JailReader.optionCRE.match(option) d = dict() mgroups = m.groups() if len(mgroups) == 2: - action_name, action_opts = mgroups + option_name, option_opts = mgroups elif len(mgroups) == 1: - action_name, action_opts = mgroups[0], None + option_name, option_opts = mgroups[0], None else: - raise ValueError("While reading action %s we should have got up to " - "2 groups. Got: %r" % (action, mgroups)) - if not action_opts is None: + raise ValueError("While reading option %s we should have got up to " + "2 groups. Got: %r" % (option, mgroups)) + if not option_opts is None: # Huge bad hack :( This method really sucks. TODO Reimplement it. - actions = "" + options = "" escapeChar = None allowComma = False - for c in action_opts: + for c in option_opts: if c in ('"', "'") and not allowComma: # Start escapeChar = c @@ -178,20 +181,20 @@ class JailReader(ConfigReader): allowComma = False else: if c == ',' and allowComma: - actions += "" + options += "" else: - actions += c + options += c # Split using , - actionsSplit = actions.split(',') + optionsSplit = options.split(',') # Replace the tag with , - actionsSplit = [n.replace("", ',') for n in actionsSplit] + optionsSplit = [n.replace("", ',') for n in optionsSplit] - for param in actionsSplit: + for param in optionsSplit: p = param.split('=') try: d[p[0].strip()] = p[1].strip() except IndexError: - logSys.error("Invalid argument %s in '%s'" % (p, action_opts)) - return [action_name, d] - splitAction = staticmethod(splitAction) + logSys.error("Invalid argument %s in '%s'" % (p, option_opts)) + return [option_name, d] + splitOption = staticmethod(splitOption) diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index d721ef00..02c65d35 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -112,10 +112,10 @@ class JailReaderTest(unittest.TestCase): self.assertFalse(jail.isEnabled()) self.assertEqual(jail.getName(), 'ssh-iptables') - def testSplitAction(self): + def testSplitOption(self): action = "mail-whois[name=SSH]" expected = ['mail-whois', {'name': 'SSH'}] - result = JailReader.splitAction(action) + result = JailReader.splitOption(action) self.assertEquals(expected, result) class FilterReaderTest(unittest.TestCase): @@ -140,7 +140,7 @@ class FilterReaderTest(unittest.TestCase): "+$^.+ module for .* from \\s*$"], ['set', 'testcase01', 'addignoreregex', "^.+ john from host 192.168.1.1\\s*$"]] - filterReader = FilterReader("testcase01", "testcase01") + filterReader = FilterReader("testcase01", "testcase01", {}) filterReader.setBaseDir(TEST_FILES_DIR) filterReader.read() #filterReader.getOptions(["failregex", "ignoreregex"]) From 9672e44d391d155a17627cbe38736ebb4b141045 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Thu, 18 Apr 2013 22:11:41 +0100 Subject: [PATCH 2/7] ENH: Move jail `maxlines` to filter config --- config/filter.d/guacamole.conf | 4 ++++ config/jail.conf | 4 ---- fail2ban/client/filterreader.py | 3 +++ fail2ban/client/jailreader.py | 1 - man/jail.conf.5 | 5 +++++ 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/config/filter.d/guacamole.conf b/config/filter.d/guacamole.conf index 272460e3..49cecc5a 100644 --- a/config/filter.d/guacamole.conf +++ b/config/filter.d/guacamole.conf @@ -16,3 +16,7 @@ failregex = ^.*\nWARNING: Authentication attempt from for user "[^"]*" fa # Values: TEXT # ignoreregex = + +[Init] +# "maxlines" is number of log lines to buffer for multi-line regex searches +maxlines = 2 diff --git a/config/jail.conf b/config/jail.conf index 7ed1bbb6..e8d6db05 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -32,9 +32,6 @@ findtime = 600 # "maxretry" is the number of failures before a host get banned. maxretry = 3 -# "maxlines" is number of log lines to buffer for multi-line regex searches -maxlines = 1 - # "backend" specifies the backend used to get files modification. # Available options are "pyinotify", "gamin", "polling" and "auto". # This option can be overridden in each jail as well. @@ -375,7 +372,6 @@ action = iptables-multiport[name=Guacmole, port="http,https"] sendmail-whois[name=Guacamole, dest=root, sender=fail2ban@example.com] logpath = /var/log/tomcat*/catalina.out maxretry = 5 -maxlines = 2 # Jail for more extended banning of persistent abusers diff --git a/fail2ban/client/filterreader.py b/fail2ban/client/filterreader.py index bdfba4d0..09f0e6a8 100644 --- a/fail2ban/client/filterreader.py +++ b/fail2ban/client/filterreader.py @@ -56,5 +56,8 @@ class FilterReader(OptionConfigReader): # Do not send a command if the rule is empty. if regex != '': stream.append(["set", self._name, "addignoreregex", regex]) + if self._initOpts: + if 'maxlines' in self._initOpts: + stream.append(["set", self._name, "maxlines", self._initOpts["maxlines"]]) return stream diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index f6ac09b3..39acc446 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -65,7 +65,6 @@ class JailReader(ConfigReader): ["string", "logencoding", "auto"], ["string", "backend", "auto"], ["int", "maxretry", 3], - ["int", "maxlines", 1], ["int", "findtime", 600], ["int", "bantime", 600], ["string", "usedns", "warn"], diff --git a/man/jail.conf.5 b/man/jail.conf.5 index 552b0ac0..d571dc7b 100644 --- a/man/jail.conf.5 +++ b/man/jail.conf.5 @@ -140,6 +140,11 @@ Using Python "string interpolation" mechanisms, other definitions are allowed an baduseragents = IE|wget failregex = useragent=%(baduseragents)s +.PP +Similar to actions, filters have an [Init] section which can be overridden in \fIjail.conf/jail.local\fR. The filter [Init] section is limited to the following options: +.TP +\fBmaxlines\fR +specifies the maximum number of lines to buffer to match multi-line regexs. For some log formats this will not required to be changed. Other logs may require to increase this value if a particular log file is frequently written to. .PP Filters can also have a section called [INCLUDES]. This is used to read other configuration files. From 5b227b6670e4d25de7f741d6441a1ff12be6b5ae Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Thu, 18 Apr 2013 22:33:42 +0100 Subject: [PATCH 3/7] TST: Add test for FilterReader [Init] `maxlines` override --- fail2ban/tests/clientreadertestcase.py | 12 +++++++++++- fail2ban/tests/files/filter.d/testcase01.conf | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 02c65d35..3e0b555d 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -139,7 +139,8 @@ class FilterReaderTest(unittest.TestCase): "error: PAM: )?User not known to the\\nunderlying authentication." "+$^.+ module for .* from \\s*$"], ['set', 'testcase01', 'addignoreregex', - "^.+ john from host 192.168.1.1\\s*$"]] + "^.+ john from host 192.168.1.1\\s*$"], + ['set', 'testcase01', 'maxlines', "1"]] filterReader = FilterReader("testcase01", "testcase01", {}) filterReader.setBaseDir(TEST_FILES_DIR) filterReader.read() @@ -150,6 +151,15 @@ class FilterReaderTest(unittest.TestCase): # is unreliable self.assertEquals(sorted(filterReader.convert()), sorted(output)) + filterReader = FilterReader( + "testcase01", "testcase01", {'maxlines': "5"}) + filterReader.setBaseDir(TEST_FILES_DIR) + filterReader.read() + #filterReader.getOptions(["failregex", "ignoreregex"]) + filterReader.getOptions(None) + output[-1][-1] = "5" + self.assertEquals(sorted(filterReader.convert()), sorted(output)) + class JailsReaderTest(unittest.TestCase): def testProvidingBadBasedir(self): diff --git a/fail2ban/tests/files/filter.d/testcase01.conf b/fail2ban/tests/files/filter.d/testcase01.conf index 4a3a95e9..c549572d 100644 --- a/fail2ban/tests/files/filter.d/testcase01.conf +++ b/fail2ban/tests/files/filter.d/testcase01.conf @@ -32,3 +32,7 @@ failregex = ^%(__prefix_line)s(?:error: PAM: )?Authentication failure for .* fro # Values: TEXT # ignoreregex = ^.+ john from host 192.168.1.1\s*$ + +[Init] +# "maxlines" is number of log lines to buffer for multi-line regex searches +maxlines = 1 From b47ea7f81334d8bb03f234653b446bbfe256a859 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Fri, 19 Apr 2013 18:17:56 +0100 Subject: [PATCH 4/7] ENH: Remove redundant `maxlines` option from jail reader --- fail2ban/client/jailreader.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index 39acc446..0599a85e 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -126,8 +126,6 @@ class JailReader(ConfigReader): backend = self.__opts[opt] elif opt == "maxretry": stream.append(["set", self.__name, "maxretry", self.__opts[opt]]) - elif opt == "maxlines": - stream.append(["set", self.__name, "maxlines", self.__opts[opt]]) elif opt == "ignoreip": for ip in self.__opts[opt].split(): # Do not send a command if the rule is empty. From c95b87c13ceda7e08f0152982590eb93562f6861 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sun, 21 Apr 2013 11:21:06 +0100 Subject: [PATCH 5/7] ENH: Use os.path.join for filter/action config readers --- fail2ban/client/actionreader.py | 4 ++-- fail2ban/client/filterreader.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fail2ban/client/actionreader.py b/fail2ban/client/actionreader.py index b9211a1b..70c5b3a7 100644 --- a/fail2ban/client/actionreader.py +++ b/fail2ban/client/actionreader.py @@ -27,7 +27,7 @@ __date__ = "$Date$" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import logging +import logging, os from configreader import ConfigReader, OptionConfigReader # Gets the instance of the logger. @@ -44,7 +44,7 @@ class ActionReader(OptionConfigReader): ] def read(self): - return ConfigReader.read(self, "action.d/" + self._file) + return ConfigReader.read(self, os.path.join("action.d", self._file)) def convert(self): head = ["set", self._name] diff --git a/fail2ban/client/filterreader.py b/fail2ban/client/filterreader.py index 09f0e6a8..19a3f0f3 100644 --- a/fail2ban/client/filterreader.py +++ b/fail2ban/client/filterreader.py @@ -27,7 +27,7 @@ __date__ = "$Date$" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import logging +import logging, os from configreader import ConfigReader, OptionConfigReader # Gets the instance of the logger. @@ -41,7 +41,7 @@ class FilterReader(OptionConfigReader): ] def read(self): - return ConfigReader.read(self, "filter.d/" + self._file) + return ConfigReader.read(self, os.path.join("filter.d", self._file)) def convert(self): stream = list() From 1a43a0bce147ecb6bea6902c633ac1582374ab12 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sun, 21 Apr 2013 11:22:54 +0100 Subject: [PATCH 6/7] ENH: Rename splitAction to extractOptions in jailreader --- fail2ban/client/jailreader.py | 8 ++++---- fail2ban/tests/clientreadertestcase.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index 0599a85e..4a33fdc9 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -77,7 +77,7 @@ class JailReader(ConfigReader): if self.isEnabled(): # Read filter - filterName, filterOpt = JailReader.splitOption( + filterName, filterOpt = JailReader.extractOptions( self.__opts["filter"]) self.__filter = FilterReader( filterName, self.__name, filterOpt, basedir=self.getBaseDir()) @@ -93,7 +93,7 @@ class JailReader(ConfigReader): try: if not act: # skip empty actions continue - actName, actOpt = JailReader.splitOption(act) + actName, actOpt = JailReader.extractOptions(act) action = ActionReader( actName, self.__name, actOpt, basedir=self.getBaseDir()) ret = action.read() @@ -151,7 +151,7 @@ class JailReader(ConfigReader): return stream #@staticmethod - def splitOption(option): + def extractOptions(option): m = JailReader.optionCRE.match(option) d = dict() mgroups = m.groups() @@ -194,4 +194,4 @@ class JailReader(ConfigReader): except IndexError: logSys.error("Invalid argument %s in '%s'" % (p, option_opts)) return [option_name, d] - splitOption = staticmethod(splitOption) + extractOptions = staticmethod(extractOptions) diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 3e0b555d..931a15bc 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -115,7 +115,7 @@ class JailReaderTest(unittest.TestCase): def testSplitOption(self): action = "mail-whois[name=SSH]" expected = ['mail-whois', {'name': 'SSH'}] - result = JailReader.splitOption(action) + result = JailReader.extractOptions(action) self.assertEquals(expected, result) class FilterReaderTest(unittest.TestCase): From e57505e0740aa1d3f49ba8b9c9b52a0bb45d74bc Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sun, 21 Apr 2013 11:27:32 +0100 Subject: [PATCH 7/7] ENH: Renamed OptionConfigReader to DefinitionInitConfigReader --- fail2ban/client/actionreader.py | 4 ++-- fail2ban/client/configreader.py | 9 ++++++++- fail2ban/client/filterreader.py | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/fail2ban/client/actionreader.py b/fail2ban/client/actionreader.py index 70c5b3a7..ca4080d0 100644 --- a/fail2ban/client/actionreader.py +++ b/fail2ban/client/actionreader.py @@ -28,12 +28,12 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" import logging, os -from configreader import ConfigReader, OptionConfigReader +from configreader import ConfigReader, DefinitionInitConfigReader # Gets the instance of the logger. logSys = logging.getLogger(__name__) -class ActionReader(OptionConfigReader): +class ActionReader(DefinitionInitConfigReader): _configOpts = [ ["string", "actionstart", ""], diff --git a/fail2ban/client/configreader.py b/fail2ban/client/configreader.py index 4cb9cd69..45ea1361 100644 --- a/fail2ban/client/configreader.py +++ b/fail2ban/client/configreader.py @@ -131,7 +131,14 @@ class ConfigReader(SafeConfigParserWithIncludes): values[option[1]] = option[2] return values -class OptionConfigReader(ConfigReader): +class DefinitionInitConfigReader(ConfigReader): + """Config reader for files with options grouped in [Definition] and + [Init] sections. + + Is a base class for readers of filters and actions, where definitions + in jails might provide custom values for options defined in [Init] + section. + """ _configOpts = [] diff --git a/fail2ban/client/filterreader.py b/fail2ban/client/filterreader.py index 19a3f0f3..62424ddb 100644 --- a/fail2ban/client/filterreader.py +++ b/fail2ban/client/filterreader.py @@ -28,12 +28,12 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" import logging, os -from configreader import ConfigReader, OptionConfigReader +from configreader import ConfigReader, DefinitionInitConfigReader # Gets the instance of the logger. logSys = logging.getLogger(__name__) -class FilterReader(OptionConfigReader): +class FilterReader(DefinitionInitConfigReader): _configOpts = [ ["string", "ignoreregex", ""],