mirror of https://github.com/fail2ban/fail2ban
Merge pull request #265 from yarikoptic/master
Improve fail2ban-client errors logging/handling -- fail if no log file could be read, dump logs to stderrpull/258/merge
commit
b20159a715
|
@ -24,7 +24,10 @@ ver. 0.8.11 (2013/XX/XXX) - wanna-be-released
|
||||||
sample logs
|
sample logs
|
||||||
Yaroslav Halchenko
|
Yaroslav Halchenko
|
||||||
* fail2ban-regex -- refactored to provide more details (missing and
|
* fail2ban-regex -- refactored to provide more details (missing and
|
||||||
ignored lines, control over logging, etc) while maintaining look&feel.
|
ignored lines, control over logging, etc) while maintaining look&feel
|
||||||
|
* fail2ban-client -- log to standard error. Closes gh-264
|
||||||
|
* Fail to configure if not a single log file was found for an
|
||||||
|
enabled jail. Closes gh-63
|
||||||
|
|
||||||
ver. 0.8.10 (2013/06/12) - wanna-be-secure
|
ver. 0.8.10 (2013/06/12) - wanna-be-secure
|
||||||
-----------
|
-----------
|
||||||
|
|
|
@ -103,16 +103,30 @@ class JailReader(ConfigReader):
|
||||||
logSys.warn("No actions were defined for %s" % self.__name)
|
logSys.warn("No actions were defined for %s" % self.__name)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def convert(self):
|
def convert(self, allow_no_files=False):
|
||||||
|
"""Convert read before __opts to the commands stream
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
allow_missing : bool
|
||||||
|
Either to allow log files to be missing entirely. Primarily is
|
||||||
|
used for testing
|
||||||
|
"""
|
||||||
|
|
||||||
stream = []
|
stream = []
|
||||||
for opt in self.__opts:
|
for opt in self.__opts:
|
||||||
if opt == "logpath":
|
if opt == "logpath":
|
||||||
|
found_files = 0
|
||||||
for path in self.__opts[opt].split("\n"):
|
for path in self.__opts[opt].split("\n"):
|
||||||
pathList = glob.glob(path)
|
pathList = glob.glob(path)
|
||||||
if len(pathList) == 0:
|
if len(pathList) == 0:
|
||||||
logSys.error("No file found for " + path)
|
logSys.error("No file(s) found for glob %s" % path)
|
||||||
for p in pathList:
|
for p in pathList:
|
||||||
|
found_files += 1
|
||||||
stream.append(["set", self.__name, "addlogpath", p])
|
stream.append(["set", self.__name, "addlogpath", p])
|
||||||
|
if not (found_files or allow_no_files):
|
||||||
|
raise ValueError(
|
||||||
|
"Have not found any log file for %s jail" % self.__name)
|
||||||
elif opt == "backend":
|
elif opt == "backend":
|
||||||
backend = self.__opts[opt]
|
backend = self.__opts[opt]
|
||||||
elif opt == "maxretry":
|
elif opt == "maxretry":
|
||||||
|
|
|
@ -79,14 +79,23 @@ class JailsReader(ConfigReader):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def convert(self):
|
def convert(self, allow_no_files=False):
|
||||||
|
"""Convert read before __opts and jails to the commands stream
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
allow_missing : bool
|
||||||
|
Either to allow log files to be missing entirely. Primarily is
|
||||||
|
used for testing
|
||||||
|
"""
|
||||||
|
|
||||||
stream = list()
|
stream = list()
|
||||||
for opt in self.__opts:
|
for opt in self.__opts:
|
||||||
if opt == "":
|
if opt == "":
|
||||||
stream.append([])
|
stream.append([])
|
||||||
# Convert jails
|
# Convert jails
|
||||||
for jail in self.__jails:
|
for jail in self.__jails:
|
||||||
stream.extend(jail.convert())
|
stream.extend(jail.convert(allow_no_files=allow_no_files))
|
||||||
# Start jails
|
# Start jails
|
||||||
for jail in self.__jails:
|
for jail in self.__jails:
|
||||||
stream.append(["start", jail.getName()])
|
stream.append(["start", jail.getName()])
|
||||||
|
|
|
@ -229,7 +229,7 @@ class Fail2banClient:
|
||||||
elif len(cmd) == 2 and cmd[0] == "reload":
|
elif len(cmd) == 2 and cmd[0] == "reload":
|
||||||
if self.__ping():
|
if self.__ping():
|
||||||
jail = cmd[1]
|
jail = cmd[1]
|
||||||
ret = self.__readJailConfig(jail)
|
ret = self.__readConfig(jail)
|
||||||
# Do not continue if configuration is not 100% valid
|
# Do not continue if configuration is not 100% valid
|
||||||
if not ret:
|
if not ret:
|
||||||
return False
|
return False
|
||||||
|
@ -336,13 +336,13 @@ class Fail2banClient:
|
||||||
logSys.setLevel(logging.INFO)
|
logSys.setLevel(logging.INFO)
|
||||||
else:
|
else:
|
||||||
logSys.setLevel(logging.DEBUG)
|
logSys.setLevel(logging.DEBUG)
|
||||||
# Add the default logging handler
|
# Add the default logging handler to dump to stderr
|
||||||
stdout = logging.StreamHandler(sys.stdout)
|
logout = logging.StreamHandler(sys.stderr)
|
||||||
# set a format which is simpler for console use
|
# set a format which is simpler for console use
|
||||||
formatter = logging.Formatter('%(levelname)-6s %(message)s')
|
formatter = logging.Formatter('%(levelname)-6s %(message)s')
|
||||||
# tell the handler to use this format
|
# tell the handler to use this format
|
||||||
stdout.setFormatter(formatter)
|
logout.setFormatter(formatter)
|
||||||
logSys.addHandler(stdout)
|
logSys.addHandler(logout)
|
||||||
|
|
||||||
# Set the configuration path
|
# Set the configuration path
|
||||||
self.__configurator.setBaseDir(self.__conf["conf"])
|
self.__configurator.setBaseDir(self.__conf["conf"])
|
||||||
|
@ -394,19 +394,18 @@ class Fail2banClient:
|
||||||
return False
|
return False
|
||||||
return self.__processCommand(args)
|
return self.__processCommand(args)
|
||||||
|
|
||||||
def __readConfig(self):
|
def __readConfig(self, jail=None):
|
||||||
# Read the configuration
|
# Read the configuration
|
||||||
self.__configurator.readAll()
|
# TODO: get away from stew of return codes and exception
|
||||||
ret = self.__configurator.getOptions()
|
# handling -- handle via exceptions
|
||||||
self.__configurator.convertToProtocol()
|
try:
|
||||||
self.__stream = self.__configurator.getConfigStream()
|
self.__configurator.readAll()
|
||||||
return ret
|
ret = self.__configurator.getOptions(jail)
|
||||||
|
self.__configurator.convertToProtocol()
|
||||||
def __readJailConfig(self, jail):
|
self.__stream = self.__configurator.getConfigStream()
|
||||||
self.__configurator.readAll()
|
except Exception, e:
|
||||||
ret = self.__configurator.getOptions(jail)
|
logSys.error("Failed during configuration: %s" % e)
|
||||||
self.__configurator.convertToProtocol()
|
ret = False
|
||||||
self.__stream = self.__configurator.getConfigStream()
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
#@staticmethod
|
#@staticmethod
|
||||||
|
|
|
@ -132,7 +132,7 @@ class JailsReaderTest(unittest.TestCase):
|
||||||
jails = JailsReader(basedir='config', force_enable=True) # we are running tests from root project dir atm
|
jails = JailsReader(basedir='config', force_enable=True) # we are running tests from root project dir atm
|
||||||
self.assertTrue(jails.read()) # opens fine
|
self.assertTrue(jails.read()) # opens fine
|
||||||
self.assertTrue(jails.getOptions()) # reads fine
|
self.assertTrue(jails.getOptions()) # reads fine
|
||||||
comm_commands = jails.convert()
|
comm_commands = jails.convert(allow_no_files=True)
|
||||||
|
|
||||||
# by default we have lots of jails ;)
|
# by default we have lots of jails ;)
|
||||||
self.assertTrue(len(comm_commands))
|
self.assertTrue(len(comm_commands))
|
||||||
|
|
Loading…
Reference in New Issue