diff --git a/bin/fail2ban-client b/bin/fail2ban-client index 15fad1b0..8737c49d 100755 --- a/bin/fail2ban-client +++ b/bin/fail2ban-client @@ -325,7 +325,7 @@ class Fail2banClient: if verbose <= 0: logSys.setLevel(logging.ERROR) elif verbose == 1: - logSys.setLevel(logging.WARN) + logSys.setLevel(logging.WARNING) elif verbose == 2: logSys.setLevel(logging.INFO) else: diff --git a/bin/fail2ban-regex b/bin/fail2ban-regex index ccdb7eac..fffa8c39 100755 --- a/bin/fail2ban-regex +++ b/bin/fail2ban-regex @@ -131,7 +131,7 @@ Report bugs to https://github.com/fail2ban/fail2ban/issues "\"systemd-journal\" only"), Option('-l', "--log-level", type="choice", dest="log_level", - choices=('heavydebug', 'debug', 'info', 'warning', 'error', 'fatal'), + choices=('heavydebug', 'debug', 'info', 'notice', 'warning', 'error', 'critical'), default=None, help="Log level for the Fail2Ban logger to use"), Option("-v", "--verbose", action='store_true', @@ -476,9 +476,9 @@ if __name__ == "__main__": logSys.setLevel(getattr(logging, opts.log_level.upper())) else: # pragma: no cover # suppress the logging but it would leave unittests' progress dots - # ticking, unless like with '-l fatal' which would be silent + # ticking, unless like with '-l critical' which would be silent # unless error occurs - logSys.setLevel(getattr(logging, 'FATAL')) + logSys.setLevel(getattr(logging, 'CRITICAL')) # Add the default logging handler stdout = logging.StreamHandler(sys.stdout) diff --git a/bin/fail2ban-testcases b/bin/fail2ban-testcases index 578763d9..b3bddf1c 100755 --- a/bin/fail2ban-testcases +++ b/bin/fail2ban-testcases @@ -48,7 +48,7 @@ def get_opt_parser(): p.add_options([ Option('-l', "--log-level", type="choice", dest="log_level", - choices=('heavydebug', 'debug', 'info', 'warning', 'error', 'fatal'), + choices=('heavydebug', 'debug', 'info', 'notice', 'warning', 'error', 'critical'), default=None, help="Log level for the logger to use during running tests"), Option('-n', "--no-network", action="store_true", @@ -75,9 +75,10 @@ logSys = logging.getLogger("fail2ban") verbosity = {'heavydebug': 4, 'debug': 3, 'info': 2, + 'notice': 2, 'warning': 1, 'error': 1, - 'fatal': 0, + 'critical': 0, None: 1}[opts.log_level] if opts.log_level is not None: # pragma: no cover @@ -85,9 +86,9 @@ if opts.log_level is not None: # pragma: no cover logSys.setLevel(getattr(logging, opts.log_level.upper())) else: # pragma: no cover # suppress the logging but it would leave unittests' progress dots - # ticking, unless like with '-l fatal' which would be silent + # ticking, unless like with '-l critical' which would be silent # unless error occurs - logSys.setLevel(getattr(logging, 'FATAL')) + logSys.setLevel(getattr(logging, 'CRITICAL')) # Add the default logging handler stdout = logging.StreamHandler(sys.stdout) @@ -111,7 +112,7 @@ logSys.addHandler(stdout) # # Let know the version # -if not opts.log_level or opts.log_level != 'fatal': # pragma: no cover +if not opts.log_level or opts.log_level != 'critical': # pragma: no cover print("Fail2ban %s test suite. Python %s. Please wait..." \ % (version, str(sys.version).replace('\n', ''))) diff --git a/config/fail2ban.conf b/config/fail2ban.conf index fb79da59..85c74701 100644 --- a/config/fail2ban.conf +++ b/config/fail2ban.conf @@ -13,13 +13,15 @@ # Option: loglevel # Notes.: Set the log level output. -# 1 = ERROR -# 2 = WARN -# 3 = INFO -# 4 = DEBUG -# Values: [ NUM ] Default: 1 +# CRITICAL +# ERROR +# WARNING +# NOTICE +# INFO +# DEBUG +# Values: [ LEVEL ] Default: ERROR # -loglevel = 3 +loglevel = INFO # Option: logtarget # Notes.: Set the log target. This could be a file, SYSLOG, STDERR or STDOUT. diff --git a/fail2ban/__init__.py b/fail2ban/__init__.py index 3eae8ee3..f6c5f2de 100644 --- a/fail2ban/__init__.py +++ b/fail2ban/__init__.py @@ -24,7 +24,47 @@ __author__ = "Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import logging +import logging.handlers # Custom debug level logging.HEAVYDEBUG = 5 + +""" +Below derived from: + https://mail.python.org/pipermail/tutor/2007-August/056243.html +""" + +logging.NOTICE = logging.INFO + 5 +logging.addLevelName(logging.NOTICE, 'NOTICE') + +# define a new logger function for notice +# this is exactly like existing info, critical, debug...etc +def Logger_notice(self, msg, *args, **kwargs): + """ + Log 'msg % args' with severity 'NOTICE'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.notice("Houston, we have a %s", "major disaster", exc_info=1) + """ + if self.isEnabledFor(logging.NOTICE): + self._log(logging.NOTICE, msg, args, **kwargs) + +logging.Logger.notice = Logger_notice + +# define a new root level notice function +# this is exactly like existing info, critical, debug...etc +def root_notice(msg, *args, **kwargs): + """ + Log a message with severity 'NOTICE' on the root logger. + """ + if len(logging.root.handlers) == 0: + logging.basicConfig() + logging.root.notice(msg, *args, **kwargs) + +# make the notice root level function known +logging.notice = root_notice + +# add NOTICE to the priority map of all the levels +logging.handlers.SysLogHandler.priority_map['NOTICE'] = 'notice' diff --git a/fail2ban/client/configreader.py b/fail2ban/client/configreader.py index 1d1c3905..dacf3e57 100644 --- a/fail2ban/client/configreader.py +++ b/fail2ban/client/configreader.py @@ -54,7 +54,7 @@ class ConfigReader(SafeConfigParserWithIncludes): raise ValueError("Base configuration directory %s does not exist " % self._basedir) basename = os.path.join(self._basedir, filename) - logSys.debug("Reading configs for %s under %s " % (basename, self._basedir)) + logSys.info("Reading configs for %s under %s " % (basename, self._basedir)) config_files = [ basename + ".conf" ] # possible further customizations under a .conf.d directory diff --git a/fail2ban/client/fail2banreader.py b/fail2ban/client/fail2banreader.py index f432a47f..f17ff92b 100644 --- a/fail2ban/client/fail2banreader.py +++ b/fail2ban/client/fail2banreader.py @@ -45,7 +45,7 @@ class Fail2banReader(ConfigReader): return ConfigReader.getOptions(self, "Definition", opts) def getOptions(self): - opts = [["int", "loglevel", 1], + opts = [["int", "loglevel", "INFO" ], ["string", "logtarget", "STDERR"], ["string", "dbfile", "/var/lib/fail2ban/fail2ban.sqlite3"], ["int", "dbpurgeage", 86400]] diff --git a/fail2ban/protocol.py b/fail2ban/protocol.py index f3cc096e..8d053501 100644 --- a/fail2ban/protocol.py +++ b/fail2ban/protocol.py @@ -39,7 +39,7 @@ protocol = [ ["ping", "tests if the server is alive"], ["help", "return this output"], ['', "LOGGING", ""], -["set loglevel ", "sets logging level to . 0 is minimal, 4 is debug"], +["set loglevel ", "sets logging level to . Levels: CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG"], ["get loglevel", "gets the logging level"], ["set logtarget ", "sets logging target to . Can be STDOUT, STDERR, SYSLOG or a file"], ["get logtarget", "gets logging target"], diff --git a/fail2ban/server/action.py b/fail2ban/server/action.py index 94beb784..c0a59aa5 100644 --- a/fail2ban/server/action.py +++ b/fail2ban/server/action.py @@ -482,7 +482,7 @@ class CommandAction(ActionBase): self.stop() self.start() if not self.executeCmd(checkCmd, self.timeout): - self._logSys.fatal("Unable to restore environment") + self._logSys.critical("Unable to restore environment") return False # Replace tags diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index 52624f29..dc80b044 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -251,7 +251,7 @@ class Actions(JailThread, Mapping): self._jail.getDatabase().getBansMerged( ip=bTicket.getIP(), jail=self._jail).getAttempt()) if self.__banManager.addBanTicket(bTicket): - logSys.warning("[%s] Ban %s" % (self._jail.getName(), aInfo["ip"])) + logSys.notice("[%s] Ban %s" % (self._jail.getName(), aInfo["ip"])) for name, action in self._actions.iteritems(): try: action.ban(aInfo) @@ -261,7 +261,7 @@ class Actions(JailThread, Mapping): self._jail.getName(), name, e) return True else: - logSys.info("[%s] %s already banned" % (self._jail.getName(), + logSys.notice("[%s] %s already banned" % (self._jail.getName(), aInfo["ip"])) return False @@ -298,7 +298,7 @@ class Actions(JailThread, Mapping): aInfo["failures"] = ticket.getAttempt() aInfo["time"] = ticket.getTime() aInfo["matches"] = "".join(ticket.getMatches()) - logSys.warning("[%s] Unban %s" % (self._jail.getName(), aInfo["ip"])) + logSys.notice("[%s] Unban %s" % (self._jail.getName(), aInfo["ip"])) for name, action in self._actions.iteritems(): try: action.unban(aInfo) diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index 67d91538..d208174f 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -419,9 +419,9 @@ class Filter(JailThread): % (unixTime, MyTime.time(), self.getFindTime())) break if self.inIgnoreIPList(ip): - logSys.debug("Ignore %s" % ip) + logSys.notice("[%s] Ignore %s" % (self.jail.getName(), ip)) continue - logSys.debug("Found %s" % ip) + logSys.notice("[%s] Found %s" % (self.jail.getName(), ip)) ## print "D: Adding a ticket for %s" % ((ip, unixTime, [line]),) self.failManager.addFailure(FailTicket(ip, unixTime, lines)) @@ -500,7 +500,7 @@ class Filter(JailThread): else: continue if date is None: - logSys.debug( + logSys.warning( "Found a match for %r but no valid date/time " "found for %r. Please try setting a custom " "date pattern (see man page jail.conf(5)). " @@ -779,7 +779,7 @@ class FileContainer: ## sys.stdout.flush() # Compare hash and inode if self.__hash != myHash or self.__ino != stats.st_ino: - logSys.debug("Log rotation detected for %s" % self.__filename) + logSys.info("Log rotation detected for %s" % self.__filename) self.__hash = myHash self.__ino = stats.st_ino self.__pos = 0 diff --git a/fail2ban/server/server.py b/fail2ban/server/server.py index 3d2b54f7..cd1d85b8 100644 --- a/fail2ban/server/server.py +++ b/fail2ban/server/server.py @@ -51,7 +51,7 @@ class Server: self.__logLevel = None self.__logTarget = None # Set logging level - self.setLogLevel(3) + self.setLogLevel("INFO") self.setLogTarget("STDOUT") def __sigTERMhandler(self, signum, frame): @@ -323,28 +323,20 @@ class Server: ## # Set the logging level. # - # Incrementing the value gives more messages. - # 0 = FATAL - # 1 = ERROR - # 2 = WARNING - # 3 = INFO - # 4 = DEBUG + # CRITICAL + # ERROR + # WARNING + # NOTICE + # INFO + # DEBUG # @param value the level def setLogLevel(self, value): try: self.__loggingLock.acquire() - self.__logLevel = value - logLevel = logging.DEBUG - if value == 0: - logLevel = logging.FATAL - elif value == 1: - logLevel = logging.ERROR - elif value == 2: - logLevel = logging.WARNING - elif value == 3: - logLevel = logging.INFO - logging.getLogger(__name__).parent.parent.setLevel(logLevel) + logging.getLogger(__name__).parent.parent.setLevel( + getattr(logging, value.upper())) + self.__logLevel = value.upper() finally: self.__loggingLock.release() diff --git a/fail2ban/server/transmitter.py b/fail2ban/server/transmitter.py index 0a955883..722c007a 100644 --- a/fail2ban/server/transmitter.py +++ b/fail2ban/server/transmitter.py @@ -107,7 +107,7 @@ class Transmitter: name = command[0] # Logging if name == "loglevel": - value = int(command[1]) + value = command[1] self.__server.setLogLevel(value) return self.__server.getLogLevel() elif name == "logtarget": diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index a0ada34e..471a328b 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -558,7 +558,7 @@ class JailsReaderTest(LogCaptureTestCase): [['set', 'dbfile', '/var/lib/fail2ban/fail2ban.sqlite3'], ['set', 'dbpurgeage', 86400], - ['set', 'loglevel', 3], + ['set', 'loglevel', "INFO"], ['set', 'logtarget', '/var/log/fail2ban.log']]) # and if we force change configurator's fail2ban's baseDir diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index 0d1c52d1..4d82107e 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -686,7 +686,7 @@ class TransmitterLogging(TransmitterBase): def setUp(self): self.server = Server() self.server.setLogTarget("/dev/null") - self.server.setLogLevel(0) + self.server.setLogLevel("CRITICAL") super(TransmitterLogging, self).setUp() def testLogTarget(self): @@ -711,12 +711,13 @@ class TransmitterLogging(TransmitterBase): self.setGetTest("logtarget", "SYSLOG") def testLogLevel(self): - self.setGetTest("loglevel", "4", 4) - self.setGetTest("loglevel", "3", 3) - self.setGetTest("loglevel", "2", 2) - self.setGetTest("loglevel", "1", 1) - self.setGetTest("loglevel", "-1", -1) - self.setGetTest("loglevel", "0", 0) + self.setGetTest("loglevel", "DEBUG") + self.setGetTest("loglevel", "INFO") + self.setGetTest("loglevel", "NOTICE") + self.setGetTest("loglevel", "WARNING") + self.setGetTest("loglevel", "ERROR") + self.setGetTest("loglevel", "CRITICAL") + self.setGetTest("loglevel", "cRiTiCaL", "CRITICAL") self.setGetTestNOK("loglevel", "Bird") def testFlushLogs(self): @@ -724,7 +725,7 @@ class TransmitterLogging(TransmitterBase): try: f, fn = tempfile.mkstemp("fail2ban.log") os.close(f) - self.server.setLogLevel(2) + self.server.setLogLevel("WARNING") self.assertEqual(self.transm.proceed(["set", "logtarget", fn]), (0, fn)) l = logging.getLogger('fail2ban.server.server').parent.parent l.warning("Before file moved") diff --git a/files/bash-completion b/files/bash-completion index 7a42bd1e..c8b99055 100644 --- a/files/bash-completion +++ b/files/bash-completion @@ -71,7 +71,7 @@ _fail2ban () { ;; *) if [[ "${words[$cword-2]}" == "add" ]];then - COMPREPLY=( $( compgen -W "auto polling gamin pyinotify" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "auto polling gamin pyinotify systemd" -- "$cur" ) ) return 0 elif [[ "${words[$cword-2]}" == "set" || "${words[$cword-2]}" == "get" ]];then cmd="${words[cword-2]}" @@ -88,7 +88,7 @@ _fail2ban () { case $prev in loglevel) if [[ "$cmd" == "set" ]];then - COMPREPLY=( $( compgen -W "0 1 2 3 4" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "CRITICAL ERROR WARNING NOTICE INFO DEBUG" -- "$cur" ) ) fi return 0 ;; diff --git a/setup.py b/setup.py index 13b16faf..c3befe83 100755 --- a/setup.py +++ b/setup.py @@ -51,7 +51,7 @@ if setuptools and "test" in sys.argv: hdlr.setFormatter(fmt) logSys.addHandler(hdlr) if set(["-q", "--quiet"]) & set(sys.argv): - logSys.setLevel(logging.FATAL) + logSys.setLevel(logging.CRITICAL) warnings.simplefilter("ignore") sys.warnoptions.append("ignore") elif set(["-v", "--verbose"]) & set(sys.argv):