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": ["string", None],
"actionstart_on_demand": ["string", None], "actionstart_on_demand": ["string", None],
"actionstop": ["string", None], "actionstop": ["string", None],
"actionflush": ["string", None],
"actionreload": ["string", None], "actionreload": ["string", None],
"actioncheck": ["string", None], "actioncheck": ["string", None],
"actionrepair": ["string", None], "actionrepair": ["string", None],

View File

@ -281,6 +281,8 @@ class CommandAction(ActionBase):
self.actioncheck = '' self.actioncheck = ''
## Command executed in order to restore sane environment in error case. ## Command executed in order to restore sane environment in error case.
self.actionrepair = '' 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. ## Command executed in order to stop the system.
self.actionstop = '' self.actionstop = ''
## Command executed in case of reloading action. ## Command executed in case of reloading action.
@ -447,6 +449,25 @@ class CommandAction(ActionBase):
if not self._processCmd('<actionunban>', aInfo): if not self._processCmd('<actionunban>', aInfo):
raise RuntimeError("Error unbanning %(ip)s" % 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): def stop(self):
"""Executes the "actionstop" command. """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 If actions specified, don't flush list - just execute unban for
given actions (reload, obsolete resp. removed actions). given actions (reload, obsolete resp. removed actions).
""" """
log = True
if actions is None: if actions is None:
logSys.debug("Flush ban list") logSys.debug("Flush ban list")
lst = self.__banManager.flushBanList() lst = self.__banManager.flushBanList()
else: else:
log = False
lst = iter(self.__banManager) lst = iter(self.__banManager)
cnt = 0 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: 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, actions=actions) self.__unBan(ticket, actions=actions, log=log)
cnt += 1 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, actions=None): def __unBan(self, ticket, actions=None, log=True):
"""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
@ -482,7 +494,7 @@ class Actions(JailThread, Mapping):
unbactions = actions unbactions = actions
ip = ticket.getIP() ip = ticket.getIP()
aInfo = self.__getActionInfo(ticket) aInfo = self.__getActionInfo(ticket)
if actions is None: if log:
logSys.notice("[%s] Unban %s", self._jail.name, aInfo["ip"]) logSys.notice("[%s] Unban %s", self._jail.name, aInfo["ip"])
for name, action in unbactions.iteritems(): for name, action in unbactions.iteritems():
try: try: