really skips invalid jails (because of theirs wrong configuration) - server starts nevertheless, as long as one jail was successful configured;

message about wrong jail configuration logged in client log (stdout, systemd journal etc.) and in server log as error
pull/1619/head
sebres 2016-11-22 13:19:09 +01:00
parent 261f875748
commit 77dc5a334c
3 changed files with 86 additions and 64 deletions

View File

@ -118,70 +118,78 @@ class JailReader(ConfigReader):
defsec = self._cfg.get_defaults() defsec = self._cfg.get_defaults()
defsec["fail2ban_version"] = version defsec["fail2ban_version"] = version
# Read first options only needed for merge defaults ('known/...' from filter): try:
self.__opts = ConfigReader.getOptions(self, self.__name, opts1st, shouldExist=True)
if not self.__opts:
return False
if self.isEnabled():
# Read filter
if self.__opts["filter"]:
filterName, filterOpt = JailReader.extractOptions(
self.__opts["filter"])
self.__filter = FilterReader(
filterName, self.__name, filterOpt, share_config=self.share_config, basedir=self.getBaseDir())
ret = self.__filter.read()
# merge options from filter as 'known/...':
self.__filter.getOptions(self.__opts)
ConfigReader.merge_section(self, self.__name, self.__filter.getCombined(), 'known/')
if not ret:
logSys.error("Unable to read the filter")
return False
else:
self.__filter = None
logSys.warning("No filter set for jail %s" % self.__name)
# Read second all options (so variables like %(known/param) can be interpolated): # Read first options only needed for merge defaults ('known/...' from filter):
self.__opts = ConfigReader.getOptions(self, self.__name, opts) self.__opts = ConfigReader.getOptions(self, self.__name, opts1st, shouldExist=True)
if not self.__opts: if not self.__opts:
return False raise ValueError("Init jail options failed")
# cumulate filter options again (ignore given in jail): if self.isEnabled():
if self.__filter: # Read filter
self.__filter.getOptions(self.__opts) if self.__opts["filter"]:
filterName, filterOpt = JailReader.extractOptions(
# Read action self.__opts["filter"])
for act in self.__opts["action"].split('\n'): self.__filter = FilterReader(
try: filterName, self.__name, filterOpt, share_config=self.share_config, basedir=self.getBaseDir())
if not act: # skip empty actions ret = self.__filter.read()
continue # merge options from filter as 'known/...':
actName, actOpt = JailReader.extractOptions(act) self.__filter.getOptions(self.__opts)
if actName.endswith(".py"): ConfigReader.merge_section(self, self.__name, self.__filter.getCombined(), 'known/')
self.__actions.append([ if not ret:
"set", raise ValueError("Unable to read the filter %r" % filterName)
self.__name, else:
"addaction", self.__filter = None
actOpt.pop("actname", os.path.splitext(actName)[0]), logSys.warning("No filter set for jail %s" % self.__name)
os.path.join(
self.getBaseDir(), "action.d", actName), # Read second all options (so variables like %(known/param) can be interpolated):
json.dumps(actOpt), self.__opts = ConfigReader.getOptions(self, self.__name, opts)
]) if not self.__opts:
else: raise ValueError("Read jail options failed")
action = ActionReader(
actName, self.__name, actOpt, # cumulate filter options again (ignore given in jail):
share_config=self.share_config, basedir=self.getBaseDir()) if self.__filter:
ret = action.read() self.__filter.getOptions(self.__opts)
if ret:
action.getOptions(self.__opts) # Read action
self.__actions.append(action) for act in self.__opts["action"].split('\n'):
try:
if not act: # skip empty actions
continue
actName, actOpt = JailReader.extractOptions(act)
if actName.endswith(".py"):
self.__actions.append([
"set",
self.__name,
"addaction",
actOpt.pop("actname", os.path.splitext(actName)[0]),
os.path.join(
self.getBaseDir(), "action.d", actName),
json.dumps(actOpt),
])
else: else:
raise AttributeError("Unable to read action") action = ActionReader(
except Exception as e: actName, self.__name, actOpt,
logSys.error("Error in action definition " + act) share_config=self.share_config, basedir=self.getBaseDir())
logSys.debug("Caught exception: %s" % (e,)) ret = action.read()
return False if ret:
if not len(self.__actions): action.getOptions(self.__opts)
logSys.warning("No actions were defined for %s" % self.__name) self.__actions.append(action)
else:
raise AttributeError("Unable to read action")
except Exception as e:
logSys.debug("Caught exception: %s" % (e,))
raise ValueError("Error in action definition %r" % e)
if not len(self.__actions):
logSys.warning("No actions were defined for %s" % self.__name)
except ValueError as e:
e = str(e)
logSys.error(e)
if not self.__opts:
self.__opts = dict()
self.__opts['config-error'] = e
return False
return True return True
def convert(self, allow_no_files=False): def convert(self, allow_no_files=False):
@ -195,6 +203,10 @@ class JailReader(ConfigReader):
""" """
stream = [] stream = []
e = self.__opts.get('config-error')
if e:
stream.extend([['config-error', "Jail '%s' skipped, because of wrong configuration: %s" % (self.__name, e)]])
return stream
for opt, value in self.__opts.iteritems(): for opt, value in self.__opts.iteritems():
if opt == "logpath" and \ if opt == "logpath" and \
not self.__opts.get('backend', None).startswith("systemd"): not self.__opts.get('backend', None).startswith("systemd"):

View File

@ -66,7 +66,7 @@ class JailsReader(ConfigReader):
sections = [ section ] sections = [ section ]
# Get the options of all jails. # Get the options of all jails.
parse_status = True parse_status = None
for sec in sections: for sec in sections:
if sec == 'INCLUDES': if sec == 'INCLUDES':
continue continue
@ -77,11 +77,17 @@ class JailsReader(ConfigReader):
ret = jail.getOptions() ret = jail.getOptions()
if ret: if ret:
if jail.isEnabled(): if jail.isEnabled():
# at least one jail was successful:
parse_status = True
# We only add enabled jails # We only add enabled jails
self.__jails.append(jail) self.__jails.append(jail)
else: else:
logSys.error("Errors in jail %r. Skipping..." % sec) logSys.error("Errors in jail %r. Skipping..." % sec)
parse_status = False self.__jails.append(jail)
if parse_status is None:
parse_status = False
if parse_status is None:
parse_status = True
return parse_status return parse_status
def convert(self, allow_no_files=False): def convert(self, allow_no_files=False):
@ -103,7 +109,8 @@ class JailsReader(ConfigReader):
stream.extend(jail.convert(allow_no_files=allow_no_files)) 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()]) if not jail.options.get('config-error'):
stream.append(["start", jail.getName()])
return stream return stream

View File

@ -131,6 +131,9 @@ class Transmitter:
return self.status(command[1:]) return self.status(command[1:])
elif command[0] == "version": elif command[0] == "version":
return version.version return version.version
elif command[0] == "config-error":
logSys.error(command[1])
return None
raise Exception("Invalid command") raise Exception("Invalid command")
def __commandSet(self, command, multiple=False): def __commandSet(self, command, multiple=False):