mirror of https://github.com/fail2ban/fail2ban
Merge commit '0.8.6-100-gdca5634' into debian-devel -- inotify backend should work
* commit '0.8.6-100-gdca5634': RF: reordered tests + enabled gamin now that its fix is pending in Debian ENH+BF: filtergamin -- to be more inline with current design of filterinotify ENH: 1 more sleep_4_poll to guarantee difference in time stamp ENH: few more delays for cases relying on time stampspull/808/head
commit
954254008b
|
@ -119,6 +119,20 @@ tests.addTest(unittest.makeSuite(banmanagertestcase.AddFailure))
|
||||||
# ClientReader
|
# ClientReader
|
||||||
tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest))
|
tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest))
|
||||||
|
|
||||||
|
# Filter
|
||||||
|
tests.addTest(unittest.makeSuite(filtertestcase.IgnoreIP))
|
||||||
|
tests.addTest(unittest.makeSuite(filtertestcase.LogFile))
|
||||||
|
tests.addTest(unittest.makeSuite(filtertestcase.LogFileMonitor))
|
||||||
|
tests.addTest(unittest.makeSuite(filtertestcase.GetFailures))
|
||||||
|
tests.addTest(unittest.makeSuite(filtertestcase.DNSUtilsTests))
|
||||||
|
|
||||||
|
# DateDetector
|
||||||
|
tests.addTest(unittest.makeSuite(datedetectortestcase.DateDetectorTest))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Extensive use-tests of different available filters backends
|
||||||
|
#
|
||||||
|
|
||||||
from server.filterpoll import FilterPoll
|
from server.filterpoll import FilterPoll
|
||||||
filters = [FilterPoll] # always available
|
filters = [FilterPoll] # always available
|
||||||
|
|
||||||
|
@ -127,8 +141,7 @@ filters = [FilterPoll] # always available
|
||||||
# with good old unittest
|
# with good old unittest
|
||||||
try:
|
try:
|
||||||
from server.filtergamin import FilterGamin
|
from server.filtergamin import FilterGamin
|
||||||
# That shmug plain doesn't work and stalls things ATM
|
filters.append(FilterGamin)
|
||||||
# filters.append(FilterGamin)
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -142,22 +155,6 @@ for Filter_ in filters:
|
||||||
tests.addTest(unittest.makeSuite(
|
tests.addTest(unittest.makeSuite(
|
||||||
filtertestcase.get_monitor_failures_testcase(Filter_)))
|
filtertestcase.get_monitor_failures_testcase(Filter_)))
|
||||||
|
|
||||||
# yoh: adding them (in particular datadetectortestscase before above
|
|
||||||
# get_monitor_failures_testcase's makes them fail (probably due
|
|
||||||
# to additional thread making it busier or smth like
|
|
||||||
# that)... TODO
|
|
||||||
|
|
||||||
# Filter
|
|
||||||
tests.addTest(unittest.makeSuite(filtertestcase.IgnoreIP))
|
|
||||||
tests.addTest(unittest.makeSuite(filtertestcase.LogFile))
|
|
||||||
tests.addTest(unittest.makeSuite(filtertestcase.LogFileMonitor))
|
|
||||||
tests.addTest(unittest.makeSuite(filtertestcase.GetFailures))
|
|
||||||
tests.addTest(unittest.makeSuite(filtertestcase.DNSUtilsTests))
|
|
||||||
|
|
||||||
# DateDetector
|
|
||||||
tests.addTest(unittest.makeSuite(datedetectortestcase.DateDetectorTest))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Run the tests
|
# Run the tests
|
||||||
|
|
|
@ -17,14 +17,10 @@
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
# along with Fail2Ban; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
# Author: Cyril Jaquier, Yaroslav Halchenko
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
__author__ = "Cyril Jaquier, Yaroslav Halchenko"
|
||||||
__version__ = "$Revision$"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012 Yaroslav Halchenko"
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
from failmanager import FailManagerEmpty
|
from failmanager import FailManagerEmpty
|
||||||
|
@ -50,7 +46,7 @@ class FilterGamin(FileFilter):
|
||||||
#
|
#
|
||||||
# Initialize the filter object with default values.
|
# Initialize the filter object with default values.
|
||||||
# @param jail the jail object
|
# @param jail the jail object
|
||||||
|
|
||||||
def __init__(self, jail):
|
def __init__(self, jail):
|
||||||
FileFilter.__init__(self, jail)
|
FileFilter.__init__(self, jail)
|
||||||
self.__modified = False
|
self.__modified = False
|
||||||
|
@ -63,9 +59,26 @@ class FilterGamin(FileFilter):
|
||||||
logSys.debug("Got event: " + `event` + " for " + path)
|
logSys.debug("Got event: " + `event` + " for " + path)
|
||||||
if event in (gamin.GAMCreated, gamin.GAMChanged, gamin.GAMExists):
|
if event in (gamin.GAMCreated, gamin.GAMChanged, gamin.GAMExists):
|
||||||
logSys.debug("File changed: " + path)
|
logSys.debug("File changed: " + path)
|
||||||
self.getFailures(path)
|
|
||||||
self.__modified = True
|
self.__modified = True
|
||||||
|
|
||||||
|
self._process_file(path)
|
||||||
|
|
||||||
|
|
||||||
|
def _process_file(self, path):
|
||||||
|
"""Process a given file
|
||||||
|
|
||||||
|
TODO -- RF:
|
||||||
|
this is a common logic and must be shared/provided by FileFilter
|
||||||
|
"""
|
||||||
|
self.getFailures(path)
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
ticket = self.failManager.toBan()
|
||||||
|
self.jail.putFailTicket(ticket)
|
||||||
|
except FailManagerEmpty:
|
||||||
|
self.failManager.cleanup(MyTime.time())
|
||||||
|
self.dateDetector.sortTemplate()
|
||||||
|
self.__modified = False
|
||||||
|
|
||||||
##
|
##
|
||||||
# Add a log file path
|
# Add a log file path
|
||||||
|
@ -80,7 +93,7 @@ class FilterGamin(FileFilter):
|
||||||
#
|
#
|
||||||
# @param path the log file to delete
|
# @param path the log file to delete
|
||||||
|
|
||||||
def delLogPath(self, path):
|
def _delLogPath(self, path):
|
||||||
self.monitor.stop_watch(path)
|
self.monitor.stop_watch(path)
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -92,30 +105,22 @@ class FilterGamin(FileFilter):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.setActive(True)
|
self.setActive(True)
|
||||||
|
# Gamin needs a loop to collect and dispatch events
|
||||||
while self._isActive():
|
while self._isActive():
|
||||||
if not self.getIdle():
|
if not self.getIdle():
|
||||||
# We cannot block here because we want to be able to
|
# We cannot block here because we want to be able to
|
||||||
# exit.
|
# exit.
|
||||||
if self.monitor.event_pending():
|
if self.monitor.event_pending():
|
||||||
self.monitor.handle_events()
|
self.monitor.handle_events()
|
||||||
|
time.sleep(self.getSleepTime())
|
||||||
if self.__modified:
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
ticket = self.failManager.toBan()
|
|
||||||
self.jail.putFailTicket(ticket)
|
|
||||||
except FailManagerEmpty:
|
|
||||||
self.failManager.cleanup(MyTime.time())
|
|
||||||
self.dateDetector.sortTemplate()
|
|
||||||
self.__modified = False
|
|
||||||
time.sleep(self.getSleepTime())
|
|
||||||
else:
|
|
||||||
time.sleep(self.getSleepTime())
|
|
||||||
# Cleanup Gamin
|
|
||||||
self.__cleanup()
|
|
||||||
logSys.debug(self.jail.getName() + ": filter terminated")
|
logSys.debug(self.jail.getName() + ": filter terminated")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
super(FilterGamin, self).stop()
|
||||||
|
self.__cleanup()
|
||||||
|
|
||||||
##
|
##
|
||||||
# Desallocates the resources used by Gamin.
|
# Desallocates the resources used by Gamin.
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,18 @@ def _killfile(f, name):
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _sleep_4_poll():
|
||||||
|
"""PollFilter relies on file timestamps - so we might need to
|
||||||
|
sleep to guarantee that they differ
|
||||||
|
"""
|
||||||
|
if sys.version_info[:2] <= (2,4):
|
||||||
|
# on old Python st_mtime is int, so we should give
|
||||||
|
# at least 1 sec so polling filter could detect
|
||||||
|
# the change
|
||||||
|
time.sleep(1.)
|
||||||
|
else:
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
def _assert_equal_entries(utest, found, output, count=None):
|
def _assert_equal_entries(utest, found, output, count=None):
|
||||||
"""Little helper to unify comparisons with the target entries
|
"""Little helper to unify comparisons with the target entries
|
||||||
|
|
||||||
|
@ -201,12 +213,14 @@ class LogFileMonitor(unittest.TestCase):
|
||||||
# but not any longer
|
# but not any longer
|
||||||
self.assertTrue(self.notModified())
|
self.assertTrue(self.notModified())
|
||||||
self.assertTrue(self.notModified())
|
self.assertTrue(self.notModified())
|
||||||
|
_sleep_4_poll() # to guarantee freshier mtime
|
||||||
for i in range(4): # few changes
|
for i in range(4): # few changes
|
||||||
# unless we write into it
|
# unless we write into it
|
||||||
self.file.write("line%d\n" % i)
|
self.file.write("line%d\n" % i)
|
||||||
self.file.flush()
|
self.file.flush()
|
||||||
self.assertTrue(self.isModified())
|
self.assertTrue(self.isModified())
|
||||||
self.assertTrue(self.notModified())
|
self.assertTrue(self.notModified())
|
||||||
|
_sleep_4_poll() # to guarantee freshier mtime
|
||||||
os.rename(self.name, self.name + '.old')
|
os.rename(self.name, self.name + '.old')
|
||||||
# we are not signaling as modified whenever
|
# we are not signaling as modified whenever
|
||||||
# it gets away
|
# it gets away
|
||||||
|
@ -214,6 +228,7 @@ class LogFileMonitor(unittest.TestCase):
|
||||||
f = open(self.name, 'a')
|
f = open(self.name, 'a')
|
||||||
self.assertTrue(self.isModified())
|
self.assertTrue(self.isModified())
|
||||||
self.assertTrue(self.notModified())
|
self.assertTrue(self.notModified())
|
||||||
|
_sleep_4_poll()
|
||||||
f.write("line%d\n" % i)
|
f.write("line%d\n" % i)
|
||||||
f.flush()
|
f.flush()
|
||||||
self.assertTrue(self.isModified())
|
self.assertTrue(self.isModified())
|
||||||
|
@ -356,13 +371,7 @@ def get_monitor_failures_testcase(Filter_):
|
||||||
# actions might be happening too fast in the tests,
|
# actions might be happening too fast in the tests,
|
||||||
# sleep a bit to guarantee reliable time stamps
|
# sleep a bit to guarantee reliable time stamps
|
||||||
if isinstance(self.filter, FilterPoll):
|
if isinstance(self.filter, FilterPoll):
|
||||||
if sys.version_info[:2] <= (2,4):
|
_sleep_4_poll()
|
||||||
# on old Python st_mtime is int, so we should give
|
|
||||||
# at least 1 sec so polling filter could detect
|
|
||||||
# the change
|
|
||||||
time.sleep(0.5)
|
|
||||||
else:
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def isEmpty(self, delay=0.4):
|
def isEmpty(self, delay=0.4):
|
||||||
# shorter wait time for not modified status
|
# shorter wait time for not modified status
|
||||||
|
|
Loading…
Reference in New Issue