diff --git a/ChangeLog b/ChangeLog index c8344d81..f32047d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,6 +28,8 @@ ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition several log messages will be tagged with as originating from a process named "sshd-session" rather than "sshd" (gh-3782) ### New Features and Enhancements +* new jail option `skip_if_nologs` to ignore jail if no `logpath` matches found, fail2ban continue to start with warnings/errors, + thus other jails become running (gh-2756) * `action.d/*-ipset.conf`: - parameter `ipsettype` to set type of ipset, e. g. hash:ip, hash:net, etc (gh-3760) * `action.d/firewallcmd-rich-*.conf` - fixed incorrect quoting, disabling port variable expansion diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index e7242bfd..d3fa703f 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -116,11 +116,15 @@ class JailReader(ConfigReader): "logtimezone": ["string", None], "logencoding": ["string", None], "logpath": ["string", None], + "skip_if_nologs": ["bool", False], "action": ["string", ""] } _configOpts.update(FilterReader._configOpts) - _ignoreOpts = set(['action', 'filter', 'enabled', 'backend'] + list(FilterReader._configOpts.keys())) + _ignoreOpts = set( + ['action', 'filter', 'enabled', 'backend', 'skip_if_nologs'] + + list(FilterReader._configOpts.keys()) + ) def getOptions(self, addOpts=None): @@ -274,9 +278,14 @@ class JailReader(ConfigReader): ["set", self.__name, "addlogpath", p, tail]) if not found_files: msg = "Have not found any log file for %s jail" % self.__name - if not allow_no_files: + skip_if_nologs = self.__opts.get('skip_if_nologs', False) + if not allow_no_files and not skip_if_nologs: raise ValueError(msg) logSys.warning(msg) + if skip_if_nologs: + self.__opts['config-error'] = msg + stream = [['config-error', "Jail '%s' skipped, because of missing log files." % (self.__name,)]] + return stream elif opt == "ignoreip": stream.append(["set", self.__name, "addignoreip"] + splitwords(value)) elif opt not in JailReader._ignoreOpts: diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 0388fd3d..02627978 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -733,6 +733,7 @@ class JailsReaderTest(LogCaptureTestCase): ['start', 'test-known-interp'], ['add', 'missinglogfiles', 'auto'], ['set', 'missinglogfiles', 'addfailregex', ''], + ['config-error', "Jail 'missinglogfiles_skip' skipped, because of missing log files."], ['add', 'brokenaction', 'auto'], ['set', 'brokenaction', 'addfailregex', ''], ['set', 'brokenaction', 'addaction', 'brokenaction'], @@ -1022,6 +1023,11 @@ filter = testfilter1 self.assertRaisesRegex(ValueError, r"Have not found any log file for .* jail", self._testLogPath, backend='polling') + def testLogPathSkipJailIfNoLogs(self): + s = self._testLogPath(backend='polling', skip_if_nologs=True) + self.assertLogged('Have not found any log file for') + self.assertEqual(s, [['config-error', "Jail 'testjail1' skipped, because of missing log files."]]) + def testLogPathSystemdBackend(self): try: # pragma: systemd no cover from ..server.filtersystemd import FilterSystemd @@ -1031,7 +1037,7 @@ filter = testfilter1 self._testLogPath(backend='systemd[journalflags=2]') @with_tmpdir - def _testLogPath(self, basedir, backend): + def _testLogPath(self, basedir, backend, skip_if_nologs=False): jailfd = open(os.path.join(basedir, "jail.conf"), 'w') jailfd.write(""" [testjail1] @@ -1043,8 +1049,10 @@ action = filter = failregex = test """ % (backend, basedir)) + if skip_if_nologs: + jailfd.write("skip_if_nologs = true\n") jailfd.close() jails = JailsReader(basedir=basedir) self.assertTrue(jails.read()) self.assertTrue(jails.getOptions()) - jails.convert() + return jails.convert() diff --git a/fail2ban/tests/config/jail.conf b/fail2ban/tests/config/jail.conf index b1a1707b..2a2a111b 100644 --- a/fail2ban/tests/config/jail.conf +++ b/fail2ban/tests/config/jail.conf @@ -23,6 +23,11 @@ failregex = %(known/failregex)s enabled = true logpath = /weapons/of/mass/destruction +[missinglogfiles_skip] +enabled = true +skip_if_nologs = true +logpath = /weapons/of/mass/destruction + [brokenactiondef] enabled = true action = joho[foo