ip-list is sorted now (by end of ban) per default;

extended with new option `--with-time` to provide more pretty and informative result (separated by new-line, including time strings: time of ban + ban-time = end of ban):
  192.0.2.1    2019-01-06 22:24:48 + 300 = 2019-01-06 22:29:48
  192.0.2.2    2019-01-06 22:24:48 + 600 = 2019-01-06 22:34:48
also it is possible now to provide separator-character as extra-parameter after `get <jail> banip ?sep-char?` (default is space).
removed unneeded test-cases (test code-base minimization) and unexpected manually changed files.
pull/2315/head
sebres 2019-01-06 22:31:23 +01:00
parent 7f5f7017db
commit df97fd33cf
10 changed files with 60 additions and 50 deletions

View File

@ -56,7 +56,7 @@ ver. 0.11.0-dev-0 (20??/??/??) - development nightly edition
end of ban) of the ticket with ban-time of jail (as maximum), for all tickets with ban-time greater
(or persistent); not affected if ban-time of the jail is unchanged between stop/start.
* added new setup-option `--without-tests` to skip building and installing of tests files (gh-2287).
* added new command `fail2ban-client get <JAIL> banip` to get the banned ip addresses (gh-1916).
* added new command `fail2ban-client get <JAIL> banip ?--with-time|sep-char?` to get the banned ip addresses (gh-1916).
ver. 0.10.4-dev-1 (20??/??/??) - development edition

View File

@ -181,7 +181,11 @@ class Beautifier:
"methods:\n" % (inC[1], inC[3])
msg += ", ".join(response)
elif inC[2] == "banip" and inC[0] == "get":
msg = " ".join(response)
if isinstance(response, list):
sep = " " if len(inC) <= 3 else inC[3]
if sep == "--with-time":
sep = "\n"
msg = sep.join(response)
except Exception:
logSys.warning("Beautifier error. Please report the error")
logSys.error("Beautify %r with %r failed", response, self.__inputCmd,

View File

@ -204,7 +204,7 @@ class Actions(JailThread, Mapping):
def getBanTime(self):
return self.__banManager.getBanTime()
def getBanList(self):
def getBanList(self, withTime=False):
"""Returns the list of banned IP addresses.
Returns
@ -212,7 +212,7 @@ class Actions(JailThread, Mapping):
list
The list of banned IP addresses.
"""
return self.__banManager.getBanList()
return self.__banManager.getBanList(ordered=True, withTime=withTime)
def removeBannedIP(self, ip=None, db=True, ifexists=False):
"""Removes banned IP calling actions' unban method

View File

@ -102,9 +102,22 @@ class BanManager:
#
# @return IP list
def getBanList(self):
def getBanList(self, ordered=False, withTime=False):
with self.__lock:
return self.__banList.keys()
if not ordered:
return self.__banList.keys()
lst = []
for ticket in self.__banList.itervalues():
eob = ticket.getEndOfBanTime(self.__banTime)
lst.append((ticket,eob))
lst.sort(key=lambda t: t[1])
t2s = MyTime.time2str
if withTime:
return ['%s \t%s + %d = %s' % (
t[0].getID(),
t2s(t[0].getTime()), t[0].getBanTime(self.__banTime), t2s(t[1])
) for t in lst]
return [t[0].getID() for t in lst]
##
# Returns a iterator to ban list (used in reload, so idle).

View File

@ -113,6 +113,16 @@ class MyTime:
return time.localtime(x)
else:
return time.localtime(MyTime.myTime)
@staticmethod
def time2str(unixTime):
"""Convert time to a string representing as date and time in ISO 8601
format, YYYY-MM-DD HH:MM:SS without microseconds.
@return ISO-capable string representation of given unixTime
"""
return datetime.datetime.fromtimestamp(
unixTime).replace(microsecond=0).strftime("%Y-%m-%d %H:%M:%S")
## precreate/precompile primitives used in str2seconds:

View File

@ -510,7 +510,7 @@ class Server:
def getBanTime(self, name):
return self.__jails[name].actions.getBanTime()
def getBanList(self, name):
def getBanList(self, name, withTime=False):
"""Returns the list of banned IP addresses for a jail.
Parameters
@ -523,7 +523,7 @@ class Server:
list
The list of banned IP addresses.
"""
return self.__jails[name].actions.getBanList()
return self.__jails[name].actions.getBanList(withTime)
def setBanTimeExtra(self, name, opt, value):
self.__jails[name].setBanTimeExtra(opt, value)

View File

@ -391,7 +391,8 @@ class Transmitter:
elif command[1] == "bantime":
return self.__server.getBanTime(name)
elif command[1] == "banip":
return self.__server.getBanList(name)
return self.__server.getBanList(name,
withTime=len(command) > 2 and command[2] == "--with-time")
elif command[1].startswith("bantime."):
opt = command[1][len("bantime."):]
return self.__server.getBanTimeExtra(name, opt)

View File

@ -261,10 +261,3 @@ class BeautifierTest(unittest.TestCase):
output = "Sorry but the command is invalid"
self.assertEqual(self.b.beautifyError(IndexError()), output)
def testJailBanList(self):
self.b.setInputCmd(["get", "ssh", "banip"])
response = ["192.168.0.1", "192.168.1.10"]
output = "192.168.0.1 192.168.1.10"
self.assertEqual(self.b.beautify(response), output)
self.assertEqual(self.b.beautify([]), "")

View File

@ -1064,6 +1064,17 @@ class Fail2banServerTest(Fail2banClientServerBase):
"stdout: '[test-jail2] test-action3: ++ ban 192.0.2.22",
"stdout: '[test-jail2] test-action3: ++ ban 192.0.2.22 ", all=True, wait=MID_WAITTIME)
# get banned ips:
_observer_wait_idle()
self.pruneLog("[test-phase 2d.1]")
self.execCmd(SUCCESS, startparams, "get", "test-jail2", "banip", "\n")
self.assertLogged(
"192.0.2.4", "192.0.2.8", "192.0.2.21", "192.0.2.22", all=True, wait=MID_WAITTIME)
self.pruneLog("[test-phase 2d.2]")
self.execCmd(SUCCESS, startparams, "get", "test-jail1", "banip")
self.assertLogged(
"192.0.2.1", "192.0.2.2", "192.0.2.3", "192.0.2.4", "192.0.2.8", all=True, wait=MID_WAITTIME)
# restart jail with unban all:
self.pruneLog("[test-phase 2e]")
self.execCmd(SUCCESS, startparams,
@ -1227,36 +1238,6 @@ class Fail2banServerTest(Fail2banClientServerBase):
"Jail 'test-jail1' stopped",
"Jail 'test-jail1' started", all=True, wait=MID_WAITTIME)
# test the list of banned IP addresses, step 0: prepare
self.pruneLog("[test-phase 9a]")
self.execCmd(SUCCESS, startparams, "reload", "--unban", "test-jail1")
self.assertLogged(
"Jail 'test-jail1' reloaded", wait=MID_WAITTIME)
# test the list of banned IP addresses, step 1: ban IP addresses
self.pruneLog("[test-phase 9b]")
self.execCmd(SUCCESS, startparams,
"set", "test-jail1", "banip", "192.168.0.1")
self.assertLogged("[test-jail1] Ban 192.168.0.1", wait=MID_WAITTIME)
self.execCmd(SUCCESS, startparams,
"set", "test-jail1", "banip", "192.168.1.10")
self.assertLogged("[test-jail1] Ban 192.168.1.10", wait=MID_WAITTIME)
self.execCmd(SUCCESS, startparams, "get", "test-jail1", "banip")
self.assertLogged(
"192.168.1.10 192.168.0.1",
"192.168.0.1 192.168.1.10", wait=MID_WAITTIME)
# test the list of banned IP addresses, step 2: unban IP addresses
self.pruneLog("[test-phase 9c]")
self.execCmd(SUCCESS, startparams,
"set", "test-jail1", "unbanip", "192.168.0.1")
self.assertLogged("[test-jail1] Unban 192.168.0.1", wait=MID_WAITTIME)
self.execCmd(SUCCESS, startparams,
"set", "test-jail1", "unbanip", "192.168.1.10")
self.assertLogged("[test-jail1] Unban 192.168.1.10", wait=MID_WAITTIME)
self.execCmd(SUCCESS, startparams, "get", "test-jail1", "banip")
self.assertNotLogged(
"192.168.1.10 192.168.0.1",
"192.168.0.1 192.168.1.10", wait=MID_WAITTIME)
# test action.d/nginx-block-map.conf --
@unittest.F2B.skip_if_cfg_missing(action="nginx-block-map")
@with_foreground_server_thread(startextra={
@ -1427,6 +1408,11 @@ class Fail2banServerTest(Fail2banClientServerBase):
"stdout: '[test-jail1] test-action1: ++ ban 192.0.2.11 -c 2 -t 300 : ",
"stdout: '[test-jail1] test-action2: ++ ban 192.0.2.11 -c 2 -t 300 : ",
all=True, wait=MID_WAITTIME)
# get banned ips with time:
self.pruneLog("[test-phase 2) time+10m - get-ips]")
self.execCmd(SUCCESS, startparams, "get", "test-jail1", "banip", "--with-time")
self.assertLogged(
"192.0.2.11", "+ 300 =", all=True, wait=MID_WAITTIME)
# unblock observer here and wait it is done:
wakeObs = True
_observer_wait_idle()
@ -1441,6 +1427,13 @@ class Fail2banServerTest(Fail2banClientServerBase):
"stdout: '[test-jail1] test-action2: ++ prolong 192.0.2.11 -c 2 -t 600 : ",
all=True, wait=MID_WAITTIME)
# get banned ips with time:
_observer_wait_idle()
self.pruneLog("[test-phase 2) time+11m - get-ips]")
self.execCmd(SUCCESS, startparams, "get", "test-jail1", "banip", "--with-time")
self.assertLogged(
"192.0.2.11", "+ 600 =", all=True, wait=MID_WAITTIME)
# test multiple start/stop of the server (threaded in foreground) --
if False: # pragma: no cover
@with_foreground_server_thread()

View File

@ -379,10 +379,6 @@ will look back for failures for
gets the time a host is banned for
<JAIL>
.TP
\fBget <JAIL> banip\fR
gets the list of banned IP
addresses for <JAIL>
.TP
\fBget <JAIL> datepattern\fR
gets the patern used to match
date/times for <JAIL>