mirror of https://github.com/fail2ban/fail2ban
do type-convert only in getCombined (otherwise int/bool conversion prevents substitution or section-related interpolation of tags)
parent
1707560df8
commit
7b05c1ce7a
|
@ -38,17 +38,17 @@ class ActionReader(DefinitionInitConfigReader):
|
|||
|
||||
_configOpts = {
|
||||
"actionstart": ["string", None],
|
||||
"actionstart_on_demand": ["string", None],
|
||||
"actionstart_on_demand": ["bool", None],
|
||||
"actionstop": ["string", None],
|
||||
"actionflush": ["string", None],
|
||||
"actionreload": ["string", None],
|
||||
"actioncheck": ["string", None],
|
||||
"actionrepair": ["string", None],
|
||||
"actionrepair_on_unban": ["string", None],
|
||||
"actionrepair_on_unban": ["bool", None],
|
||||
"actionban": ["string", None],
|
||||
"actionreban": ["string", None],
|
||||
"actionunban": ["string", None],
|
||||
"norestored": ["string", None],
|
||||
"norestored": ["bool", None],
|
||||
}
|
||||
|
||||
def __init__(self, file_, jailName, initOpts, **kwargs):
|
||||
|
@ -83,11 +83,6 @@ class ActionReader(DefinitionInitConfigReader):
|
|||
def convert(self):
|
||||
opts = self.getCombined(
|
||||
ignore=CommandAction._escapedTags | set(('timeout', 'bantime')))
|
||||
# type-convert only after combined (otherwise boolean converting prevents substitution):
|
||||
for o in ('norestored', 'actionstart_on_demand', 'actionrepair_on_unban'):
|
||||
if opts.get(o):
|
||||
opts[o] = self._convert_to_boolean(opts[o])
|
||||
|
||||
# stream-convert:
|
||||
head = ["set", self._jailName]
|
||||
stream = list()
|
||||
|
|
|
@ -228,7 +228,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
|||
# Or it is a dict:
|
||||
# {name: [type, default], ...}
|
||||
|
||||
def getOptions(self, sec, options, pOptions=None, shouldExist=False):
|
||||
def getOptions(self, sec, options, pOptions=None, shouldExist=False, convert=True):
|
||||
values = dict()
|
||||
if pOptions is None:
|
||||
pOptions = {}
|
||||
|
@ -244,12 +244,15 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
|||
if optname in pOptions:
|
||||
continue
|
||||
try:
|
||||
if opttype == "bool":
|
||||
v = self.getboolean(sec, optname)
|
||||
if v is None: continue
|
||||
elif opttype == "int":
|
||||
v = self.getint(sec, optname)
|
||||
if v is None: continue
|
||||
if convert:
|
||||
if opttype == "bool":
|
||||
v = self.getboolean(sec, optname)
|
||||
if v is None: continue
|
||||
elif opttype == "int":
|
||||
v = self.getint(sec, optname)
|
||||
if v is None: continue
|
||||
else:
|
||||
v = self.get(sec, optname, vars=pOptions)
|
||||
else:
|
||||
v = self.get(sec, optname, vars=pOptions)
|
||||
values[optname] = v
|
||||
|
@ -267,7 +270,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
|||
values[optname] = optvalue
|
||||
# elif logSys.getEffectiveLevel() <= logLevel:
|
||||
# logSys.log(logLevel, "Non essential option '%s' not defined in '%s'.", optname, sec)
|
||||
except ValueError:
|
||||
except ValueError:
|
||||
logSys.warning("Wrong value for '" + optname + "' in '" + sec +
|
||||
"'. Using default one: '" + repr(optvalue) + "'")
|
||||
values[optname] = optvalue
|
||||
|
@ -324,8 +327,9 @@ class DefinitionInitConfigReader(ConfigReader):
|
|||
pOpts = dict()
|
||||
if self._initOpts:
|
||||
pOpts = _merge_dicts(pOpts, self._initOpts)
|
||||
# type-convert only in combined (otherwise int/bool converting prevents substitution):
|
||||
self._opts = ConfigReader.getOptions(
|
||||
self, "Definition", self._configOpts, pOpts)
|
||||
self, "Definition", self._configOpts, pOpts, convert=False)
|
||||
self._pOpts = pOpts
|
||||
if self.has_section("Init"):
|
||||
# get only own options (without options from default):
|
||||
|
@ -346,10 +350,34 @@ class DefinitionInitConfigReader(ConfigReader):
|
|||
if opt == '__name__' or opt in self._opts: continue
|
||||
self._opts[opt] = self.get("Definition", opt)
|
||||
|
||||
def convertOptions(self, opts, pOptions={}):
|
||||
options = self._configOpts
|
||||
for optname in options:
|
||||
if isinstance(options, (list,tuple)):
|
||||
if len(optname) > 2:
|
||||
opttype, optname, optvalue = optname
|
||||
else:
|
||||
(opttype, optname), optvalue = optname, None
|
||||
else:
|
||||
opttype, optvalue = options[optname]
|
||||
if optname in pOptions:
|
||||
continue
|
||||
try:
|
||||
if opttype == "bool":
|
||||
v = opts.get(optname)
|
||||
if v is None or isinstance(v, bool): continue
|
||||
v = _as_bool(v)
|
||||
opts[optname] = v
|
||||
elif opttype == "int":
|
||||
v = opts.get(optname)
|
||||
if v is None or isinstance(v, (int, long)): continue
|
||||
v = int(v)
|
||||
opts[optname] = v
|
||||
except ValueError:
|
||||
logSys.warning("Wrong %s value %r for %r. Using default one: %r",
|
||||
opttype, v, optname, optvalue)
|
||||
opts[optname] = optvalue
|
||||
|
||||
def _convert_to_boolean(self, value):
|
||||
return _as_bool(value)
|
||||
|
||||
def getCombOption(self, optname):
|
||||
"""Get combined definition option (as string) using pre-set and init
|
||||
options as preselection (values with higher precedence as specified in section).
|
||||
|
@ -384,6 +412,8 @@ class DefinitionInitConfigReader(ConfigReader):
|
|||
ignore=ignore, addrepl=self.getCombOption)
|
||||
if not opts:
|
||||
raise ValueError('recursive tag definitions unable to be resolved')
|
||||
# convert options after all interpolations:
|
||||
self.convertOptions(opts)
|
||||
return opts
|
||||
|
||||
def convert(self):
|
||||
|
|
|
@ -490,7 +490,9 @@ class FilterReaderTest(unittest.TestCase):
|
|||
self.__share_cfg = {}
|
||||
|
||||
def testConvert(self):
|
||||
output = [['multi-set', 'testcase01', 'addfailregex', [
|
||||
output = [
|
||||
['set', 'testcase01', 'maxlines', 1],
|
||||
['multi-set', 'testcase01', 'addfailregex', [
|
||||
"^\\s*(?:\\S+ )?(?:kernel: \\[\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )"
|
||||
"?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|"
|
||||
"[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:)?\\s*(?:"
|
||||
|
@ -512,7 +514,6 @@ class FilterReaderTest(unittest.TestCase):
|
|||
['set', 'testcase01', 'addjournalmatch',
|
||||
"FIELD= with spaces ", "+", "AFIELD= with + char and spaces"],
|
||||
['set', 'testcase01', 'datepattern', "%Y %m %d %H:%M:%S"],
|
||||
['set', 'testcase01', 'maxlines', 1], # Last for overide test
|
||||
]
|
||||
filterReader = FilterReader("testcase01", "testcase01", {})
|
||||
filterReader.setBaseDir(TEST_FILES_DIR)
|
||||
|
@ -529,7 +530,7 @@ class FilterReaderTest(unittest.TestCase):
|
|||
filterReader.read()
|
||||
#filterReader.getOptions(["failregex", "ignoreregex"])
|
||||
filterReader.getOptions(None)
|
||||
output[-1][-1] = "5"
|
||||
output[0][-1] = 5; # maxlines = 5
|
||||
self.assertSortedEqual(filterReader.convert(), output)
|
||||
|
||||
def testFilterReaderSubstitionDefault(self):
|
||||
|
|
Loading…
Reference in New Issue