Merge pull request #1616 from sebres/fix-1194

[fix-gh-1194] Fixed misleading errors logged from ignorecommand in success case on retcode 1
pull/1618/head
Serg G. Brester 2016-11-21 17:15:16 +01:00 committed by GitHub
commit 44fddc102d
6 changed files with 19 additions and 8 deletions

View File

@ -28,6 +28,7 @@ TODO: implementing of options resp. other tasks from PR #1346
* Pyinotify-backend: stability fix for sporadically errors in multi-threaded * Pyinotify-backend: stability fix for sporadically errors in multi-threaded
environment (without lock) environment (without lock)
* Fixed sporadically error in testCymruInfoNxdomain, because of unsorted values * Fixed sporadically error in testCymruInfoNxdomain, because of unsorted values
* Misleading errors logged from ignorecommand in success case on retcode 1 (gh-1194)
### New Features ### New Features
* IPv6 support: * IPv6 support:

View File

@ -584,7 +584,7 @@ class CommandAction(ActionBase):
return self.executeCmd(realCmd, self.timeout) return self.executeCmd(realCmd, self.timeout)
@staticmethod @staticmethod
def executeCmd(realCmd, timeout=60): def executeCmd(realCmd, timeout=60, **kwargs):
"""Executes a command. """Executes a command.
Parameters Parameters
@ -613,6 +613,6 @@ class CommandAction(ActionBase):
_cmd_lock.acquire() _cmd_lock.acquire()
try: try:
return Utils.executeCmd(realCmd, timeout, shell=True, output=False) return Utils.executeCmd(realCmd, timeout, shell=True, output=False, **kwargs)
finally: finally:
_cmd_lock.release() _cmd_lock.release()

View File

@ -455,7 +455,8 @@ class Filter(JailThread):
if self.__ignoreCommand: if self.__ignoreCommand:
command = CommandAction.replaceTag(self.__ignoreCommand, { 'ip': ip } ) command = CommandAction.replaceTag(self.__ignoreCommand, { 'ip': ip } )
logSys.debug('ignore command: ' + command) logSys.debug('ignore command: ' + command)
ret_ignore = CommandAction.executeCmd(command) ret, ret_ignore = CommandAction.executeCmd(command, success_codes=(0, 1))
ret_ignore = ret and ret_ignore == 0
self.logIgnoreIp(ip, log_ignore and ret_ignore, ignore_source="command") self.logIgnoreIp(ip, log_ignore and ret_ignore, ignore_source="command")
return ret_ignore return ret_ignore

View File

@ -110,7 +110,7 @@ class Utils():
return flags return flags
@staticmethod @staticmethod
def executeCmd(realCmd, timeout=60, shell=True, output=False, tout_kill_tree=True): def executeCmd(realCmd, timeout=60, shell=True, output=False, tout_kill_tree=True, success_codes=(0,)):
"""Executes a command. """Executes a command.
Parameters Parameters
@ -178,7 +178,7 @@ class Utils():
if not popen: if not popen:
return False if not output else (False, stdout, stderr, retcode) return False if not output else (False, stdout, stderr, retcode)
std_level = retcode == 0 and logging.DEBUG or logging.ERROR std_level = logging.DEBUG if retcode in success_codes else logging.ERROR
# if we need output (to return or to log it): # if we need output (to return or to log it):
if output or std_level >= logSys.getEffectiveLevel(): if output or std_level >= logSys.getEffectiveLevel():
# if was timeouted (killed/terminated) - to prevent waiting, set std handles to non-blocking mode. # if was timeouted (killed/terminated) - to prevent waiting, set std handles to non-blocking mode.
@ -208,8 +208,8 @@ class Utils():
popen.stderr.close() popen.stderr.close()
success = False success = False
if retcode == 0: if retcode in success_codes:
logSys.debug("%-.40s -- returned successfully", realCmd) logSys.debug("%-.40s -- returned successfully %i", realCmd, retcode)
success = True success = True
elif retcode is None: elif retcode is None:
logSys.error("%-.40s -- unable to kill PID %i", realCmd, popen.pid) logSys.error("%-.40s -- unable to kill PID %i", realCmd, popen.pid)
@ -223,7 +223,9 @@ class Utils():
logSys.error("%-.40s -- returned %i", realCmd, retcode) logSys.error("%-.40s -- returned %i", realCmd, retcode)
if msg: if msg:
logSys.info("HINT on %i: %s", retcode, msg % locals()) logSys.info("HINT on %i: %s", retcode, msg % locals())
return success if not output else (success, stdout, stderr, retcode) if output:
return success, stdout, stderr, retcode
return success if len(success_codes) == 1 else (success, retcode)
@staticmethod @staticmethod
def wait_for(cond, timeout, interval=None): def wait_for(cond, timeout, interval=None):

View File

@ -1,5 +1,8 @@
#!/usr/bin/env fail2ban-python #!/usr/bin/env fail2ban-python
import sys import sys
if len(sys.argv) != 2 or sys.argv[1] == "":
sys.stderr.write('usage: ignorecommand IP')
exit(10)
if sys.argv[1] == "10.0.0.1": if sys.argv[1] == "10.0.0.1":
exit(0) exit(0)
exit(1) exit(1)

View File

@ -377,6 +377,10 @@ class IgnoreIP(LogCaptureTestCase):
self.filter.setIgnoreCommand(sys.executable + ' ' + os.path.join(TEST_FILES_DIR, "ignorecommand.py <ip>")) self.filter.setIgnoreCommand(sys.executable + ' ' + os.path.join(TEST_FILES_DIR, "ignorecommand.py <ip>"))
self.assertTrue(self.filter.inIgnoreIPList("10.0.0.1")) self.assertTrue(self.filter.inIgnoreIPList("10.0.0.1"))
self.assertFalse(self.filter.inIgnoreIPList("10.0.0.0")) self.assertFalse(self.filter.inIgnoreIPList("10.0.0.0"))
self.assertLogged("returned successfully 0", "returned successfully 1", all=True)
self.pruneLog()
self.assertFalse(self.filter.inIgnoreIPList(""))
self.assertLogged("usage: ignorecommand IP", "returned 10", all=True)
def testIgnoreCauseOK(self): def testIgnoreCauseOK(self):
ip = "93.184.216.34" ip = "93.184.216.34"