mirror of https://github.com/fail2ban/fail2ban
code review;
more stable config sharing, configurator always shares it config readers now;pull/824/head
parent
e0eb4f2358
commit
02a46d0901
|
@ -62,6 +62,7 @@ else: # pragma: no cover
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
# Gets the instance of the logger.
|
||||||
logSys = getLogger(__name__)
|
logSys = getLogger(__name__)
|
||||||
|
logLevel = 7
|
||||||
|
|
||||||
__all__ = ['SafeConfigParserWithIncludes']
|
__all__ = ['SafeConfigParserWithIncludes']
|
||||||
|
|
||||||
|
@ -126,8 +127,8 @@ after = 1.conf
|
||||||
cfg = SCPWI(share_config=self._cfg_share)
|
cfg = SCPWI(share_config=self._cfg_share)
|
||||||
i = cfg.read(filename, get_includes=False)
|
i = cfg.read(filename, get_includes=False)
|
||||||
self._cfg_share[hashv] = (cfg, i)
|
self._cfg_share[hashv] = (cfg, i)
|
||||||
else:
|
elif logSys.getEffectiveLevel() <= logLevel:
|
||||||
logSys.debug(" Shared file: %s", filename)
|
logSys.log(logLevel, " Shared file: %s", filename)
|
||||||
else:
|
else:
|
||||||
# don't have sharing:
|
# don't have sharing:
|
||||||
cfg = SCPWI()
|
cfg = SCPWI()
|
||||||
|
@ -207,10 +208,9 @@ after = 1.conf
|
||||||
if not fileNamesFull:
|
if not fileNamesFull:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if self._cfg_share is not None:
|
if logSys.getEffectiveLevel() <= logLevel:
|
||||||
logSys.debug(" Sharing files: %s", fileNamesFull)
|
logSys.log(logLevel, (" Sharing files: %s" if self._cfg_share is not None else \
|
||||||
else:
|
" Reading files: %s"), fileNamesFull)
|
||||||
logSys.debug(" Reading files: %s", fileNamesFull)
|
|
||||||
|
|
||||||
if len(fileNamesFull) > 1:
|
if len(fileNamesFull) > 1:
|
||||||
# read multiple configs:
|
# read multiple configs:
|
||||||
|
@ -237,10 +237,10 @@ after = 1.conf
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# read one config :
|
# read one config :
|
||||||
logSys.debug(" Reading file: %s", fileNamesFull[0])
|
if logSys.getEffectiveLevel() <= logLevel:
|
||||||
|
logSys.log(logLevel, " Reading file: %s", fileNamesFull[0])
|
||||||
# read file(s) :
|
# read file(s) :
|
||||||
if sys.version_info >= (3,2): # pragma: no cover
|
if sys.version_info >= (3,2): # pragma: no cover
|
||||||
return SafeConfigParser.read(self, fileNamesFull, encoding='utf-8')
|
return SafeConfigParser.read(self, fileNamesFull, encoding='utf-8')
|
||||||
else:
|
else:
|
||||||
return SafeConfigParser.read(self, fileNamesFull)
|
return SafeConfigParser.read(self, fileNamesFull)
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,11 @@ __license__ = "GPL"
|
||||||
import glob, os
|
import glob, os
|
||||||
from ConfigParser import NoOptionError, NoSectionError
|
from ConfigParser import NoOptionError, NoSectionError
|
||||||
|
|
||||||
from .configparserinc import SafeConfigParserWithIncludes
|
from .configparserinc import SafeConfigParserWithIncludes, logLevel
|
||||||
from ..helpers import getLogger
|
from ..helpers import getLogger
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
# Gets the instance of the logger.
|
||||||
logSys = getLogger(__name__)
|
logSys = getLogger(__name__)
|
||||||
_logLevel = 6
|
|
||||||
|
|
||||||
class ConfigReader():
|
class ConfigReader():
|
||||||
"""Generic config reader class.
|
"""Generic config reader class.
|
||||||
|
@ -72,6 +71,22 @@ class ConfigReader():
|
||||||
|
|
||||||
def read(self, name, once=True):
|
def read(self, name, once=True):
|
||||||
# shared ?
|
# shared ?
|
||||||
|
if not self._cfg:
|
||||||
|
self.touch(name)
|
||||||
|
# performance feature - read once if using shared config reader:
|
||||||
|
if once and self._cfg.read_cfg_files is not None:
|
||||||
|
return self._cfg.read_cfg_files
|
||||||
|
|
||||||
|
# read:
|
||||||
|
if self._cfg_share is not None:
|
||||||
|
logSys.info("Sharing configs for %s under %s ", name, self._cfg.getBaseDir())
|
||||||
|
ret = self._cfg.read(name)
|
||||||
|
|
||||||
|
# save already read and return:
|
||||||
|
self._cfg.read_cfg_files = ret
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def touch(self, name = ''):
|
||||||
if not self._cfg and self._cfg_share is not None:
|
if not self._cfg and self._cfg_share is not None:
|
||||||
self._cfg = self._cfg_share.get(name)
|
self._cfg = self._cfg_share.get(name)
|
||||||
if not self._cfg:
|
if not self._cfg:
|
||||||
|
@ -79,36 +94,33 @@ class ConfigReader():
|
||||||
if self._cfg_share_basedir is not None:
|
if self._cfg_share_basedir is not None:
|
||||||
self._cfg.setBaseDir(self._cfg_share_basedir)
|
self._cfg.setBaseDir(self._cfg_share_basedir)
|
||||||
self._cfg_share[name] = self._cfg
|
self._cfg_share[name] = self._cfg
|
||||||
# performance feature - read once if using shared config reader:
|
else:
|
||||||
rc = self._cfg.read_cfg_files
|
self._cfg = ConfigReaderUnshared(**self._cfg_share_kwargs)
|
||||||
if once and rc.get(name) is not None:
|
|
||||||
return rc.get(name)
|
|
||||||
|
|
||||||
# read:
|
|
||||||
if self._cfg_share is not None:
|
|
||||||
logSys.info("Sharing configs for %s under %s ", name, self._cfg.getBaseDir())
|
|
||||||
ret = self._cfg.read(name)
|
|
||||||
|
|
||||||
# save already read:
|
|
||||||
if once:
|
|
||||||
rc[name] = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def sections(self):
|
def sections(self):
|
||||||
return self._cfg.sections()
|
if self._cfg is not None:
|
||||||
|
return self._cfg.sections()
|
||||||
|
return []
|
||||||
|
|
||||||
def has_section(self, sec):
|
def has_section(self, sec):
|
||||||
return self._cfg.has_section(sec)
|
if self._cfg is not None:
|
||||||
|
return self._cfg.has_section(sec)
|
||||||
|
return False
|
||||||
|
|
||||||
def options(self, *args):
|
def options(self, *args):
|
||||||
return self._cfg.options(*args)
|
if self._cfg is not None:
|
||||||
|
return self._cfg.options(*args)
|
||||||
|
return {}
|
||||||
|
|
||||||
def get(self, sec, opt):
|
def get(self, sec, opt):
|
||||||
return self._cfg.get(sec, opt)
|
if self._cfg is not None:
|
||||||
|
return self._cfg.get(sec, opt)
|
||||||
|
return None
|
||||||
|
|
||||||
def getOptions(self, *args, **kwargs):
|
def getOptions(self, *args, **kwargs):
|
||||||
return self._cfg.getOptions(*args, **kwargs)
|
if self._cfg is not None:
|
||||||
|
return self._cfg.getOptions(*args, **kwargs)
|
||||||
|
return {}
|
||||||
|
|
||||||
class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
||||||
"""Unshared config reader (previously ConfigReader).
|
"""Unshared config reader (previously ConfigReader).
|
||||||
|
@ -121,7 +133,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
||||||
|
|
||||||
def __init__(self, basedir=None, *args, **kwargs):
|
def __init__(self, basedir=None, *args, **kwargs):
|
||||||
SafeConfigParserWithIncludes.__init__(self, *args, **kwargs)
|
SafeConfigParserWithIncludes.__init__(self, *args, **kwargs)
|
||||||
self.read_cfg_files = dict()
|
self.read_cfg_files = None
|
||||||
self.setBaseDir(basedir)
|
self.setBaseDir(basedir)
|
||||||
|
|
||||||
def setBaseDir(self, basedir):
|
def setBaseDir(self, basedir):
|
||||||
|
@ -137,7 +149,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
||||||
raise ValueError("Base configuration directory %s does not exist "
|
raise ValueError("Base configuration directory %s does not exist "
|
||||||
% self._basedir)
|
% self._basedir)
|
||||||
basename = os.path.join(self._basedir, filename)
|
basename = os.path.join(self._basedir, filename)
|
||||||
logSys.info("Reading configs for %s under %s " , filename, self._basedir)
|
logSys.debug("Reading configs for %s under %s " , filename, self._basedir)
|
||||||
config_files = [ basename + ".conf" ]
|
config_files = [ basename + ".conf" ]
|
||||||
|
|
||||||
# possible further customizations under a .conf.d directory
|
# possible further customizations under a .conf.d directory
|
||||||
|
@ -203,8 +215,8 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
||||||
logSys.warning("'%s' not defined in '%s'. Using default one: %r"
|
logSys.warning("'%s' not defined in '%s'. Using default one: %r"
|
||||||
% (option[1], sec, option[2]))
|
% (option[1], sec, option[2]))
|
||||||
values[option[1]] = option[2]
|
values[option[1]] = option[2]
|
||||||
elif logSys.getEffectiveLevel() <= _logLevel:
|
elif logSys.getEffectiveLevel() <= logLevel:
|
||||||
logSys.log(_logLevel, "Non essential option '%s' not defined in '%s'.", option[1], sec)
|
logSys.log(logLevel, "Non essential option '%s' not defined in '%s'.", option[1], sec)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logSys.warning("Wrong value for '" + option[1] + "' in '" + sec +
|
logSys.warning("Wrong value for '" + option[1] + "' in '" + sec +
|
||||||
"'. Using default one: '" + `option[2]` + "'")
|
"'. Using default one: '" + `option[2]` + "'")
|
||||||
|
|
|
@ -36,6 +36,9 @@ class Configurator:
|
||||||
def __init__(self, force_enable=False, share_config=None):
|
def __init__(self, force_enable=False, share_config=None):
|
||||||
self.__settings = dict()
|
self.__settings = dict()
|
||||||
self.__streams = dict()
|
self.__streams = dict()
|
||||||
|
# always share all config readers:
|
||||||
|
if share_config is None:
|
||||||
|
share_config = dict()
|
||||||
self.__fail2ban = Fail2banReader(share_config=share_config)
|
self.__fail2ban = Fail2banReader(share_config=share_config)
|
||||||
self.__jails = JailsReader(force_enable=force_enable, share_config=share_config)
|
self.__jails = JailsReader(force_enable=force_enable, share_config=share_config)
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ logSys = getLogger(__name__)
|
||||||
class Fail2banReader(ConfigReader):
|
class Fail2banReader(ConfigReader):
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.__opts = None
|
|
||||||
ConfigReader.__init__(self, **kwargs)
|
ConfigReader.__init__(self, **kwargs)
|
||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
|
|
|
@ -42,7 +42,6 @@ class JailReader(ConfigReader):
|
||||||
r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,]*))(?:,|$)')
|
r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,]*))(?:,|$)')
|
||||||
|
|
||||||
def __init__(self, name, force_enable=False, **kwargs):
|
def __init__(self, name, force_enable=False, **kwargs):
|
||||||
# use shared config if possible:
|
|
||||||
ConfigReader.__init__(self, **kwargs)
|
ConfigReader.__init__(self, **kwargs)
|
||||||
self.__name = name
|
self.__name = name
|
||||||
self.__filter = None
|
self.__filter = None
|
||||||
|
|
|
@ -41,7 +41,6 @@ class JailsReader(ConfigReader):
|
||||||
Passed to JailReader to force enable the jails.
|
Passed to JailReader to force enable the jails.
|
||||||
It is for internal use
|
It is for internal use
|
||||||
"""
|
"""
|
||||||
# use shared config if possible:
|
|
||||||
ConfigReader.__init__(self, **kwargs)
|
ConfigReader.__init__(self, **kwargs)
|
||||||
self.__jails = list()
|
self.__jails = list()
|
||||||
self.__force_enable = force_enable
|
self.__force_enable = force_enable
|
||||||
|
|
|
@ -21,9 +21,9 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
import os, glob, shutil, tempfile, unittest, re
|
import os, glob, shutil, tempfile, unittest, re, logging
|
||||||
|
|
||||||
from ..client.configreader import ConfigReaderUnshared
|
from ..client.configreader import ConfigReaderUnshared
|
||||||
|
from ..client import configparserinc
|
||||||
from ..client.jailreader import JailReader
|
from ..client.jailreader import JailReader
|
||||||
from ..client.filterreader import FilterReader
|
from ..client.filterreader import FilterReader
|
||||||
from ..client.jailsreader import JailsReader
|
from ..client.jailsreader import JailsReader
|
||||||
|
@ -355,6 +355,8 @@ class JailsReaderTestCache(LogCaptureTestCase):
|
||||||
return cnt
|
return cnt
|
||||||
|
|
||||||
def testTestJailConfCache(self):
|
def testTestJailConfCache(self):
|
||||||
|
saved_ll = configparserinc.logLevel
|
||||||
|
configparserinc.logLevel = logging.DEBUG
|
||||||
basedir = tempfile.mkdtemp("fail2ban_conf")
|
basedir = tempfile.mkdtemp("fail2ban_conf")
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(basedir)
|
shutil.rmtree(basedir)
|
||||||
|
@ -388,6 +390,7 @@ class JailsReaderTestCache(LogCaptureTestCase):
|
||||||
self.assertTrue(cnt == 1, "Unexpected count by reading of action files, cnt = %s" % cnt)
|
self.assertTrue(cnt == 1, "Unexpected count by reading of action files, cnt = %s" % cnt)
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(basedir)
|
shutil.rmtree(basedir)
|
||||||
|
configparserinc.logLevel = saved_ll
|
||||||
|
|
||||||
|
|
||||||
class JailsReaderTest(LogCaptureTestCase):
|
class JailsReaderTest(LogCaptureTestCase):
|
||||||
|
|
Loading…
Reference in New Issue