RF: Refactor Jail and JailThread

Includes:
    - documentation to new format and use of properties
    - change isActive->is_active as former no longer documented for
      python3, and later introduction and documented in python2.6
    - status formatter in beautifier somewhat more automatically
      formatted; no changes are required for additional status elements
    - JailThread now set to active within `start` method, complimenting
      `stop` method
pull/628/head
Steven Hiscocks 2014-02-23 17:35:36 +00:00
parent 212d05dc0b
commit df8d700d17
19 changed files with 238 additions and 287 deletions

View File

@ -121,7 +121,7 @@ class SMTPAction(ActionBase):
self.matches = matches
self.message_values = CallingMap(
jailname = self._jail.getName(), # Doesn't change
jailname = self._jail.name,
hostname = socket.gethostname,
bantime = self._jail.actions.getBanTime,
)

View File

@ -67,28 +67,23 @@ class Beautifier:
msg = "logs: " + response
elif inC[0:1] == ['status']:
if len(inC) > 1:
# Create IP list
ipList = ""
for ip in response[1][1][2][1]:
ipList += ip + " "
# Creates file list.
fileList = ""
for f in response[0][1][2][1]:
fileList += f + " "
# Display information
msg = "Status for the jail: " + inC[1] + "\n"
msg = msg + "|- " + response[0][0] + "\n"
msg = msg + "| |- " + response[0][1][2][0] + ":\t" + fileList + "\n"
msg = msg + "| |- " + response[0][1][0][0] + ":\t" + `response[0][1][0][1]` + "\n"
msg = msg + "| `- " + response[0][1][1][0] + ":\t" + `response[0][1][1][1]` + "\n"
msg = msg + "`- " + response[1][0] + "\n"
msg = msg + " |- " + response[1][1][0][0] + ":\t" + `response[1][1][0][1]` + "\n"
msg = msg + " | `- " + response[1][1][2][0] + ":\t" + ipList + "\n"
msg = msg + " `- " + response[1][1][1][0] + ":\t" + `response[1][1][1][1]`
msg = ["Status for the jail: %s" % inC[1]]
for n, res1 in enumerate(response):
prefix1 = "`-" if n == len(response) - 1 else "|-"
msg.append("%s %s" % (prefix1, res1[0]))
prefix1 = " " if n == len(response) - 1 else "| "
for m, res2 in enumerate(res1[1]):
prefix2 = prefix1 + ("`-" if m == len(res1[1]) - 1 else "|-")
val = " ".join(res2[1]) if isinstance(res2[1], list) else res2[1]
msg.append("%s %s:\t%s" % (prefix2, res2[0], val))
else:
msg = "Status\n"
msg = msg + "|- " + response[0][0] + ":\t" + `response[0][1]` + "\n"
msg = msg + "`- " + response[1][0] + ":\t\t" + response[1][1]
msg = ["Status"]
for n, res1 in enumerate(response):
prefix1 = "`-" if n == len(response) - 1 else "|-"
val = " ".join(res1[1]) if isinstance(res1[1], list) else res1[1]
msg.append("%s %s:\t%s" % (prefix1, res1[0], val))
msg = "\n".join(msg)
elif inC[1] == "logtarget":
msg = "Current logging target is:\n"
msg = msg + "`- " + response

View File

@ -192,30 +192,29 @@ class Actions(JailThread, Mapping):
bool
True when the thread exits nicely.
"""
self.setActive(True)
for name, action in self._actions.iteritems():
try:
action.start()
except Exception as e:
logSys.error("Failed to start jail '%s' action '%s': %s",
self._jail.getName(), name, e)
while self._isActive():
if not self.getIdle():
#logSys.debug(self._jail.getName() + ": action")
self._jail.name, name, e)
while self.active:
if not self.idle:
#logSys.debug(self._jail.name + ": action")
ret = self.__checkBan()
if not ret:
self.__checkUnBan()
time.sleep(self.getSleepTime())
time.sleep(self.sleeptime)
else:
time.sleep(self.getSleepTime())
time.sleep(self.sleeptime)
self.__flushBan()
for name, action in self._actions.iteritems():
try:
action.stop()
except Exception as e:
logSys.error("Failed to stop jail '%s' action '%s': %s",
self._jail.getName(), name, e)
logSys.debug(self._jail.getName() + ": action terminated")
self._jail.name, name, e)
logSys.debug(self._jail.name + ": action terminated")
return True
def __checkBan(self):
@ -237,31 +236,31 @@ class Actions(JailThread, Mapping):
aInfo["failures"] = bTicket.getAttempt()
aInfo["time"] = bTicket.getTime()
aInfo["matches"] = "\n".join(bTicket.getMatches())
if self._jail.getDatabase() is not None:
if self._jail.database is not None:
aInfo["ipmatches"] = lambda: "\n".join(
self._jail.getDatabase().getBansMerged(
self._jail.database.getBansMerged(
ip=bTicket.getIP()).getMatches())
aInfo["ipjailmatches"] = lambda: "\n".join(
self._jail.getDatabase().getBansMerged(
self._jail.database.getBansMerged(
ip=bTicket.getIP(), jail=self._jail).getMatches())
aInfo["ipfailures"] = lambda: "\n".join(
self._jail.getDatabase().getBansMerged(
self._jail.database.getBansMerged(
ip=bTicket.getIP()).getAttempt())
aInfo["ipjailfailures"] = lambda: "\n".join(
self._jail.getDatabase().getBansMerged(
self._jail.database.getBansMerged(
ip=bTicket.getIP(), jail=self._jail).getAttempt())
if self.__banManager.addBanTicket(bTicket):
logSys.warning("[%s] Ban %s" % (self._jail.getName(), aInfo["ip"]))
logSys.warning("[%s] Ban %s" % (self._jail.name, aInfo["ip"]))
for name, action in self._actions.iteritems():
try:
action.ban(aInfo)
except Exception as e:
logSys.error(
"Failed to execute ban jail '%s' action '%s': %s",
self._jail.getName(), name, e)
self._jail.name, name, e)
return True
else:
logSys.info("[%s] %s already banned" % (self._jail.getName(),
logSys.info("[%s] %s already banned" % (self._jail.name,
aInfo["ip"]))
return False
@ -298,28 +297,20 @@ 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.warning("[%s] Unban %s" % (self._jail.name, aInfo["ip"]))
for name, action in self._actions.iteritems():
try:
action.unban(aInfo)
except Exception as e:
logSys.error(
"Failed to execute unban jail '%s' action '%s': %s",
self._jail.getName(), name, e)
self._jail.name, name, e)
@property
def status(self):
"""Get the status of the filter.
Get some informations about the filter state such as the total
number of failures.
Returns
-------
list
List of tuple pairs, each containing a description and value
for general status information.
"""Status of active bans, and total ban counts.
"""
ret = [("Currently banned", self.__banManager.size()),
("Total banned", self.__banManager.getBanTotal()),
("IP list", self.__banManager.getBanList())]
("Banned IP list", self.__banManager.getBanList())]
return ret

View File

@ -184,10 +184,10 @@ class Fail2BanDb(object):
def addJail(self, cur, jail):
cur.execute(
"INSERT OR REPLACE INTO jails(name, enabled) VALUES(?, 1)",
(jail.getName(),))
(jail.name,))
def delJail(self, jail):
return self.delJailName(jail.getName())
return self.delJailName(jail.name)
@commitandrollback
def delJailName(self, cur, name):
@ -211,7 +211,7 @@ class Fail2BanDb(object):
cur.execute(
"SELECT firstlinemd5, lastfilepos FROM logs "
"WHERE jail=? AND path=?",
(jail.getName(), container.getFileName()))
(jail.name, container.getFileName()))
try:
firstLineMD5, lastLinePos = cur.fetchone()
except TypeError:
@ -220,7 +220,7 @@ class Fail2BanDb(object):
cur.execute(
"INSERT OR REPLACE INTO logs(jail, path, firstlinemd5, lastfilepos) "
"VALUES(?, ?, ?, ?)",
(jail.getName(), container.getFileName(),
(jail.name, container.getFileName(),
container.getHash(), container.getPos()))
if container.getHash() != firstLineMD5:
lastLinePos = None
@ -232,7 +232,7 @@ class Fail2BanDb(object):
queryArgs = []
if jail is not None:
query += " WHERE jail=?"
queryArgs.append(jail.getName())
queryArgs.append(jail.name)
cur.execute(query, queryArgs)
return set(row[0] for row in cur.fetchmany())
@ -245,7 +245,7 @@ class Fail2BanDb(object):
"UPDATE logs SET firstlinemd5=?, lastfilepos=? "
"WHERE jail=? AND path=?",
(container.getHash(), container.getPos(),
jail.getName(), container.getFileName()))
jail.name, container.getFileName()))
@commitandrollback
def addBan(self, cur, jail, ticket):
@ -253,7 +253,7 @@ class Fail2BanDb(object):
#TODO: Implement data parts once arbitrary match keys completed
cur.execute(
"INSERT INTO bans(jail, ip, timeofban, data) VALUES(?, ?, ?, ?)",
(jail.getName(), ticket.getIP(), ticket.getTime(),
(jail.name, ticket.getIP(), ticket.getTime(),
{"matches": ticket.getMatches(),
"failures": ticket.getAttempt()}))
@ -264,7 +264,7 @@ class Fail2BanDb(object):
if jail is not None:
query += " AND jail=?"
queryArgs.append(jail.getName())
queryArgs.append(jail.name)
if bantime is not None:
query += " AND timeofban > ?"
queryArgs.append(MyTime.time() - bantime)
@ -284,7 +284,7 @@ class Fail2BanDb(object):
return tickets
def getBansMerged(self, ip, jail=None, **kwargs):
cacheKey = ip if jail is None else "%s|%s" % (ip, jail.getName())
cacheKey = ip if jail is None else "%s|%s" % (ip, jail.name)
if cacheKey in self._bansMergedCache:
return self._bansMergedCache[cacheKey]
matches = []

View File

@ -530,15 +530,10 @@ class Filter(JailThread):
logSys.error(e)
return failList
##
# Get the status of the filter.
#
# Get some informations about the filter state such as the total
# number of failures.
# @return a list with tuple
@property
def status(self):
"""Status of failures detected by filter.
"""
ret = [("Currently failed", self.failManager.size()),
("Total failed", self.failManager.getFailTotal())]
return ret
@ -562,7 +557,7 @@ class FileFilter(Filter):
logSys.error(path + " already exists")
else:
container = FileContainer(path, self.getLogEncoding(), tail)
db = self.jail.getDatabase()
db = self.jail.database
if db is not None:
lastpos = db.addLog(self.jail, container)
if lastpos and not tail:
@ -586,7 +581,7 @@ class FileFilter(Filter):
for log in self.__logPath:
if log.getFileName() == path:
self.__logPath.remove(log)
db = self.jail.getDatabase()
db = self.jail.database
if db is not None:
db.updateLog(self.jail, log)
logSys.info("Removed logfile = %s" % path)
@ -682,18 +677,21 @@ class FileFilter(Filter):
# might occur leading at least to tests failures.
while has_content:
line = container.readline()
if not line or not self._isActive():
if not line or not self.active:
# The jail reached the bottom or has been stopped
break
self.processLineAndAdd(line)
container.close()
db = self.jail.getDatabase()
db = self.jail.database
if db is not None:
db.updateLog(self.jail, container)
return True
@property
def status(self):
ret = Filter.status(self)
"""Status of Filter plus files being monitored.
"""
ret = super(FileFilter, self).status
path = [m.getFileName() for m in self.getLogPath()]
ret.append(("File list", path))
return ret

View File

@ -109,16 +109,15 @@ class FilterGamin(FileFilter):
# @return True when the thread exits nicely
def run(self):
self.setActive(True)
# Gamin needs a loop to collect and dispatch events
while self._isActive():
if not self.getIdle():
while self.active:
if not self.idle:
# We cannot block here because we want to be able to
# exit.
if self.monitor.event_pending():
self.monitor.handle_events()
time.sleep(self.getSleepTime())
logSys.debug(self.jail.getName() + ": filter terminated")
time.sleep(self.sleeptime)
logSys.debug(self.jail.name + ": filter terminated")
return True

View File

@ -82,12 +82,11 @@ class FilterPoll(FileFilter):
# @return True when the thread exits nicely
def run(self):
self.setActive(True)
while self._isActive():
while self.active:
if logSys.getEffectiveLevel() <= 6:
logSys.log(6, "Woke up idle=%s with %d files monitored",
self.getIdle(), len(self.getLogPath()))
if not self.getIdle():
self.idle, len(self.getLogPath()))
if not self.idle:
# Get file modification
for container in self.getLogPath():
filename = container.getFileName()
@ -104,11 +103,11 @@ class FilterPoll(FileFilter):
self.failManager.cleanup(MyTime.time())
self.dateDetector.sortTemplate()
self.__modified = False
time.sleep(self.getSleepTime())
time.sleep(self.sleeptime)
else:
time.sleep(self.getSleepTime())
time.sleep(self.sleeptime)
logSys.debug(
(self.jail is not None and self.jail.getName() or "jailless") +
(self.jail is not None and self.jail.name or "jailless") +
" filter terminated")
return True
@ -143,7 +142,7 @@ class FilterPoll(FileFilter):
if self.__file404Cnt[filename] > 2:
logSys.warning("Too many errors. Setting the jail idle")
if self.jail is not None:
self.jail.setIdle(True)
self.jail.idle = True
else:
logSys.warning("No jail is assigned to %s" % self)
self.__file404Cnt[filename] = 0

View File

@ -168,11 +168,10 @@ class FilterPyinotify(FileFilter):
# loop is necessary
def run(self):
self.setActive(True)
self.__notifier = pyinotify.ThreadedNotifier(self.__monitor,
ProcessPyinotify(self))
self.__notifier.start()
logSys.debug("pyinotifier started for %s.", self.jail.getName())
logSys.debug("pyinotifier started for %s.", self.jail.name)
# TODO: verify that there is nothing really to be done for
# idle jails
return True

View File

@ -211,7 +211,6 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
# handover to FailManager
def run(self):
self.setActive(True)
# Seek to now - findtime in journal
start_time = datetime.datetime.now() - \
@ -224,9 +223,9 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
except OSError:
pass # Reading failure, so safe to ignore
while self._isActive():
if not self.getIdle():
while self._isActive():
while self.active:
if not self.idle:
while self.active:
try:
logentry = self.__journal.get_next()
except OSError:
@ -247,20 +246,14 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
except FailManagerEmpty:
self.failManager.cleanup(MyTime.time())
self.__modified = False
self.__journal.wait(self.getSleepTime())
logSys.debug((self.jail is not None and self.jail.getName()
self.__journal.wait(self.sleeptime)
logSys.debug((self.jail is not None and self.jail.name
or "jailless") +" filter terminated")
return True
##
# Get the status of the filter.
#
# Get some informations about the filter state such as the total
# number of failures.
# @return a list with tuple
@property
def status(self):
ret = JournalFilter.status(self)
ret = super(FilterSystemd, self).status
ret.append(("Journal matches",
[" + ".join(" ".join(match) for match in self.__matches)]))
return ret

View File

@ -31,6 +31,12 @@ from .actions import Actions
logSys = logging.getLogger(__name__)
class Jail:
"""Fail2Ban jail, which manages a filter and associated actions.
The class handles the initialisation of a filter, and actions. It's
role is then to act as an interface between the filter and actions,
passing bans detected by the filter, for the actions to then act upon.
"""
#Known backends. Each backend should have corresponding __initBackend method
# yoh: stored in a list instead of a tuple since only
@ -38,15 +44,32 @@ class Jail:
_BACKENDS = ['pyinotify', 'gamin', 'polling', 'systemd']
def __init__(self, name, backend = "auto", db=None):
"""Initialise a jail, by initalises filter and actions.
Parameters
----------
name : str
Name assigned to the jail.
backend : str
Backend to be used for filter. "auto" will attempt to pick
the most preferred backend method. Default: "auto"
db : Fail2BanDb
Fail2Ban persistent database instance. Default: `None`
"""
self.__db = db
self.setName(name)
# 26 based on iptable chain name limit of 30 less len('f2b-')
if len(name) >= 26:
logSys.warning("Jail name %r might be too long and some commands "
"might not function correctly. Please shorten"
% name)
self.__name = name
self.__queue = Queue.Queue()
self.__filter = None
logSys.info("Creating new jail '%s'" % self.__name)
logSys.info("Creating new jail '%s'" % self.name)
self._setBackend(backend)
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.__name)
return "%s(%r)" % (self.__class__.__name__, self.name)
def _setBackend(self, backend):
backend = backend.lower() # to assure consistent matching
@ -78,51 +101,49 @@ class Jail:
"Backend %r failed to initialize due to %s" % (b, e))
# log error since runtime error message isn't printed, INVALID COMMAND
logSys.error(
"Failed to initialize any backend for Jail %r" % self.__name)
"Failed to initialize any backend for Jail %r" % self.name)
raise RuntimeError(
"Failed to initialize any backend for Jail %r" % self.__name)
"Failed to initialize any backend for Jail %r" % self.name)
def _initPolling(self):
logSys.info("Jail '%s' uses poller" % self.__name)
logSys.info("Jail '%s' uses poller" % self.name)
from filterpoll import FilterPoll
self.__filter = FilterPoll(self)
def _initGamin(self):
# Try to import gamin
import gamin
logSys.info("Jail '%s' uses Gamin" % self.__name)
logSys.info("Jail '%s' uses Gamin" % self.name)
from filtergamin import FilterGamin
self.__filter = FilterGamin(self)
def _initPyinotify(self):
# Try to import pyinotify
import pyinotify
logSys.info("Jail '%s' uses pyinotify" % self.__name)
logSys.info("Jail '%s' uses pyinotify" % self.name)
from filterpyinotify import FilterPyinotify
self.__filter = FilterPyinotify(self)
def _initSystemd(self): # pragma: systemd no cover
# Try to import systemd
import systemd
logSys.info("Jail '%s' uses systemd" % self.__name)
logSys.info("Jail '%s' uses systemd" % self.name)
from filtersystemd import FilterSystemd
self.__filter = FilterSystemd(self)
def setName(self, name):
# 26 based on iptable chain name limit of 30 less len('f2b-')
if len(name) >= 26:
logSys.warning("Jail name %r might be too long and some commands "
"might not function correctly. Please shorten"
% name)
self.__name = name
def getName(self):
@property
def name(self):
"""Name of jail.
"""
return self.__name
def getDatabase(self):
@property
def database(self):
"""The database used to store persistent data for the jail.
"""
return self.__db
@property
def filter(self):
"""The filter which the jail is using to monitor log files.
@ -134,50 +155,71 @@ class Jail:
"""Actions object used to manage actions for jail.
"""
return self.__actions
@property
def idle(self):
"""A boolean indicating whether jail is idle.
"""
return self.filter.idle or self.actions.idle
@idle.setter
def idle(self, value):
self.filter.idle = value
self.actions.idle = value
@property
def status(self):
"""The status of the jail.
"""
return [
("Filter", self.filter.status),
("Actions", self.actions.status),
]
def putFailTicket(self, ticket):
"""Add a fail ticket to the jail.
Used by filter to add a failure for banning.
"""
self.__queue.put(ticket)
if self.__db is not None:
self.__db.addBan(self, ticket)
if self.database is not None:
self.database.addBan(self, ticket)
def getFailTicket(self):
"""Get a fail ticket from the jail.
Used by actions to get a failure for banning.
"""
try:
return self.__queue.get(False)
except Queue.Empty:
return False
def start(self):
self.__filter.start()
self.__actions.start()
"""Start the jail, by starting filter and actions threads.
Once stated, also queries the persistent database to reinstate
any valid bans.
"""
self.filter.start()
self.actions.start()
# Restore any previous valid bans from the database
if self.__db is not None:
for ticket in self.__db.getBans(
jail=self, bantime=self.__actions.getBanTime()):
if self.database is not None:
for ticket in self.database.getBans(
jail=self, bantime=self.actions.getBanTime()):
self.__queue.put(ticket)
logSys.info("Jail '%s' started" % self.__name)
logSys.info("Jail '%s' started" % self.name)
def stop(self):
self.__filter.stop()
self.__actions.stop()
self.__filter.join()
self.__actions.join()
logSys.info("Jail '%s' stopped" % self.__name)
def isAlive(self):
isAlive0 = self.__filter.isAlive()
isAlive1 = self.__actions.isAlive()
return isAlive0 or isAlive1
def setIdle(self, value):
self.__filter.setIdle(value)
self.__actions.setIdle(value)
def getIdle(self):
return self.__filter.getIdle() or self.__actions.getIdle()
def getStatus(self):
fStatus = self.__filter.status()
aStatus = self.__actions.status()
ret = [("filter", fStatus),
("action", aStatus)]
return ret
"""Stop the jail, by stopping filter and actions threads.
"""
self.filter.stop()
self.actions.stop()
self.filter.join()
self.actions.join()
logSys.info("Jail '%s' stopped" % self.name)
def is_alive(self):
"""Check jail "is_alive" by checking filter and actions threads.
"""
return self.filter.is_alive() or self.actions.is_alive()

View File

@ -25,94 +25,42 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
from threading import Thread
import logging
# Gets the instance of the logger.
logSys = logging.getLogger(__name__)
from abc import abstractproperty, abstractmethod
class JailThread(Thread):
##
# Constructor.
#
# Initialize the filter object with default values.
# @param jail the jail object
"""Abstract class for threading elements in Fail2Ban.
"""
def __init__(self):
Thread.__init__(self)
"""Initialise a JailThread instance.
"""
super(JailThread, self).__init__()
## Control the state of the thread.
self.__isRunning = False
self.active = False
## Control the idle state of the thread.
self.__isIdle = False
self.idle = False
## The time the thread sleeps in the loop.
self.__sleepTime = 1
##
# Set the time that the thread sleeps.
#
# This value could also be called "polling time". A value of 1 is a
# good one. This unit is "second"
# @param value the polling time (second)
def setSleepTime(self, value):
self.__sleepTime = value
logSys.info("Set sleeptime %s" % value)
##
# Get the time that the thread sleeps.
#
# @return the polling time
def getSleepTime(self):
return self.__sleepTime
##
# Set the idle flag.
#
# This flag stops the check of the log file.
# @param value boolean value
def setIdle(self, value):
self.__isIdle = value
##
# Get the idle state.
#
# @return the idle state
def getIdle(self):
return self.__isIdle
##
# Stop the thread.
#
# Stop the exection of the thread and quit.
def stop(self):
self.__isRunning = False
##
# Set the isRunning flag.
#
# @param value True if the thread is running
def setActive(self, value):
self.__isRunning = value
##
# Check if the thread is active.
#
# Check if the filter thread is running.
# @return True if the thread is running
def _isActive(self):
return self.__isRunning
##
# Get the status of the thread
#
# Get some informations about the thread. This is an abstract method.
# @return a list with tuple
def status(self):
self.sleeptime = 1
@abstractproperty
def status(self): # pragma: no cover - abstract
"""Abstract - Should provide status information.
"""
pass
def start(self):
"""Sets active flag and starts thread.
"""
self.active = True
super(JailThread, self).start()
def stop(self):
"""Sets `active` property to False, to flag run method to return.
"""
self.active = False
@abstractmethod
def run(self): # pragma: no cover - absract
"""Abstract - Called when thread starts, thread stops when returns.
"""
pass

View File

@ -132,7 +132,7 @@ class Server:
def startJail(self, name):
try:
self.__lock.acquire()
if not self.isAlive(name):
if not self.__jails[name].is_alive():
self.__jails[name].start()
finally:
self.__lock.release()
@ -141,7 +141,7 @@ class Server:
logSys.debug("Stopping jail %s" % name)
try:
self.__lock.acquire()
if self.isAlive(name):
if self.__jails[name].is_alive():
self.__jails[name].stop()
self.delJail(name)
finally:
@ -155,16 +155,13 @@ class Server:
self.stopJail(jail)
finally:
self.__lock.release()
def isAlive(self, name):
return self.__jails[name].isAlive()
def setIdleJail(self, name, value):
self.__jails[name].setIdle(value)
self.__jails[name].idle = value
return True
def getIdleJail(self, name):
return self.__jails[name].getIdle()
return self.__jails[name].idle
# Filter
def addIgnoreIP(self, name, ip):
@ -316,7 +313,7 @@ class Server:
self.__lock.release()
def statusJail(self, name):
return self.__jails[name].getStatus()
return self.__jails[name].status
# Logging

View File

@ -77,7 +77,7 @@ class SMTPActionTest(unittest.TestCase):
self.assertEqual(self.smtpd.mailfrom, "fail2ban")
self.assertEqual(self.smtpd.rcpttos, ["root"])
self.assertTrue(
"Subject: [Fail2Ban] %s: started" % self.jail.getName()
"Subject: [Fail2Ban] %s: started" % self.jail.name
in self.smtpd.data)
def testStop(self):
@ -86,7 +86,7 @@ class SMTPActionTest(unittest.TestCase):
self.assertEqual(self.smtpd.rcpttos, ["root"])
self.assertTrue(
"Subject: [Fail2Ban] %s: stopped" %
self.jail.getName() in self.smtpd.data)
self.jail.name in self.smtpd.data)
def testBan(self):
aInfo = {
@ -102,7 +102,7 @@ class SMTPActionTest(unittest.TestCase):
self.assertEqual(self.smtpd.rcpttos, ["root"])
self.assertTrue(
"Subject: [Fail2Ban] %s: banned %s" %
(self.jail.getName(), aInfo['ip']) in self.smtpd.data)
(self.jail.name, aInfo['ip']) in self.smtpd.data)
self.assertTrue(
"%i attempts" % aInfo['failures'] in self.smtpd.data)

View File

@ -84,8 +84,8 @@ class ExecuteActions(LogCaptureTestCase):
self.__actions.stop()
self.__actions.join()
self.assertEqual(self.__actions.status(),[("Currently banned", 0 ),
("Total banned", 0 ), ("IP list", [] )])
self.assertEqual(self.__actions.status,[("Currently banned", 0 ),
("Total banned", 0 ), ("Banned IP list", [] )])
def testAddActionPython(self):

View File

@ -61,7 +61,7 @@ class DatabaseTest(unittest.TestCase):
self.db = Fail2BanDb(self.dbFilename)
# and check jail of same name still present
self.assertTrue(
self.jail.getName() in self.db.getJailNames(),
self.jail.name in self.db.getJailNames(),
"Jail not retained in Db after disconnect reconnect.")
def testUpdateDb(self):
@ -80,7 +80,7 @@ class DatabaseTest(unittest.TestCase):
self.jail = DummyJail()
self.db.addJail(self.jail)
self.assertTrue(
self.jail.getName() in self.db.getJailNames(),
self.jail.name in self.db.getJailNames(),
"Jail not added to database")
def testAddLog(self):

View File

@ -32,6 +32,8 @@ class DummyJail(object):
def __init__(self):
self.lock = Lock()
self.queue = []
self.idle = False
self.database = None
self.actions = Actions(self)
def __len__(self):
@ -58,15 +60,6 @@ class DummyJail(object):
finally:
self.lock.release()
def setIdle(self, value):
pass
def getIdle(self):
pass
def getName(self):
@property
def name(self):
return "DummyJail #%s with %d tickets" % (id(self), len(self))
def getDatabase(self):
return None

View File

@ -325,7 +325,7 @@ class LogFileMonitor(LogCaptureTestCase):
self.file = open(self.name, 'a')
self.filter = FilterPoll(DummyJail())
self.filter.addLogPath(self.name)
self.filter.setActive(True)
self.filter.active = True
self.filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) <HOST>")
def tearDown(self):
@ -466,7 +466,7 @@ def get_monitor_failures_testcase(Filter_):
self.jail = DummyJail()
self.filter = Filter_(self.jail)
self.filter.addLogPath(self.name)
self.filter.setActive(True)
self.filter.active = True
self.filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) <HOST>")
self.filter.start()
# If filter is polling it would sleep a bit to guarantee that
@ -687,7 +687,7 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
"TEST_UUID=%s" % self.test_uuid])
self.journal_fields = {
'TEST_FIELD': "1", 'TEST_UUID': self.test_uuid}
self.filter.setActive(True)
self.filter.active = True
self.filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) <HOST>")
self.filter.start()
@ -804,7 +804,7 @@ class GetFailures(unittest.TestCase):
setUpMyTime()
self.jail = DummyJail()
self.filter = FileFilter(self.jail)
self.filter.setActive(True)
self.filter.active = True
# TODO Test this
#self.filter.setTimeRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
#self.filter.setTimePattern("%b %d %H:%M:%S")
@ -895,7 +895,7 @@ class GetFailures(unittest.TestCase):
('warn', output_yes)):
jail = DummyJail()
filter_ = FileFilter(jail, useDns=useDns)
filter_.setActive(True)
filter_.active = True
filter_.failManager.setMaxRetry(1) # we might have just few failures
filter_.addLogPath(GetFailures.FILENAME_USEDNS)

View File

@ -45,7 +45,7 @@ class FilterSamplesRegex(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.filter = Filter(None)
self.filter.setActive(True)
self.filter.active = True
setUpMyTime()

View File

@ -227,8 +227,7 @@ class Transmitter(TransmitterBase):
time.sleep(1)
self.assertEqual(
self.transm.proceed(["stop", self.jailName]), (0, None))
self.assertRaises(
UnknownJailException, self.server.isAlive, self.jailName)
self.assertTrue(self.jailName not in self.server._Server__jails)
def testStartStopAllJail(self):
self.server.addJail("TestJail2", "auto")
@ -242,10 +241,8 @@ class Transmitter(TransmitterBase):
time.sleep(0.1)
self.assertEqual(self.transm.proceed(["stop", "all"]), (0, None))
time.sleep(1)
self.assertRaises(
UnknownJailException, self.server.isAlive, self.jailName)
self.assertRaises(
UnknownJailException, self.server.isAlive, "TestJail2")
self.assertTrue(self.jailName not in self.server._Server__jails)
self.assertTrue("TestJail2" not in self.server._Server__jails)
def testJailIdle(self):
self.assertEqual(
@ -482,15 +479,15 @@ class Transmitter(TransmitterBase):
self.assertEqual(self.transm.proceed(["status", self.jailName]),
(0,
[
('filter', [
('Filter', [
('Currently failed', 0),
('Total failed', 0),
('File list', [])]
),
('action', [
('Actions', [
('Currently banned', 0),
('Total banned', 0),
('IP list', [])]
('Banned IP list', [])]
)
]
)
@ -774,7 +771,7 @@ class JailTests(unittest.TestCase):
# Just a smoke test for now
longname = "veryveryverylongname"
jail = Jail(longname)
self.assertEqual(jail.getName(), longname)
self.assertEqual(jail.name, longname)
class RegexTests(unittest.TestCase):