mirror of https://github.com/fail2ban/fail2ban
badips: try to fix sporadic test errors if badips-server timed out resp. not available (502 bad gateway or similar).
parent
414469c102
commit
8069eef50c
|
@ -114,6 +114,15 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable
|
||||||
except Exception as e: # pragma: no cover
|
except Exception as e: # pragma: no cover
|
||||||
return False, e
|
return False, e
|
||||||
|
|
||||||
|
def logError(self, response, what=''): # pragma: no cover - sporadical (502: Bad Gateway, etc)
|
||||||
|
messages = {}
|
||||||
|
try:
|
||||||
|
messages = json.loads(response.read().decode('utf-8'))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self._logSys.error(
|
||||||
|
"%s. badips.com response: '%s'", what,
|
||||||
|
messages.get('err', 'Unknown'))
|
||||||
|
|
||||||
def getCategories(self, incParents=False):
|
def getCategories(self, incParents=False):
|
||||||
"""Get badips.com categories.
|
"""Get badips.com categories.
|
||||||
|
@ -133,11 +142,8 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable
|
||||||
try:
|
try:
|
||||||
response = urlopen(
|
response = urlopen(
|
||||||
self._Request("/".join([self._badips, "get", "categories"])), timeout=self.timeout)
|
self._Request("/".join([self._badips, "get", "categories"])), timeout=self.timeout)
|
||||||
except HTTPError as response:
|
except HTTPError as response: # pragma: no cover
|
||||||
messages = json.loads(response.read().decode('utf-8'))
|
self.logError(response, "Failed to fetch categories")
|
||||||
self._logSys.error(
|
|
||||||
"Failed to fetch categories. badips.com response: '%s'",
|
|
||||||
messages['err'])
|
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
response_json = json.loads(response.read().decode('utf-8'))
|
response_json = json.loads(response.read().decode('utf-8'))
|
||||||
|
@ -188,11 +194,8 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable
|
||||||
url = "&".join([url, urlencode({'key': key})])
|
url = "&".join([url, urlencode({'key': key})])
|
||||||
self._logSys.debug('badips.com: get list, url: %r', url)
|
self._logSys.debug('badips.com: get list, url: %r', url)
|
||||||
response = urlopen(self._Request(url), timeout=self.timeout)
|
response = urlopen(self._Request(url), timeout=self.timeout)
|
||||||
except HTTPError as response:
|
except HTTPError as response: # pragma: no cover
|
||||||
messages = json.loads(response.read().decode('utf-8'))
|
self.logError(response, "Failed to fetch bad IP list")
|
||||||
self._logSys.error(
|
|
||||||
"Failed to fetch bad IP list. badips.com response: '%s'",
|
|
||||||
messages['err'])
|
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
return set(response.read().decode('utf-8').split())
|
return set(response.read().decode('utf-8').split())
|
||||||
|
@ -286,7 +289,7 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable
|
||||||
exc_info=self._logSys.getEffectiveLevel()<=logging.DEBUG)
|
exc_info=self._logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||||
else:
|
else:
|
||||||
self._bannedips.add(ip)
|
self._bannedips.add(ip)
|
||||||
self._logSys.info(
|
self._logSys.debug(
|
||||||
"Banned IP %s for jail '%s' with action '%s'",
|
"Banned IP %s for jail '%s' with action '%s'",
|
||||||
ip, self._jail.name, self.banaction)
|
ip, self._jail.name, self.banaction)
|
||||||
|
|
||||||
|
@ -306,7 +309,7 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable
|
||||||
ip, self._jail.name, self.banaction, e,
|
ip, self._jail.name, self.banaction, e,
|
||||||
exc_info=self._logSys.getEffectiveLevel()<=logging.DEBUG)
|
exc_info=self._logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||||
else:
|
else:
|
||||||
self._logSys.info(
|
self._logSys.debug(
|
||||||
"Unbanned IP %s for jail '%s' with action '%s'",
|
"Unbanned IP %s for jail '%s' with action '%s'",
|
||||||
ip, self._jail.name, self.banaction)
|
ip, self._jail.name, self.banaction)
|
||||||
finally:
|
finally:
|
||||||
|
@ -338,7 +341,7 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable
|
||||||
# Add new IPs which are now listed
|
# Add new IPs which are now listed
|
||||||
self._banIPs(ips - self._bannedips)
|
self._banIPs(ips - self._bannedips)
|
||||||
|
|
||||||
self._logSys.info(
|
self._logSys.debug(
|
||||||
"Updated IPs for jail '%s'. Update again in %i seconds",
|
"Updated IPs for jail '%s'. Update again in %i seconds",
|
||||||
self._jail.name, self.updateperiod)
|
self._jail.name, self.updateperiod)
|
||||||
finally:
|
finally:
|
||||||
|
@ -374,15 +377,12 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable
|
||||||
url = "?".join([url, urlencode({'key': self.key})])
|
url = "?".join([url, urlencode({'key': self.key})])
|
||||||
self._logSys.debug('badips.com: ban, url: %r', url)
|
self._logSys.debug('badips.com: ban, url: %r', url)
|
||||||
response = urlopen(self._Request(url), timeout=self.timeout)
|
response = urlopen(self._Request(url), timeout=self.timeout)
|
||||||
except HTTPError as response:
|
except HTTPError as response: # pragma: no cover
|
||||||
messages = json.loads(response.read().decode('utf-8'))
|
self.logError(response, "Failed to ban")
|
||||||
self._logSys.error(
|
|
||||||
"Response from badips.com report: '%s'",
|
|
||||||
messages['err'])
|
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
messages = json.loads(response.read().decode('utf-8'))
|
messages = json.loads(response.read().decode('utf-8'))
|
||||||
self._logSys.info(
|
self._logSys.debug(
|
||||||
"Response from badips.com report: '%s'",
|
"Response from badips.com report: '%s'",
|
||||||
messages['suc'])
|
messages['suc'])
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
import sys
|
import sys
|
||||||
|
from functools import wraps
|
||||||
from socket import timeout
|
from socket import timeout
|
||||||
from ssl import SSLError
|
from ssl import SSLError
|
||||||
|
|
||||||
|
@ -28,6 +29,25 @@ from ..dummyjail import DummyJail
|
||||||
from ..servertestcase import IPAddr
|
from ..servertestcase import IPAddr
|
||||||
from ..utils import LogCaptureTestCase, CONFIG_DIR
|
from ..utils import LogCaptureTestCase, CONFIG_DIR
|
||||||
|
|
||||||
|
if sys.version_info >= (3, ):
|
||||||
|
from urllib.error import HTTPError, URLError
|
||||||
|
else:
|
||||||
|
from urllib2 import HTTPError, URLError
|
||||||
|
|
||||||
|
def skip_if_not_available(f):
|
||||||
|
"""Helper to decorate tests to skip in case of timeout/http-errors like "502 bad gateway".
|
||||||
|
"""
|
||||||
|
@wraps(f)
|
||||||
|
def wrapper(self, *args):
|
||||||
|
try:
|
||||||
|
return f(self, *args)
|
||||||
|
except (SSLError, HTTPError, URLError, timeout) as e: # pragma: no cover - timeout/availability issues
|
||||||
|
if not isinstance(e, timeout) and 'timed out' not in str(e):
|
||||||
|
if not hasattr(e, 'code') or e.code > 200 and e.code <= 404:
|
||||||
|
raise
|
||||||
|
raise unittest.SkipTest('Skip test because of %s' % e)
|
||||||
|
return wrapper
|
||||||
|
|
||||||
if sys.version_info >= (2,7): # pragma: no cover - may be unavailable
|
if sys.version_info >= (2,7): # pragma: no cover - may be unavailable
|
||||||
class BadIPsActionTest(LogCaptureTestCase):
|
class BadIPsActionTest(LogCaptureTestCase):
|
||||||
|
|
||||||
|
@ -75,6 +95,7 @@ if sys.version_info >= (2,7): # pragma: no cover - may be unavailable
|
||||||
self.action._timer.cancel()
|
self.action._timer.cancel()
|
||||||
super(BadIPsActionTest, self).tearDown()
|
super(BadIPsActionTest, self).tearDown()
|
||||||
|
|
||||||
|
@skip_if_not_available
|
||||||
def testCategory(self):
|
def testCategory(self):
|
||||||
categories = self.action.getCategories()
|
categories = self.action.getCategories()
|
||||||
self.assertIn("ssh", categories)
|
self.assertIn("ssh", categories)
|
||||||
|
@ -90,17 +111,20 @@ if sys.version_info >= (2,7): # pragma: no cover - may be unavailable
|
||||||
# but valid for blacklisting.
|
# but valid for blacklisting.
|
||||||
self.action.bancategory = "mail"
|
self.action.bancategory = "mail"
|
||||||
|
|
||||||
|
@skip_if_not_available
|
||||||
def testScore(self):
|
def testScore(self):
|
||||||
self.assertRaises(ValueError, setattr, self.action, "score", -5)
|
self.assertRaises(ValueError, setattr, self.action, "score", -5)
|
||||||
self.action.score = 3
|
self.action.score = 3
|
||||||
self.action.score = "3"
|
self.action.score = "3"
|
||||||
|
|
||||||
|
@skip_if_not_available
|
||||||
def testBanaction(self):
|
def testBanaction(self):
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
ValueError, setattr, self.action, "banaction",
|
ValueError, setattr, self.action, "banaction",
|
||||||
"invalid-action")
|
"invalid-action")
|
||||||
self.action.banaction = "test"
|
self.action.banaction = "test"
|
||||||
|
|
||||||
|
@skip_if_not_available
|
||||||
def testUpdateperiod(self):
|
def testUpdateperiod(self):
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
ValueError, setattr, self.action, "updateperiod", -50)
|
ValueError, setattr, self.action, "updateperiod", -50)
|
||||||
|
@ -109,18 +133,15 @@ if sys.version_info >= (2,7): # pragma: no cover - may be unavailable
|
||||||
self.action.updateperiod = 900
|
self.action.updateperiod = 900
|
||||||
self.action.updateperiod = "900"
|
self.action.updateperiod = "900"
|
||||||
|
|
||||||
|
@skip_if_not_available
|
||||||
def testStartStop(self):
|
def testStartStop(self):
|
||||||
try:
|
self.action.start()
|
||||||
self.action.start()
|
self.assertTrue(len(self.action._bannedips) > 10,
|
||||||
self.assertTrue(len(self.action._bannedips) > 10,
|
"%s is fewer as 10: %r" % (len(self.action._bannedips), self.action._bannedips))
|
||||||
"%s is fewer as 10: %r" % (len(self.action._bannedips), self.action._bannedips))
|
self.action.stop()
|
||||||
self.action.stop()
|
self.assertTrue(len(self.action._bannedips) == 0)
|
||||||
self.assertTrue(len(self.action._bannedips) == 0)
|
|
||||||
except (SSLError, timeout) as e: # pragma: no cover - timeout only
|
|
||||||
if not isinstance(e, timeout) and 'timed out' not in str(e):
|
|
||||||
raise
|
|
||||||
raise unittest.SkipTest('Skip test because of %s' % e)
|
|
||||||
|
|
||||||
|
@skip_if_not_available
|
||||||
def testBanIP(self):
|
def testBanIP(self):
|
||||||
aInfo = CallingMap({
|
aInfo = CallingMap({
|
||||||
'ip': IPAddr('192.0.2.1')
|
'ip': IPAddr('192.0.2.1')
|
||||||
|
|
Loading…
Reference in New Issue