From e2665d39fd5e1b108873dca28cbff01c453fea5d Mon Sep 17 00:00:00 2001 From: benrubson Date: Mon, 26 Feb 2018 09:58:37 +0100 Subject: [PATCH 1/7] Use httpS with badips --- config/action.d/badips.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/action.d/badips.py b/config/action.d/badips.py index 473fbf33..03fe7856 100644 --- a/config/action.d/badips.py +++ b/config/action.d/badips.py @@ -81,7 +81,7 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable """ TIMEOUT = 10 - _badips = "http://www.badips.com" + _badips = "https://www.badips.com" def _Request(self, url, **argv): return Request(url, headers={'User-Agent': self.agent}, **argv) From 9a8add0ef04103428c51145327b0c7fb22ec612f Mon Sep 17 00:00:00 2001 From: benrubson Date: Mon, 26 Feb 2018 10:28:51 +0100 Subject: [PATCH 2/7] changelog --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 4bee6288..b16827a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -44,6 +44,7 @@ ver. 0.10.3-dev-1 (20??/??/??) - development edition * possibility to specify own regex-pattern to match epoch date-time, e. g. `^\[{EPOCH}\]` or `^\[{LEPOCH}\]` (gh-2038); the epoch-pattern similar to `{DATE}` patterns does the capture and cuts out the match of whole pattern from the log-line, e. g. date-pattern `^\[{LEPOCH}\]\s+:` will match and cut out `[1516469849551000] :` from begin of the log-line. +* badips.py now uses https instead of plain http when requesting badips.com (gh-2057); ver. 0.10.2 (2018/01/18) - nothing-burns-like-the-cold From fce2a501657269b4a191978317d0bc96aa56f518 Mon Sep 17 00:00:00 2001 From: benrubson Date: Mon, 26 Feb 2018 15:55:21 +0100 Subject: [PATCH 3/7] badips.py, solve a str() issue under FreeBSD --- config/action.d/badips.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/action.d/badips.py b/config/action.d/badips.py index 473fbf33..da80017f 100644 --- a/config/action.d/badips.py +++ b/config/action.d/badips.py @@ -368,7 +368,7 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable Any issues with badips.com request. """ try: - url = "/".join([self._badips, "add", self.category, aInfo['ip']]) + url = "/".join([self._badips, "add", self.category, str(aInfo['ip'])]) if self.key: url = "?".join([url, urlencode({'key': self.key})]) response = urlopen(self._Request(url), timeout=self.timeout) From 8ed892b8bb7637e07b937688f412a5218dffa047 Mon Sep 17 00:00:00 2001 From: benrubson Date: Mon, 26 Feb 2018 16:15:29 +0100 Subject: [PATCH 4/7] Changelog --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 4bee6288..a91f2c68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -44,6 +44,7 @@ ver. 0.10.3-dev-1 (20??/??/??) - development edition * possibility to specify own regex-pattern to match epoch date-time, e. g. `^\[{EPOCH}\]` or `^\[{LEPOCH}\]` (gh-2038); the epoch-pattern similar to `{DATE}` patterns does the capture and cuts out the match of whole pattern from the log-line, e. g. date-pattern `^\[{LEPOCH}\]\s+:` will match and cut out `[1516469849551000] :` from begin of the log-line. +* `action.d/badips.py`: implicit convert IPAddr to str, solves an issue "expected string, IPAddr found" (gh-2059); ver. 0.10.2 (2018/01/18) - nothing-burns-like-the-cold From 095a909c8417958e19174779c27abf1f22ca5a86 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 26 Feb 2018 17:53:34 +0100 Subject: [PATCH 5/7] action.d/badips.py: increases score in test-cases (5 now, ssh/3 returns to large list, which can cause timeout if badips server to busy); --- fail2ban/tests/action_d/test_badips.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fail2ban/tests/action_d/test_badips.py b/fail2ban/tests/action_d/test_badips.py index 2d08b5df..28228544 100644 --- a/fail2ban/tests/action_d/test_badips.py +++ b/fail2ban/tests/action_d/test_badips.py @@ -52,6 +52,9 @@ if sys.version_info >= (2,7): # pragma: no cover - may be unavailable self.jail.actions.add("badips", pythonModule, initOpts={ 'category': "ssh", 'banaction': "test", + 'score': 5, + 'key': "fail2ban-test-suite", + #'bankey': "fail2ban-test-suite", 'timeout': (3 if unittest.F2B.fast else 30), }) self.action = self.jail.actions["badips"] @@ -80,8 +83,8 @@ if sys.version_info >= (2,7): # pragma: no cover - may be unavailable def testScore(self): self.assertRaises(ValueError, setattr, self.action, "score", -5) - self.action.score = 5 - self.action.score = "5" + self.action.score = 3 + self.action.score = "3" def testBanaction(self): self.assertRaises( @@ -97,11 +100,9 @@ if sys.version_info >= (2,7): # pragma: no cover - may be unavailable self.action.updateperiod = 900 self.action.updateperiod = "900" - def testStart(self): + def testStartStop(self): self.action.start() - self.assertTrue(len(self.action._bannedips) > 10) - - def testStop(self): - self.testStart() + self.assertTrue(len(self.action._bannedips) > 10, + "%s is fewer as 10: %r" % (len(self.action._bannedips), self.action._bannedips)) self.action.stop() self.assertTrue(len(self.action._bannedips) == 0) From f52c67238ada1c22df529142f284bf3677730cc4 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 26 Feb 2018 18:16:20 +0100 Subject: [PATCH 6/7] action.d/badips.py: code review, ban command covered, debug log-messages, etc; --- config/action.d/badips.py | 2 ++ fail2ban/tests/action_d/test_badips.py | 31 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/config/action.d/badips.py b/config/action.d/badips.py index da80017f..4e3a1cde 100644 --- a/config/action.d/badips.py +++ b/config/action.d/badips.py @@ -186,6 +186,7 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable urlencode({'age': age})]) if key: url = "&".join([url, urlencode({'key': key})]) + self._logSys.debug('badips.com: get list, url: %r', url) response = urlopen(self._Request(url), timeout=self.timeout) except HTTPError as response: messages = json.loads(response.read().decode('utf-8')) @@ -371,6 +372,7 @@ class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable url = "/".join([self._badips, "add", self.category, str(aInfo['ip'])]) if self.key: url = "?".join([url, urlencode({'key': self.key})]) + self._logSys.debug('badips.com: ban, url: %r', url) response = urlopen(self._Request(url), timeout=self.timeout) except HTTPError as response: messages = json.loads(response.read().decode('utf-8')) diff --git a/fail2ban/tests/action_d/test_badips.py b/fail2ban/tests/action_d/test_badips.py index 28228544..781d0b05 100644 --- a/fail2ban/tests/action_d/test_badips.py +++ b/fail2ban/tests/action_d/test_badips.py @@ -21,15 +21,18 @@ import os import unittest import sys +from ..actiontestcase import CallingMap from ..dummyjail import DummyJail -from ..utils import CONFIG_DIR +from ..servertestcase import IPAddr +from ..utils import LogCaptureTestCase, CONFIG_DIR if sys.version_info >= (2,7): # pragma: no cover - may be unavailable - class BadIPsActionTest(unittest.TestCase): + class BadIPsActionTest(LogCaptureTestCase): available = True, None + pythonModule = None modAction = None - + def setUp(self): """Call before every test case.""" super(BadIPsActionTest, self).setUp() @@ -39,17 +42,20 @@ if sys.version_info >= (2,7): # pragma: no cover - may be unavailable self.jail.actions.add("test") - pythonModule = os.path.join(CONFIG_DIR, "action.d", "badips.py") + pythonModuleName = os.path.join(CONFIG_DIR, "action.d", "badips.py") # check availability (once if not alive, used shorter timeout as in test cases): if BadIPsActionTest.available[0]: if not BadIPsActionTest.modAction: - BadIPsActionTest.modAction = self.jail.actions._load_python_module(pythonModule).Action + if not BadIPsActionTest.pythonModule: + BadIPsActionTest.pythonModule = self.jail.actions._load_python_module(pythonModuleName) + BadIPsActionTest.modAction = BadIPsActionTest.pythonModule.Action + self.jail.actions._load_python_module(pythonModuleName) BadIPsActionTest.available = BadIPsActionTest.modAction.isAvailable(timeout=2 if unittest.F2B.fast else 10) if not BadIPsActionTest.available[0]: raise unittest.SkipTest('Skip test because service is not available: %s' % BadIPsActionTest.available[1]) - self.jail.actions.add("badips", pythonModule, initOpts={ + self.jail.actions.add("badips", pythonModuleName, initOpts={ 'category': "ssh", 'banaction': "test", 'score': 5, @@ -106,3 +112,16 @@ if sys.version_info >= (2,7): # pragma: no cover - may be unavailable "%s is fewer as 10: %r" % (len(self.action._bannedips), self.action._bannedips)) self.action.stop() self.assertTrue(len(self.action._bannedips) == 0) + + def testBanIP(self): + aInfo = CallingMap({ + 'ip': IPAddr('192.0.2.1') + }) + self.action.ban(aInfo) + self.assertLogged('badips.com: ban', wait=True) + self.pruneLog() + # produce an error using wrong category/IP: + self.action._category = 'f2b-this-category-dont-available-test-suite-only' + aInfo['ip'] = '' + self.assertRaises(BadIPsActionTest.pythonModule.HTTPError, self.action.ban, aInfo) + self.assertLogged('IP is invalid', 'invalid category', wait=True, all=False) From 933670d0343b59371b5919b3c0e6c5e2bedbd66f Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 26 Feb 2018 18:35:30 +0100 Subject: [PATCH 7/7] pragma: no cover - availability (once after error case only) --- fail2ban/tests/banmanagertestcase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fail2ban/tests/banmanagertestcase.py b/fail2ban/tests/banmanagertestcase.py index 0391ae3e..c2c64a35 100644 --- a/fail2ban/tests/banmanagertestcase.py +++ b/fail2ban/tests/banmanagertestcase.py @@ -156,7 +156,7 @@ class StatusExtendedCymruInfo(unittest.TestCase): if tc.available[0]: cymru_info = self.__banManager.getBanListExtendedCymruInfo( timeout=(2 if unittest.F2B.fast else 20)) - else: + else: # pragma: no cover - availability (once after error case only) cymru_info = tc.available[1] if cymru_info.get("error"): # pragma: no cover - availability tc.available = False, cymru_info