From 486214585e131f8c442e4f3a710f066cae7ea1e8 Mon Sep 17 00:00:00 2001 From: Lee Clemens Date: Mon, 26 Jan 2015 19:38:06 -0500 Subject: [PATCH] Update extended status to accept additional argument, flavor Default to as-in behavior, or flavor=="basic" --- ChangeLog | 7 ++--- fail2ban/server/actions.py | 27 +++++++++---------- fail2ban/server/filter.py | 8 +++--- fail2ban/server/filtersystemd.py | 5 ++-- fail2ban/server/jail.py | 16 +++--------- fail2ban/server/jailthread.py | 12 +++------ fail2ban/server/server.py | 7 ++--- fail2ban/server/transmitter.py | 6 ++--- fail2ban/tests/servertestcase.py | 45 +++++++++++++++++++++++++++----- 9 files changed, 71 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3013dac8..90be2bbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -41,9 +41,10 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released - Monit config for fail2ban in /files/monit - New actions: - action.d/firewallcmd-multiport and action.d/firewallcmd-allports Thanks Donald Yandt - - New status commands: - - fail2ban-client status extended - - prints Cymru data (ASN, Country RIR) per banned IP + - New status argument, flavor: + - fail2ban-client status [flavor] + - empty or "basic" works as-is + - "cymru" additionally prints (ASN, Country RIR) per banned IP - Requires dnspython or dnspython3 - Enhancements: diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index f4d5c18b..3a1c9579 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -370,22 +370,21 @@ class Actions(JailThread, Mapping): self._jail.name, name, aInfo, e, exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) - @property - def status(self): + def status(self, flavor="basic"): """Status of current and total ban counts and current banned IP list. """ - ret = [("Currently banned", self.__banManager.size()), + # TODO: Allow this list to be printed as 'status' output + supported_flavors = ["basic", "cymru"] + if flavor is None or flavor not in supported_flavors: + logSys.warning("Unsupported extended jail status flavor %r. Supported: %s" % (flavor, supported_flavors)) + # Always print this information (basic) + ret = [("Currently banned", self.__banManager.size()), ("Total banned", self.__banManager.getBanTotal()), ("Banned IP list", self.__banManager.getBanList())] - return ret - - @property - def statusExtended(self): - """Jail status plus banned IPs' ASN, Country and RIR - """ - cymru_info = self.__banManager.getBanListExtendedCymruInfo() - ret = self.status +\ - [("Banned ASN list", self.__banManager.geBanListExtendedASN(cymru_info)), - ("Banned Country list", self.__banManager.geBanListExtendedCountry(cymru_info)), - ("Banned RIR list", self.__banManager.geBanListExtendedRIR(cymru_info))] + if flavor == "cymru": + cymru_info = self.__banManager.getBanListExtendedCymruInfo() + ret += \ + [("Banned ASN list", self.__banManager.geBanListExtendedASN(cymru_info)), + ("Banned Country list", self.__banManager.geBanListExtendedCountry(cymru_info)), + ("Banned RIR list", self.__banManager.geBanListExtendedRIR(cymru_info))] return ret diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index c886bf35..71b08a2d 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -529,8 +529,7 @@ class Filter(JailThread): logSys.error(e) return failList - @property - def status(self): + def status(self, flavor="basic"): """Status of failures detected by filter. """ ret = [("Currently failed", self.failManager.size()), @@ -686,11 +685,10 @@ class FileFilter(Filter): db.updateLog(self.jail, container) return True - @property - def status(self): + def status(self, flavor="basic"): """Status of Filter plus files being monitored. """ - ret = super(FileFilter, self).status + ret = super(FileFilter, self).status(flavor=flavor) path = [m.getFileName() for m in self.getLogPath()] ret.append(("File list", path)) return ret diff --git a/fail2ban/server/filtersystemd.py b/fail2ban/server/filtersystemd.py index 3a42f61c..d1150c57 100644 --- a/fail2ban/server/filtersystemd.py +++ b/fail2ban/server/filtersystemd.py @@ -259,9 +259,8 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover or "jailless") +" filter terminated") return True - @property - def status(self): - ret = super(FilterSystemd, self).status + def status(self, flavor="basic"): + ret = super(FilterSystemd, self).status(flavor=flavor) ret.append(("Journal matches", [" + ".join(" ".join(match) for match in self.__matches)])) return ret diff --git a/fail2ban/server/jail.py b/fail2ban/server/jail.py index df28945e..0271a190 100644 --- a/fail2ban/server/jail.py +++ b/fail2ban/server/jail.py @@ -174,22 +174,12 @@ class Jail: self.filter.idle = value self.actions.idle = value - @property - def status(self): + def status(self, flavor="basic"): """The status of the jail. """ return [ - ("Filter", self.filter.status), - ("Actions", self.actions.status), - ] - - @property - def statusExtended(self): - """The extended status of the jail. - """ - return [ - ("Filter", self.filter.status), - ("Actions", self.actions.statusExtended), + ("Filter", self.filter.status(flavor=flavor)), + ("Actions", self.actions.status(flavor=flavor)), ] def putFailTicket(self, ticket): diff --git a/fail2ban/server/jailthread.py b/fail2ban/server/jailthread.py index 123a2891..e4186739 100644 --- a/fail2ban/server/jailthread.py +++ b/fail2ban/server/jailthread.py @@ -26,7 +26,7 @@ __license__ = "GPL" import sys from threading import Thread -from abc import abstractproperty, abstractmethod +from abc import abstractmethod from ..helpers import excepthook @@ -66,18 +66,12 @@ class JailThread(Thread): excepthook(*sys.exc_info()) self.run = run_with_except_hook - @abstractproperty - def status(self): # pragma: no cover - abstract + @abstractmethod + def status(self, flavor="basic"): # pragma: no cover - abstract """Abstract - Should provide status information. """ pass - @abstractproperty - def statusExtended(self): # pragma: no cover - abstract - """Abstract - Should provide extended status information. - """ - pass - def start(self): """Sets active flag and starts thread. """ diff --git a/fail2ban/server/server.py b/fail2ban/server/server.py index c8840608..d57f2cce 100644 --- a/fail2ban/server/server.py +++ b/fail2ban/server/server.py @@ -320,11 +320,8 @@ class Server: finally: self.__lock.release() - def statusJail(self, name): - return self.__jails[name].status - - def statusJailExtended(self, name): - return self.__jails[name].statusExtended + def statusJail(self, name, flavor="basic"): + return self.__jails[name].status(flavor=flavor) # Logging diff --git a/fail2ban/server/transmitter.py b/fail2ban/server/transmitter.py index 05498646..58663590 100644 --- a/fail2ban/server/transmitter.py +++ b/fail2ban/server/transmitter.py @@ -335,8 +335,6 @@ class Transmitter: return self.__server.statusJail(name) elif len(command) == 2: name = command[0] - if command[1] == "extended": - return self.__server.statusJailExtended(name) - else: - raise Exception("Invalid command (invalid status extension)") + flavor = command[1] + return self.__server.statusJail(name, flavor=flavor) raise Exception("Invalid command (no status)") diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index 3bfcc303..556f4b97 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -474,8 +474,44 @@ class Transmitter(TransmitterBase): ) ) - def testJailStatusExtended(self): - self.assertEqual(self.transm.proceed(["status", self.jailName, "extended"]), + def testJailStatusBasic(self): + self.assertEqual(self.transm.proceed(["status", self.jailName, "basic"]), + (0, + [ + ('Filter', [ + ('Currently failed', 0), + ('Total failed', 0), + ('File list', [])] + ), + ('Actions', [ + ('Currently banned', 0), + ('Total banned', 0), + ('Banned IP list', [])] + ) + ] + ) + ) + + def testJailStatusBasicKwarg(self): + self.assertEqual(self.transm.proceed(["status", self.jailName, "INVALID"]), + (0, + [ + ('Filter', [ + ('Currently failed', 0), + ('Total failed', 0), + ('File list', [])] + ), + ('Actions', [ + ('Currently banned', 0), + ('Total banned', 0), + ('Banned IP list', [])] + ) + ] + ) + ) + + def testJailStatusCymru(self): + self.assertEqual(self.transm.proceed(["status", self.jailName, "cymru"]), (0, [ ('Filter', [ @@ -495,6 +531,7 @@ class Transmitter(TransmitterBase): ) ) + def testAction(self): action = "TestCaseAction" cmdList = [ @@ -622,10 +659,6 @@ class Transmitter(TransmitterBase): self.assertEqual( self.transm.proceed(["status", "INVALID", "COMMAND"])[0],1) - def testStatusJailExtendedNOK(self): - self.assertEqual( - self.transm.proceed(["status", self.jailName, "INVALID_COMMAND"])[0],1) - def testJournalMatch(self): if not filtersystemd: # pragma: no cover if sys.version_info >= (2, 7):