mirror of https://github.com/fail2ban/fail2ban
temp commit: reload now supported actions and action reloading (parameters, unban obsolete removed actions, etc.)
parent
d1ef33cc45
commit
4fb511294e
|
@ -38,6 +38,7 @@ class ActionReader(DefinitionInitConfigReader):
|
||||||
_configOpts = {
|
_configOpts = {
|
||||||
"actionstart": ["string", None],
|
"actionstart": ["string", None],
|
||||||
"actionstop": ["string", None],
|
"actionstop": ["string", None],
|
||||||
|
"actionreload": ["string", None],
|
||||||
"actioncheck": ["string", None],
|
"actioncheck": ["string", None],
|
||||||
"actionrepair": ["string", None],
|
"actionrepair": ["string", None],
|
||||||
"actionban": ["string", None],
|
"actionban": ["string", None],
|
||||||
|
|
|
@ -201,6 +201,7 @@ class CommandAction(ActionBase):
|
||||||
----------
|
----------
|
||||||
actionban
|
actionban
|
||||||
actioncheck
|
actioncheck
|
||||||
|
actionreload
|
||||||
actionrepair
|
actionrepair
|
||||||
actionstart
|
actionstart
|
||||||
actionstop
|
actionstop
|
||||||
|
@ -210,24 +211,35 @@ class CommandAction(ActionBase):
|
||||||
|
|
||||||
_escapedTags = set(('matches', 'ipmatches', 'ipjailmatches'))
|
_escapedTags = set(('matches', 'ipmatches', 'ipjailmatches'))
|
||||||
|
|
||||||
timeout = 60
|
def clearAllParams(self):
|
||||||
## Command executed in order to initialize the system.
|
""" Clear all lists/dicts parameters (used by reloading)
|
||||||
actionstart = ''
|
"""
|
||||||
## Command executed when an IP address gets banned.
|
self.__init = 1
|
||||||
actionban = ''
|
try:
|
||||||
## Command executed when an IP address gets removed.
|
self.timeout = 60
|
||||||
actionunban = ''
|
## Command executed in order to initialize the system.
|
||||||
## Command executed in order to check requirements.
|
self.actionstart = ''
|
||||||
actioncheck = ''
|
## Command executed when an IP address gets banned.
|
||||||
## Command executed in order to restore sane environment in error case.
|
self.actionban = ''
|
||||||
actionrepair = ''
|
## Command executed when an IP address gets removed.
|
||||||
## Command executed in order to stop the system.
|
self.actionunban = ''
|
||||||
actionstop = ''
|
## Command executed in order to check requirements.
|
||||||
|
self.actioncheck = ''
|
||||||
|
## Command executed in order to restore sane environment in error case.
|
||||||
|
self.actionrepair = ''
|
||||||
|
## Command executed in order to stop the system.
|
||||||
|
self.actionstop = ''
|
||||||
|
## Command executed in case of reloading action.
|
||||||
|
self.actionreload = ''
|
||||||
|
finally:
|
||||||
|
self.__init = 0
|
||||||
|
|
||||||
def __init__(self, jail, name):
|
def __init__(self, jail, name):
|
||||||
super(CommandAction, self).__init__(jail, name)
|
super(CommandAction, self).__init__(jail, name)
|
||||||
|
self.__init = 1
|
||||||
self.__properties = None
|
self.__properties = None
|
||||||
self.__substCache = {}
|
self.__substCache = {}
|
||||||
|
self.clearAllParams()
|
||||||
self._logSys.debug("Created %s" % self.__class__)
|
self._logSys.debug("Created %s" % self.__class__)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -235,7 +247,7 @@ class CommandAction(ActionBase):
|
||||||
return NotImplemented # Standard checks
|
return NotImplemented # Standard checks
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if not name.startswith('_') and not callable(value):
|
if not name.startswith('_') and not self.__init and not callable(value):
|
||||||
# special case for some pasrameters:
|
# special case for some pasrameters:
|
||||||
if name in ('timeout', 'bantime'):
|
if name in ('timeout', 'bantime'):
|
||||||
value = str(MyTime.str2seconds(value))
|
value = str(MyTime.str2seconds(value))
|
||||||
|
@ -268,8 +280,8 @@ class CommandAction(ActionBase):
|
||||||
def _substCache(self):
|
def _substCache(self):
|
||||||
return self.__substCache
|
return self.__substCache
|
||||||
|
|
||||||
def start(self):
|
def _executeOperation(self, tag, operation):
|
||||||
"""Executes the "actionstart" command.
|
"""Executes the operation commands (like "actionstart", "actionstop", etc).
|
||||||
|
|
||||||
Replace the tags in the action command with actions properties
|
Replace the tags in the action command with actions properties
|
||||||
and executes the resulting command.
|
and executes the resulting command.
|
||||||
|
@ -278,20 +290,28 @@ class CommandAction(ActionBase):
|
||||||
res = True
|
res = True
|
||||||
try:
|
try:
|
||||||
# common (resp. ipv4):
|
# common (resp. ipv4):
|
||||||
startCmd = self.replaceTag('<actionstart>', self._properties,
|
startCmd = self.replaceTag(tag, self._properties,
|
||||||
conditional='family=inet4', cache=self.__substCache)
|
conditional='family=inet4', cache=self.__substCache)
|
||||||
if startCmd:
|
if startCmd:
|
||||||
res &= self.executeCmd(startCmd, self.timeout)
|
res &= self.executeCmd(startCmd, self.timeout)
|
||||||
# start ipv6 actions if available:
|
# start ipv6 actions if available:
|
||||||
if allowed_ipv6:
|
if allowed_ipv6:
|
||||||
startCmd6 = self.replaceTag('<actionstart>', self._properties,
|
startCmd6 = self.replaceTag(tag, self._properties,
|
||||||
conditional='family=inet6', cache=self.__substCache)
|
conditional='family=inet6', cache=self.__substCache)
|
||||||
if startCmd6 and startCmd6 != startCmd:
|
if startCmd6 and startCmd6 != startCmd:
|
||||||
res &= self.executeCmd(startCmd6, self.timeout)
|
res &= self.executeCmd(startCmd6, self.timeout)
|
||||||
if not res:
|
if not res:
|
||||||
raise RuntimeError("Error starting action %s/%s" % (self._jail, self._name,))
|
raise RuntimeError("Error %s action %s/%s" % (operation, self._jail, self._name,))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise RuntimeError("Error starting action %s/%s: %r" % (self._jail, self._name, e))
|
raise RuntimeError("Error %s action %s/%s: %r" % (operation, self._jail, self._name, e))
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""Executes the "actionstart" command.
|
||||||
|
|
||||||
|
Replace the tags in the action command with actions properties
|
||||||
|
and executes the resulting command.
|
||||||
|
"""
|
||||||
|
return self._executeOperation('<actionstart>', 'starting')
|
||||||
|
|
||||||
def ban(self, aInfo):
|
def ban(self, aInfo):
|
||||||
"""Executes the "actionban" command.
|
"""Executes the "actionban" command.
|
||||||
|
@ -329,20 +349,20 @@ class CommandAction(ActionBase):
|
||||||
Replaces the tags in the action command with actions properties
|
Replaces the tags in the action command with actions properties
|
||||||
and executes the resulting command.
|
and executes the resulting command.
|
||||||
"""
|
"""
|
||||||
res = True
|
return self._executeOperation('<actionstop>', 'stopping')
|
||||||
# common (resp. ipv4):
|
|
||||||
stopCmd = self.replaceTag('<actionstop>', self._properties,
|
def reload(self, **kwargs):
|
||||||
conditional='family=inet4', cache=self.__substCache)
|
"""Executes the "actionreload" command.
|
||||||
if stopCmd:
|
|
||||||
res &= self.executeCmd(stopCmd, self.timeout)
|
Parameters
|
||||||
# ipv6 actions if available:
|
----------
|
||||||
if allowed_ipv6:
|
kwargs : dict
|
||||||
stopCmd6 = self.replaceTag('<actionstop>', self._properties,
|
Currently unused, because CommandAction do not support initOpts
|
||||||
conditional='family=inet6', cache=self.__substCache)
|
|
||||||
if stopCmd6 and stopCmd6 != stopCmd:
|
Replaces the tags in the action command with actions properties
|
||||||
res &= self.executeCmd(stopCmd6, self.timeout)
|
and executes the resulting command.
|
||||||
if not res:
|
"""
|
||||||
raise RuntimeError("Error stopping action")
|
return self._executeOperation('<actionreload>', 'reloading')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def substituteRecursiveTags(cls, inptags, conditional=''):
|
def substituteRecursiveTags(cls, inptags, conditional=''):
|
||||||
|
|
|
@ -36,7 +36,7 @@ from collections import Mapping
|
||||||
try:
|
try:
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
except ImportError:
|
except ImportError:
|
||||||
OrderedDict = None
|
OrderedDict = dict
|
||||||
|
|
||||||
from .banmanager import BanManager
|
from .banmanager import BanManager
|
||||||
from .jailthread import JailThread
|
from .jailthread import JailThread
|
||||||
|
@ -81,14 +81,11 @@ class Actions(JailThread, Mapping):
|
||||||
JailThread.__init__(self)
|
JailThread.__init__(self)
|
||||||
## The jail which contains this action.
|
## The jail which contains this action.
|
||||||
self._jail = jail
|
self._jail = jail
|
||||||
if OrderedDict is not None:
|
self._actions = OrderedDict()
|
||||||
self._actions = OrderedDict()
|
|
||||||
else:
|
|
||||||
self._actions = dict()
|
|
||||||
## The ban manager.
|
## The ban manager.
|
||||||
self.__banManager = BanManager()
|
self.__banManager = BanManager()
|
||||||
|
|
||||||
def add(self, name, pythonModule=None, initOpts=None):
|
def add(self, name, pythonModule=None, initOpts=None, reload=False):
|
||||||
"""Adds a new action.
|
"""Adds a new action.
|
||||||
|
|
||||||
Add a new action if not already present, defaulting to standard
|
Add a new action if not already present, defaulting to standard
|
||||||
|
@ -116,7 +113,17 @@ class Actions(JailThread, Mapping):
|
||||||
"""
|
"""
|
||||||
# Check is action name already exists
|
# Check is action name already exists
|
||||||
if name in self._actions:
|
if name in self._actions:
|
||||||
raise ValueError("Action %s already exists" % name)
|
if not reload:
|
||||||
|
raise ValueError("Action %s already exists" % name)
|
||||||
|
# don't create new action if reload supported:
|
||||||
|
action = self._actions[name]
|
||||||
|
if hasattr(action, 'reload'):
|
||||||
|
# don't execute reload right now, reload after all parameters are actualized
|
||||||
|
if hasattr(action, 'clearAllParams'):
|
||||||
|
action.clearAllParams()
|
||||||
|
self._reload_actions[name] = initOpts
|
||||||
|
return
|
||||||
|
## Create new action:
|
||||||
if pythonModule is None:
|
if pythonModule is None:
|
||||||
action = CommandAction(self._jail, name)
|
action = CommandAction(self._jail, name)
|
||||||
else:
|
else:
|
||||||
|
@ -138,6 +145,27 @@ class Actions(JailThread, Mapping):
|
||||||
action = customActionModule.Action(self._jail, name, **initOpts)
|
action = customActionModule.Action(self._jail, name, **initOpts)
|
||||||
self._actions[name] = action
|
self._actions[name] = action
|
||||||
|
|
||||||
|
def reload(self, begin=True):
|
||||||
|
""" Begin or end of reloading resp. refreshing of all parameters
|
||||||
|
"""
|
||||||
|
if begin:
|
||||||
|
self._reload_actions = dict()
|
||||||
|
else:
|
||||||
|
if hasattr(self, '_reload_actions'):
|
||||||
|
# reload actions after all parameters set via stream:
|
||||||
|
for name, initOpts in self._reload_actions.iteritems():
|
||||||
|
if name in self._actions:
|
||||||
|
self._actions[name].reload(**initOpts if initOpts else {})
|
||||||
|
# remove obsolete actions (untouched by reload process):
|
||||||
|
delacts = OrderedDict((name, action) for name, action in self._actions.iteritems()
|
||||||
|
if name not in self._reload_actions)
|
||||||
|
if len(delacts):
|
||||||
|
# unban all tickets using remove action only:
|
||||||
|
self.__flushBan(db=False, actions=delacts)
|
||||||
|
# stop and remove it:
|
||||||
|
self.stopActions(actions=delacts)
|
||||||
|
delattr(self, '_reload_actions')
|
||||||
|
|
||||||
def __getitem__(self, name):
|
def __getitem__(self, name):
|
||||||
try:
|
try:
|
||||||
return self._actions[name]
|
return self._actions[name]
|
||||||
|
@ -215,6 +243,24 @@ class Actions(JailThread, Mapping):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def stopActions(self, actions=None):
|
||||||
|
"""Stops the actions in reverse sequence (optionally filtered)
|
||||||
|
"""
|
||||||
|
if actions is None:
|
||||||
|
actions = self._actions
|
||||||
|
revactions = actions.items()
|
||||||
|
revactions.reverse()
|
||||||
|
for name, action in revactions:
|
||||||
|
try:
|
||||||
|
action.stop()
|
||||||
|
except Exception as e:
|
||||||
|
logSys.error("Failed to stop jail '%s' action '%s': %s",
|
||||||
|
self._jail.name, name, e,
|
||||||
|
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||||
|
del self._actions[name]
|
||||||
|
logSys.debug("%s: action %s terminated", self._jail.name, name)
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Main loop for Threading.
|
"""Main loop for Threading.
|
||||||
|
|
||||||
|
@ -239,18 +285,9 @@ class Actions(JailThread, Mapping):
|
||||||
continue
|
continue
|
||||||
if not Utils.wait_for(self.__checkBan, self.sleeptime):
|
if not Utils.wait_for(self.__checkBan, self.sleeptime):
|
||||||
self.__checkUnBan()
|
self.__checkUnBan()
|
||||||
|
|
||||||
self.__flushBan()
|
self.__flushBan()
|
||||||
|
self.stopActions()
|
||||||
actions = self._actions.items()
|
|
||||||
actions.reverse()
|
|
||||||
for name, action in actions:
|
|
||||||
try:
|
|
||||||
action.stop()
|
|
||||||
except Exception as e:
|
|
||||||
logSys.error("Failed to stop jail '%s' action '%s': %s",
|
|
||||||
self._jail.name, name, e,
|
|
||||||
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
|
||||||
logSys.debug(self._jail.name + ": action terminated")
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __getBansMerged(self, mi, overalljails=False):
|
def __getBansMerged(self, mi, overalljails=False):
|
||||||
|
@ -355,26 +392,33 @@ class Actions(JailThread, Mapping):
|
||||||
cnt, self.__banManager.size(), self._jail.name)
|
cnt, self.__banManager.size(), self._jail.name)
|
||||||
return cnt
|
return cnt
|
||||||
|
|
||||||
def __flushBan(self, db=False):
|
def __flushBan(self, db=False, actions=None):
|
||||||
"""Flush the ban list.
|
"""Flush the ban list.
|
||||||
|
|
||||||
Unban all IP address which are still in the banning list.
|
Unban all IP address which are still in the banning list.
|
||||||
|
|
||||||
|
If actions specified, don't flush list - just execute unban for
|
||||||
|
given actions (reload, obsolete resp. removed actions).
|
||||||
"""
|
"""
|
||||||
logSys.debug("Flush ban list")
|
if actions is None:
|
||||||
lst = self.__banManager.flushBanList()
|
logSys.debug("Flush ban list")
|
||||||
|
lst = self.__banManager.flushBanList()
|
||||||
|
else:
|
||||||
|
lst = iter(self.__banManager)
|
||||||
|
cnt = 0
|
||||||
for ticket in lst:
|
for ticket in lst:
|
||||||
# delete ip from database also:
|
# delete ip from database also:
|
||||||
if db and self._jail.database is not None:
|
if db and self._jail.database is not None:
|
||||||
ip = str(ticket.getIP())
|
ip = str(ticket.getIP())
|
||||||
self._jail.database.delBan(self._jail, ip)
|
self._jail.database.delBan(self._jail, ip)
|
||||||
# unban ip:
|
# unban ip:
|
||||||
self.__unBan(ticket)
|
self.__unBan(ticket, actions=actions)
|
||||||
cnt = len(lst)
|
cnt += 1
|
||||||
logSys.debug("Unbanned %s, %s ticket(s) in %r",
|
logSys.debug("Unbanned %s, %s ticket(s) in %r",
|
||||||
cnt, self.__banManager.size(), self._jail.name)
|
cnt, self.__banManager.size(), self._jail.name)
|
||||||
return cnt
|
return cnt
|
||||||
|
|
||||||
def __unBan(self, ticket):
|
def __unBan(self, ticket, actions=None):
|
||||||
"""Unbans host corresponding to the ticket.
|
"""Unbans host corresponding to the ticket.
|
||||||
|
|
||||||
Executes the actions in order to unban the host given in the
|
Executes the actions in order to unban the host given in the
|
||||||
|
@ -385,13 +429,15 @@ class Actions(JailThread, Mapping):
|
||||||
ticket : FailTicket
|
ticket : FailTicket
|
||||||
Ticket of failures of which to unban
|
Ticket of failures of which to unban
|
||||||
"""
|
"""
|
||||||
|
if actions is None:
|
||||||
|
actions = self._actions
|
||||||
aInfo = dict()
|
aInfo = dict()
|
||||||
aInfo["ip"] = ticket.getIP()
|
aInfo["ip"] = ticket.getIP()
|
||||||
aInfo["failures"] = ticket.getAttempt()
|
aInfo["failures"] = ticket.getAttempt()
|
||||||
aInfo["time"] = ticket.getTime()
|
aInfo["time"] = ticket.getTime()
|
||||||
aInfo["matches"] = "".join(ticket.getMatches())
|
aInfo["matches"] = "".join(ticket.getMatches())
|
||||||
logSys.notice("[%s] Unban %s" % (self._jail.name, aInfo["ip"]))
|
logSys.notice("[%s] Unban %s" % (self._jail.name, aInfo["ip"]))
|
||||||
for name, action in self._actions.iteritems():
|
for name, action in actions.iteritems():
|
||||||
try:
|
try:
|
||||||
action.unban(aInfo.copy())
|
action.unban(aInfo.copy())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
@ -106,6 +106,15 @@ class BanManager:
|
||||||
with self.__lock:
|
with self.__lock:
|
||||||
return self.__banList.keys()
|
return self.__banList.keys()
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns a iterator to ban list (used in reload, so idle).
|
||||||
|
#
|
||||||
|
# @return ban list iterator
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
with self.__lock:
|
||||||
|
return self.__banList.itervalues()
|
||||||
|
|
||||||
##
|
##
|
||||||
# Returns normalized value
|
# Returns normalized value
|
||||||
#
|
#
|
||||||
|
|
|
@ -604,16 +604,14 @@ class Fail2BanDb(object):
|
||||||
results = list(self._getCurrentBans(jail=jail, ip=ip, forbantime=forbantime, fromtime=fromtime))
|
results = list(self._getCurrentBans(jail=jail, ip=ip, forbantime=forbantime, fromtime=fromtime))
|
||||||
|
|
||||||
if results:
|
if results:
|
||||||
matches = []
|
|
||||||
failures = 0
|
|
||||||
for banip, timeofban, data in results:
|
for banip, timeofban, data in results:
|
||||||
#TODO: Implement data parts once arbitrary match keys completed
|
|
||||||
ticket = FailTicket(banip, timeofban, matches)
|
|
||||||
ticket.setAttempt(failures)
|
|
||||||
matches = []
|
matches = []
|
||||||
failures = 0
|
failures = 0
|
||||||
matches.extend(data['matches'])
|
if isinstance(data['matches'], list):
|
||||||
failures += data['failures']
|
matches.extend(data['matches'])
|
||||||
|
if data['failures']:
|
||||||
|
failures += data['failures']
|
||||||
|
ticket = FailTicket(banip, timeofban, matches)
|
||||||
ticket.setAttempt(failures)
|
ticket.setAttempt(failures)
|
||||||
tickets.append(ticket)
|
tickets.append(ticket)
|
||||||
|
|
||||||
|
|
|
@ -117,14 +117,11 @@ class Filter(JailThread):
|
||||||
self._reload_logs = dict((k, 1) for k in self.getLogPaths())
|
self._reload_logs = dict((k, 1) for k in self.getLogPaths())
|
||||||
else:
|
else:
|
||||||
if hasattr(self, '_reload_logs'):
|
if hasattr(self, '_reload_logs'):
|
||||||
dellogs = dict()
|
|
||||||
# if it was not reloaded - remove obsolete log file:
|
# if it was not reloaded - remove obsolete log file:
|
||||||
for path in self._reload_logs:
|
for path in self._reload_logs:
|
||||||
self.delLogPath(path)
|
self.delLogPath(path)
|
||||||
delattr(self, '_reload_logs')
|
delattr(self, '_reload_logs')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Add a regular expression which matches the failure.
|
# Add a regular expression which matches the failure.
|
||||||
#
|
#
|
||||||
|
|
|
@ -267,6 +267,7 @@ class Server:
|
||||||
jail.idle = True
|
jail.idle = True
|
||||||
self.__reload_state[jn] = jail
|
self.__reload_state[jn] = jail
|
||||||
jail.filter.reload(begin=True)
|
jail.filter.reload(begin=True)
|
||||||
|
jail.actions.reload(begin=True)
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# end reload, all affected (or new) jails have already all new parameters (via stream) and (re)started:
|
# end reload, all affected (or new) jails have already all new parameters (via stream) and (re)started:
|
||||||
|
@ -280,6 +281,7 @@ class Server:
|
||||||
else:
|
else:
|
||||||
# commit (reload was finished):
|
# commit (reload was finished):
|
||||||
jail.filter.reload(begin=False)
|
jail.filter.reload(begin=False)
|
||||||
|
jail.actions.reload(begin=False)
|
||||||
for jn in deljails:
|
for jn in deljails:
|
||||||
self.delJail(jn)
|
self.delJail(jn)
|
||||||
self.__reload_state = {}
|
self.__reload_state = {}
|
||||||
|
@ -416,7 +418,9 @@ class Server:
|
||||||
|
|
||||||
# Action
|
# Action
|
||||||
def addAction(self, name, value, *args):
|
def addAction(self, name, value, *args):
|
||||||
self.__jails[name].actions.add(value, *args)
|
## create (or reload) jail action:
|
||||||
|
self.__jails[name].actions.add(value, *args,
|
||||||
|
reload=name in self.__reload_state)
|
||||||
|
|
||||||
def getActions(self, name):
|
def getActions(self, name):
|
||||||
return self.__jails[name].actions
|
return self.__jails[name].actions
|
||||||
|
|
|
@ -677,6 +677,20 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
||||||
test2log = pjoin(tmp, "test2.log")
|
test2log = pjoin(tmp, "test2.log")
|
||||||
test3log = pjoin(tmp, "test3.log")
|
test3log = pjoin(tmp, "test3.log")
|
||||||
|
|
||||||
|
os.mkdir(pjoin(cfg, "action.d"))
|
||||||
|
def _write_action_cfg(actname="test-action1"):
|
||||||
|
fn = pjoin(cfg, "action.d", "%s.conf" % actname)
|
||||||
|
_write_file(fn, "w",
|
||||||
|
"[Definition]",
|
||||||
|
"actionstart = echo '[<name>] %s: ** start'" % actname,
|
||||||
|
"actionstop = echo '[<name>] %s: -- unban <ip>'" % actname,
|
||||||
|
"actionreload = echo '[<name>] %s: ** reload'" % actname,
|
||||||
|
"actionban = echo '[<name>] %s: ++ ban <ip>'" % actname,
|
||||||
|
"actionunban = echo '[<name>] %s: // stop'" % actname,
|
||||||
|
)
|
||||||
|
if DefLogSys.level < logging.DEBUG: # if HEAVYDEBUG
|
||||||
|
_out_file(fn)
|
||||||
|
|
||||||
def _write_jail_cfg(enabled=[1, 2]):
|
def _write_jail_cfg(enabled=[1, 2]):
|
||||||
_write_file(pjoin(cfg, "jail.conf"), "w",
|
_write_file(pjoin(cfg, "jail.conf"), "w",
|
||||||
"[INCLUDES]", "",
|
"[INCLUDES]", "",
|
||||||
|
@ -686,7 +700,9 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
||||||
"findtime = 10m",
|
"findtime = 10m",
|
||||||
"failregex = ^\s*failure (401|403) from <HOST>",
|
"failregex = ^\s*failure (401|403) from <HOST>",
|
||||||
"",
|
"",
|
||||||
"[test-jail1]", "backend = polling", "filter =", "action =",
|
"[test-jail1]", "backend = polling", "filter =",
|
||||||
|
"action = test-action1[name='%(__name__)s']",
|
||||||
|
" test-action2[name='%(__name__)s']",
|
||||||
"logpath = " + test1log,
|
"logpath = " + test1log,
|
||||||
" " + test2log if 2 in enabled else "",
|
" " + test2log if 2 in enabled else "",
|
||||||
" " + test3log if 2 in enabled else "",
|
" " + test3log if 2 in enabled else "",
|
||||||
|
@ -701,6 +717,10 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
||||||
if DefLogSys.level < logging.DEBUG: # if HEAVYDEBUG
|
if DefLogSys.level < logging.DEBUG: # if HEAVYDEBUG
|
||||||
_out_file(pjoin(cfg, "jail.conf"))
|
_out_file(pjoin(cfg, "jail.conf"))
|
||||||
|
|
||||||
|
# create default test actions:
|
||||||
|
_write_action_cfg(actname="test-action1")
|
||||||
|
_write_action_cfg(actname="test-action2")
|
||||||
|
|
||||||
_write_jail_cfg(enabled=[1])
|
_write_jail_cfg(enabled=[1])
|
||||||
_write_file(test1log, "w", *((str(int(MyTime.time())) + " failure 401 from 192.0.2.1: test 1",) * 3))
|
_write_file(test1log, "w", *((str(int(MyTime.time())) + " failure 401 from 192.0.2.1: test 1",) * 3))
|
||||||
_write_file(test2log, "w")
|
_write_file(test2log, "w")
|
||||||
|
@ -737,6 +757,11 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
||||||
self.assertLogged(
|
self.assertLogged(
|
||||||
"Added logfile: %r" % test2log,
|
"Added logfile: %r" % test2log,
|
||||||
"Added logfile: %r" % test3log, all=True)
|
"Added logfile: %r" % test3log, all=True)
|
||||||
|
# test actions reloaded:
|
||||||
|
self.assertLogged(
|
||||||
|
"echo '[test-jail1] test-action1: ** reload' -- returned successfully",
|
||||||
|
"echo '[test-jail1] test-action2: ** reload' -- returned successfully", all=True)
|
||||||
|
|
||||||
# test 1 new jail:
|
# test 1 new jail:
|
||||||
self.assertLogged(
|
self.assertLogged(
|
||||||
"Creating new jail 'test-jail2'",
|
"Creating new jail 'test-jail2'",
|
||||||
|
|
Loading…
Reference in New Issue