bulk unban: introduced new command `actionflush`: executed in order to flush all bans at once (e. g. by unban all, reload with removing action, stop, shutdown the system);

the actions having `actionflush` do not execute `actionunban` for each single ticket
pull/1743/head
sebres 2017-03-29 23:05:52 +02:00
parent 44a26c6159
commit a1e9cc552c
3 changed files with 37 additions and 3 deletions

View File

@ -40,6 +40,7 @@ class ActionReader(DefinitionInitConfigReader):
"actionstart": ["string", None],
"actionstart_on_demand": ["string", None],
"actionstop": ["string", None],
"actionflush": ["string", None],
"actionreload": ["string", None],
"actioncheck": ["string", None],
"actionrepair": ["string", None],

View File

@ -281,6 +281,8 @@ class CommandAction(ActionBase):
self.actioncheck = ''
## Command executed in order to restore sane environment in error case.
self.actionrepair = ''
## Command executed in order to flush all bans at once (e. g. by stop/shutdown the system).
self.actionflush = ''
## Command executed in order to stop the system.
self.actionstop = ''
## Command executed in case of reloading action.
@ -447,6 +449,25 @@ class CommandAction(ActionBase):
if not self._processCmd('<actionunban>', aInfo):
raise RuntimeError("Error unbanning %(ip)s" % aInfo)
def flush(self):
"""Executes the "actionflush" command.
Command executed in order to flush all bans at once (e. g. by stop/shutdown
the system), instead of unbunning of each single ticket.
Replaces the tags in the action command with actions properties
and executes the resulting command.
"""
family = []
# cumulate started families, if started on demand (conditional):
if self._startOnDemand:
for f in CommandAction.COND_FAMILIES:
if self.__started.get(f) == 1: # only real started:
family.append(f)
# if no started (on demand) actions:
if not family: return True
return self._executeOperation('<actionflush>', 'flushing', family=family)
def stop(self):
"""Executes the "actionstop" command.

View File

@ -447,25 +447,37 @@ class Actions(JailThread, Mapping):
If actions specified, don't flush list - just execute unban for
given actions (reload, obsolete resp. removed actions).
"""
log = True
if actions is None:
logSys.debug("Flush ban list")
lst = self.__banManager.flushBanList()
else:
log = False
lst = iter(self.__banManager)
cnt = 0
# first we'll execute flush for actions supporting this operation:
unbactions = {}
for name, action in (actions if actions is not None else self._actions).iteritems():
if hasattr(action, 'flush') and action.actionflush:
logSys.notice("[%s] Flush ticket(s) with %s", self._jail.name, name)
action.flush()
else:
unbactions[name] = action
actions = unbactions
# unban each ticket with non-flasheable actions:
for ticket in lst:
# delete ip from database also:
if db and self._jail.database is not None:
ip = str(ticket.getIP())
self._jail.database.delBan(self._jail, ip)
# unban ip:
self.__unBan(ticket, actions=actions)
self.__unBan(ticket, actions=actions, log=log)
cnt += 1
logSys.debug("Unbanned %s, %s ticket(s) in %r",
cnt, self.__banManager.size(), self._jail.name)
return cnt
def __unBan(self, ticket, actions=None):
def __unBan(self, ticket, actions=None, log=True):
"""Unbans host corresponding to the ticket.
Executes the actions in order to unban the host given in the
@ -482,7 +494,7 @@ class Actions(JailThread, Mapping):
unbactions = actions
ip = ticket.getIP()
aInfo = self.__getActionInfo(ticket)
if actions is None:
if log:
logSys.notice("[%s] Unban %s", self._jail.name, aInfo["ip"])
for name, action in unbactions.iteritems():
try: