mirror of https://github.com/fail2ban/fail2ban
ENH: Database now optional, by setting dbfile to "None"
parent
174f9a243a
commit
e18af48e34
|
@ -49,9 +49,10 @@ pidfile = /var/run/fail2ban/fail2ban.pid
|
|||
|
||||
# Options: dbfile
|
||||
# Notes.: Set the file for the fail2ban persistent data to be stored.
|
||||
# A value of :memory: means database is only stored in memory, and
|
||||
# data is lost once fail2ban is stops.
|
||||
# Values: [ FILE ] :memory: Default: /var/lib/fail2ban/fail2ban.sqlite3
|
||||
# A value of ":memory:" means database is only stored in memory
|
||||
# and data is lost once fail2ban is stops.
|
||||
# A value of "None" disables the database.
|
||||
# Values: [ None :memory: FILE ] Default: /var/lib/fail2ban/fail2ban.sqlite3
|
||||
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
|
||||
|
||||
# Options: dbpurgeage
|
||||
|
|
|
@ -103,11 +103,17 @@ class Beautifier:
|
|||
else:
|
||||
msg = msg + `response`
|
||||
elif inC[1] == "dbfile":
|
||||
msg = "Current database file is:\n"
|
||||
msg = msg + "`- " + response
|
||||
if response is None:
|
||||
msg = "Database currently disabled"
|
||||
else:
|
||||
msg = "Current database file is:\n"
|
||||
msg = msg + "`- " + response
|
||||
elif inC[1] == "dbpurgeage":
|
||||
msg = "Current database purge age is:\n"
|
||||
msg = msg + "`- %iseconds" % response
|
||||
if response is None:
|
||||
msg = "Database currently disabled"
|
||||
else:
|
||||
msg = "Current database purge age is:\n"
|
||||
msg = msg + "`- %iseconds" % response
|
||||
elif inC[2] in ("logpath", "addlogpath", "dellogpath"):
|
||||
if len(response) == 0:
|
||||
msg = "No file is currently monitored"
|
||||
|
|
|
@ -44,7 +44,7 @@ protocol = [
|
|||
["set logtarget <TARGET>", "sets logging target to <TARGET>. Can be STDOUT, STDERR, SYSLOG or a file"],
|
||||
["get logtarget", "gets logging target"],
|
||||
['', "DATABASE", ""],
|
||||
["set dbfile <FILE>", "set the location of fail2ban persistent datastore"],
|
||||
["set dbfile <FILE>", "set the location of fail2ban persistent datastore. Set to \"None\" to disable"],
|
||||
["get dbfile", "get the location of fail2ban persistent datastore"],
|
||||
["set dbpurgeage <SECONDS>", "sets the max age in <SECONDS> that history of bans will be kept"],
|
||||
["get dbpurgeage", "gets the max age in seconds that history of bans will be kept"],
|
||||
|
|
|
@ -527,9 +527,11 @@ class FileFilter(Filter):
|
|||
logSys.error(path + " already exists")
|
||||
else:
|
||||
container = FileContainer(path, self.getLogEncoding(), tail)
|
||||
lastpos = self.jail.getDatabase().addLog(self.jail, container)
|
||||
if lastpos and not tail:
|
||||
container.setPos(lastpos)
|
||||
db = self.jail.getDatabase()
|
||||
if db is not None:
|
||||
lastpos = db.addLog(self.jail, container)
|
||||
if lastpos and not tail:
|
||||
container.setPos(lastpos)
|
||||
self.__logPath.append(container)
|
||||
logSys.info("Added logfile = %s" % path)
|
||||
self._addLogPath(path) # backend specific
|
||||
|
@ -549,7 +551,9 @@ class FileFilter(Filter):
|
|||
for log in self.__logPath:
|
||||
if log.getFileName() == path:
|
||||
self.__logPath.remove(log)
|
||||
self.jail.getDatabase().updateLog(self.jail, log)
|
||||
db = self.jail.getDatabase()
|
||||
if db is not None:
|
||||
db.updateLog(self.jail, log)
|
||||
logSys.info("Removed logfile = %s" % path)
|
||||
self._delLogPath(path)
|
||||
return
|
||||
|
@ -648,7 +652,9 @@ class FileFilter(Filter):
|
|||
break
|
||||
self.processLineAndAdd(line)
|
||||
container.close()
|
||||
self.jail.getDatabase().updateLog(self.jail, container)
|
||||
db = self.jail.getDatabase()
|
||||
if db is not None:
|
||||
db.updateLog(self.jail, container)
|
||||
return True
|
||||
|
||||
def status(self):
|
||||
|
|
|
@ -37,7 +37,7 @@ class Jail:
|
|||
# list had .index until 2.6
|
||||
_BACKENDS = ['pyinotify', 'gamin', 'polling', 'systemd']
|
||||
|
||||
def __init__(self, db, name, backend = "auto"):
|
||||
def __init__(self, name, backend = "auto", db=None):
|
||||
self.__db = db
|
||||
self.setName(name)
|
||||
self.__queue = Queue.Queue()
|
||||
|
@ -130,7 +130,8 @@ class Jail:
|
|||
|
||||
def putFailTicket(self, ticket):
|
||||
self.__queue.put(ticket)
|
||||
self.__db.addBan(self, ticket)
|
||||
if self.__db is not None:
|
||||
self.__db.addBan(self, ticket)
|
||||
|
||||
def getFailTicket(self):
|
||||
try:
|
||||
|
@ -142,8 +143,9 @@ class Jail:
|
|||
self.__filter.start()
|
||||
self.__action.start()
|
||||
# Restore any previous valid bans from the database
|
||||
for ticket in self.__db.getBans(self, self.__action.getBanTime()):
|
||||
self.__queue.put(ticket)
|
||||
if self.__db is not None:
|
||||
for ticket in self.__db.getBans(self, self.__action.getBanTime()):
|
||||
self.__queue.put(ticket)
|
||||
logSys.info("Jail '%s' started" % self.__name)
|
||||
|
||||
def stop(self):
|
||||
|
|
|
@ -50,13 +50,13 @@ class Jails:
|
|||
# @param name The name of the jail
|
||||
# @param backend The backend to use
|
||||
|
||||
def add(self, db, name, backend):
|
||||
def add(self, name, backend, db=None):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
if self.__jails.has_key(name):
|
||||
raise DuplicateJailException(name)
|
||||
else:
|
||||
self.__jails[name] = Jail(db, name, backend)
|
||||
self.__jails[name] = Jail(name, backend, db=None)
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ class Server:
|
|||
self.__loggingLock = Lock()
|
||||
self.__lock = RLock()
|
||||
self.__jails = Jails()
|
||||
self.__db = None
|
||||
self.__daemon = daemon
|
||||
self.__transm = Transmitter(self)
|
||||
self.__asyncServer = AsyncServer(self.__transm)
|
||||
|
@ -51,9 +52,6 @@ class Server:
|
|||
# Set logging level
|
||||
self.setLogLevel(3)
|
||||
self.setLogTarget("STDOUT")
|
||||
|
||||
# Create database, initially in memory
|
||||
self.setDatabase(":memory:")
|
||||
|
||||
def __sigTERMhandler(self, signum, frame):
|
||||
logSys.debug("Caught signal %d. Exiting" % signum)
|
||||
|
@ -121,12 +119,14 @@ class Server:
|
|||
|
||||
|
||||
def addJail(self, name, backend):
|
||||
self.__jails.add(self.__db, name, backend)
|
||||
self.__db.addJail(self.__jails.get(name))
|
||||
self.__jails.add(name, backend, self.__db)
|
||||
if self.__db is not None:
|
||||
self.__db.addJail(self.__jails.get(name))
|
||||
|
||||
def delJail(self, name):
|
||||
self.__jails.remove(name)
|
||||
self.__db.delJailName(name)
|
||||
if self.__db is not None:
|
||||
self.__db.delJailName(name)
|
||||
|
||||
def startJail(self, name):
|
||||
try:
|
||||
|
@ -468,8 +468,11 @@ class Server:
|
|||
|
||||
def setDatabase(self, filename):
|
||||
if self.__jails.size() == 0:
|
||||
self.__db = Fail2BanDb(filename)
|
||||
self.__db.delAllJails()
|
||||
if filename.lower() == "none":
|
||||
self.__db = None
|
||||
else:
|
||||
self.__db = Fail2BanDb(filename)
|
||||
self.__db.delAllJails()
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Cannot change database when there are jails present")
|
||||
|
|
|
@ -116,10 +116,18 @@ class Transmitter:
|
|||
#Database
|
||||
elif name == "dbfile":
|
||||
self.__server.setDatabase(command[1])
|
||||
return self.__server.getDatabase().getFilename()
|
||||
db = self.__server.getDatabase()
|
||||
if db is None:
|
||||
return None
|
||||
else:
|
||||
return db.getFilename()
|
||||
elif name == "dbpurgeage":
|
||||
self.__server.getDatabase().setPurgeAge(command[1])
|
||||
return self.__server.getDatabase().getPurgeAge()
|
||||
db = self.__server.getDatabase()
|
||||
if db is None:
|
||||
return None
|
||||
else:
|
||||
db.setPurgeAge(command[1])
|
||||
return db.getPurgeAge()
|
||||
# Jail
|
||||
elif command[1] == "idle":
|
||||
if command[2] == "on":
|
||||
|
@ -266,9 +274,17 @@ class Transmitter:
|
|||
return self.__server.getLogTarget()
|
||||
#Database
|
||||
elif name == "dbfile":
|
||||
return self.__server.getDatabase().getFilename()
|
||||
db = self.__server.getDatabase()
|
||||
if db is None:
|
||||
return None
|
||||
else:
|
||||
return db.getFilename()
|
||||
elif name == "dbpurgeage":
|
||||
return self.__server.getDatabase().getPurgeAge()
|
||||
db = self.__server.getDatabase()
|
||||
if db is None:
|
||||
return None
|
||||
else:
|
||||
return db.getPurgeAge()
|
||||
# Filter
|
||||
elif command[1] == "logpath":
|
||||
return self.__server.getLogPath(name)
|
||||
|
|
|
@ -24,16 +24,12 @@ __license__ = "GPL"
|
|||
|
||||
from threading import Lock
|
||||
|
||||
from fail2ban.server.database import Fail2BanDb
|
||||
|
||||
class DummyJail(object):
|
||||
"""A simple 'jail' to suck in all the tickets generated by Filter's
|
||||
"""
|
||||
def __init__(self):
|
||||
self.lock = Lock()
|
||||
self.queue = []
|
||||
self.__db = Fail2BanDb(":memory:")
|
||||
self.__db.addJail(self)
|
||||
|
||||
def __len__(self):
|
||||
try:
|
||||
|
@ -69,5 +65,5 @@ class DummyJail(object):
|
|||
return "DummyJail #%s with %d tickets" % (id(self), len(self))
|
||||
|
||||
def getDatabase(self):
|
||||
return self.__db
|
||||
return None
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ from fail2ban.server.filter import FileFilter, DNSUtils
|
|||
from fail2ban.server.failmanager import FailManager
|
||||
from fail2ban.server.failmanager import FailManagerEmpty
|
||||
from fail2ban.server.mytime import MyTime
|
||||
from fail2ban.server.database import Fail2BanDb
|
||||
from fail2ban.tests.utils import setUpMyTime, tearDownMyTime
|
||||
|
||||
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
|
||||
|
@ -565,7 +564,7 @@ def get_monitor_failures_testcase(Filter_):
|
|||
# tail written before, so let's not copy anything yet
|
||||
#_copy_lines_between_files(GetFailures.FILENAME_01, self.name, n=100)
|
||||
# we should detect the failures
|
||||
self.assert_correct_last_attempt(GetFailures.FAILURES_01, count=3) # was needed if we write twice above
|
||||
self.assert_correct_last_attempt(GetFailures.FAILURES_01, count=6) # was needed if we write twice above
|
||||
|
||||
# now copy and get even more
|
||||
_copy_lines_between_files(GetFailures.FILENAME_01, self.file, n=100)
|
||||
|
@ -920,5 +919,5 @@ class JailTests(unittest.TestCase):
|
|||
def testSetBackend_gh83(self):
|
||||
# smoke test
|
||||
# Must not fail to initiate
|
||||
jail = Jail(Fail2BanDb(":memory:"), 'test', backend='polling')
|
||||
jail = Jail('test', backend='polling')
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import unittest, socket, time, tempfile, os, locale, sys
|
|||
|
||||
from fail2ban.server.server import Server
|
||||
from fail2ban.server.jail import Jail
|
||||
from fail2ban.server.database import Fail2BanDb
|
||||
from fail2ban.exceptions import UnknownJailException
|
||||
try:
|
||||
from fail2ban.server import filtersystemd
|
||||
|
@ -175,9 +174,23 @@ class Transmitter(TransmitterBase):
|
|||
self.setGetTestNOK("dbfile", tmpFilename)
|
||||
self.server.delJail(self.jailName)
|
||||
self.setGetTest("dbfile", tmpFilename)
|
||||
self.setGetTest("dbpurgeage", 600)
|
||||
self.setGetTest("dbpurgeage", "600", 600)
|
||||
self.setGetTestNOK("dbpurgeage", "LIZARD")
|
||||
|
||||
# Disable database
|
||||
self.assertEqual(self.transm.proceed(
|
||||
["set", "dbfile", "None"]),
|
||||
(0, None))
|
||||
self.assertEqual(self.transm.proceed(
|
||||
["get", "dbfile"]),
|
||||
(0, None))
|
||||
self.assertEqual(self.transm.proceed(
|
||||
["set", "dbpurgeage", "500"]),
|
||||
(0, None))
|
||||
self.assertEqual(self.transm.proceed(
|
||||
["get", "dbpurgeage"]),
|
||||
(0, None))
|
||||
|
||||
def testAddJail(self):
|
||||
jail2 = "TestJail2"
|
||||
jail3 = "TestJail3"
|
||||
|
@ -651,5 +664,5 @@ class JailTests(unittest.TestCase):
|
|||
def testLongName(self):
|
||||
# Just a smoke test for now
|
||||
longname = "veryveryverylongname"
|
||||
jail = Jail(Fail2BanDb(":memory:"), longname)
|
||||
jail = Jail(longname)
|
||||
self.assertEqual(jail.getName(), longname)
|
||||
|
|
Loading…
Reference in New Issue