From 9479a393a71fe1de7d62ca2b50a7d3d8698d4ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= Date: Tue, 4 Aug 2020 11:05:31 +0200 Subject: [PATCH] ipatests: tasks.py: fix ipa-epn invocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tasks.py::ipa_epn would previously fail to invoke ipa-epn with from_nbdays=0. Related: https://pagure.io/freeipa/issue/8449 Signed-off-by: François Cami Reviewed-By: Rob Crittenden Reviewed-By: Florence Blanc-Renaud --- ipatests/pytest_ipa/integration/tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipatests/pytest_ipa/integration/tasks.py b/ipatests/pytest_ipa/integration/tasks.py index a3f7cc838..c0a592750 100755 --- a/ipatests/pytest_ipa/integration/tasks.py +++ b/ipatests/pytest_ipa/integration/tasks.py @@ -1470,9 +1470,9 @@ def ipa_epn( cmd.append("--dry-run") if mailtest: cmd.append("--mail-test") - if from_nbdays: + if from_nbdays is not None: cmd.extend(("--from-nbdays", str(from_nbdays))) - if to_nbdays: + if to_nbdays is not None: cmd.extend(("--to-nbdays", str(to_nbdays))) return host.run_command(cmd, raiseonerr=raiseonerr) -- 2.26.2 From 3b8fdd87760cfb8ec739c67298f012cf0bd3ac39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= Date: Wed, 5 Aug 2020 10:02:31 +0200 Subject: [PATCH] ipatests: test_epn: test_EPN_nbdays enhancements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhance test_EPN_nbdays so that it checks: * that no emails get sent when using --dry-run * that --from-nbdays implies --dry-run * that --to-nbdays requires --from-nbdays * illegal inputs for nbdays: ** from-nbdays > to-nbdays ** non-numerical input ** decimal input Fixes: https://pagure.io/freeipa/issue/8449 Signed-off-by: François Cami Reviewed-By: Rob Crittenden Reviewed-By: Florence Blanc-Renaud --- ipatests/test_integration/test_epn.py | 130 +++++++++++++++++++++++--- 1 file changed, 117 insertions(+), 13 deletions(-) diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py index f4c123c6d..18f73c722 100644 --- a/ipatests/test_integration/test_epn.py +++ b/ipatests/test_integration/test_epn.py @@ -15,6 +15,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +###### +# This test suite will _expectedly_ fail if run at the end of the UTC day +# because users would be created during day N and then EPN output checked +# during day N+1. This is expected and should be ignored as it does not +# reflect a product bug. -- fcami +###### + from __future__ import print_function, absolute_import import base64 @@ -178,12 +185,14 @@ class TestEPN(IntegrationTest): from_nbdays=None, to_nbdays=None, raiseonerr=True, + validatejson=True ): result = tasks.ipa_epn(host, raiseonerr=raiseonerr, dry_run=dry_run, from_nbdays=from_nbdays, to_nbdays=to_nbdays) - json.dumps(json.loads(result.stdout_text), ensure_ascii=False) - return (result.stdout_text, result.stderr_text) + if validatejson: + json.dumps(json.loads(result.stdout_text), ensure_ascii=False) + return (result.stdout_text, result.stderr_text, result.returncode) @classmethod def install(cls, mh): @@ -244,12 +253,12 @@ class TestEPN(IntegrationTest): ''') self.master.put_file_contents('/etc/ipa/epn.conf', epn_conf) # check EPN on client (LDAP+GSSAPI) - (stdout_text, unused) = self._check_epn_output( + (stdout_text, unused, _unused) = self._check_epn_output( self.clients[0], dry_run=True ) assert len(json.loads(stdout_text)) == 0 # check EPN on master (LDAPI) - (stdout_text, unused) = self._check_epn_output( + (stdout_text, unused, _unused) = self._check_epn_output( self.master, dry_run=True ) assert len(json.loads(stdout_text)) == 0 @@ -292,10 +301,10 @@ class TestEPN(IntegrationTest): ), ], ) - (stdout_text_client, unused) = self._check_epn_output( + (stdout_text_client, unused, _unused) = self._check_epn_output( self.clients[0], dry_run=True ) - (stdout_text_master, unused) = self._check_epn_output( + (stdout_text_master, unused, _unused) = self._check_epn_output( self.master, dry_run=True ) assert stdout_text_master == stdout_text_client @@ -331,10 +340,10 @@ class TestEPN(IntegrationTest): password=None, ) - (stdout_text_client, unused) = self._check_epn_output( + (stdout_text_client, unused, _unused) = self._check_epn_output( self.clients[0], dry_run=True ) - (stdout_text_master, unused) = self._check_epn_output( + (stdout_text_master, unused, _unused) = self._check_epn_output( self.master, dry_run=True ) assert stdout_text_master == stdout_text_client @@ -344,22 +353,117 @@ class TestEPN(IntegrationTest): expected_users = ["user1", "user3", "user7", "user14", "user28"] assert sorted(user_lst) == sorted(expected_users) - def test_EPN_nbdays(self): + def test_EPN_nbdays_0(self, cleanupmail): """Test the to/from nbdays options (implies --dry-run) We have a set of users installed with varying expiration dates. Confirm that to/from nbdays finds them. + + Make sure --dry-run does not accidentally send emails. """ - # Compare the notify_ttls values + # Use the notify_ttls values with a 1-day sliding window for i in self.notify_ttls: user_list = [] - (stdout_text_client, unused) = self._check_epn_output( - self.clients[0], from_nbdays=i, to_nbdays=i + 1, dry_run=True) + (stdout_text_client, unused, _unused) = self._check_epn_output( + self.clients[0], from_nbdays=i, to_nbdays=i + 1, dry_run=True + ) for user in json.loads(stdout_text_client): user_list.append(user["uid"]) assert len(user_list) == 1 - assert user_list[0] == "user%d" % i + userid = "user{id}".format(id=i) + assert user_list[0] == userid + + # Check that the user list is expected for any given notify_ttls. + (stdout_text_client, unused, _unused) = self._check_epn_output( + self.clients[0], to_nbdays=i + ) + user_list = [user["uid"] for user in json.loads(stdout_text_client)] + assert len(user_list) == 1 + assert user_list[0] == "user{id}".format(id=i - 1) + + # make sure no emails were sent + result = self.clients[0].run_command(['ls', '-lha', '/var/mail/']) + assert userid not in result.stdout_text + + def test_EPN_nbdays_1(self, cleanupmail): + """Test that for a given range, we find the users in that range""" + + # Use hardcoded date ranges for now + for date_range in [(0, 5), (7, 15), (1, 20)]: + expected_user_list = ["user{i}".format(i=i) + for i in range(date_range[0], date_range[1])] + (stdout_text_client, unused, _unused) = self._check_epn_output( + self.clients[0], + from_nbdays=date_range[0], + to_nbdays=date_range[1] + ) + user_list = [user["uid"] for user in json.loads(stdout_text_client)] + for user in expected_user_list: + assert user in user_list + for user in user_list: + assert user in expected_user_list + + # Test the to/from nbdays options behavior with illegal input + + def test_EPN_nbdays_input_0(self): + """Make sure that --to-nbdays implies --dry-run ; + therefore check that the output is valid JSON and contains the + expected user. + """ + + (stdout_text_client, unused, _unused) = self._check_epn_output( + self.clients[0], to_nbdays=5, dry_run=False + ) + assert len(json.loads(stdout_text_client)) == 1 + assert json.loads(stdout_text_client)[0]["uid"] == "user4" + + def test_EPN_nbdays_input_1(self): + """Make sure that --from-nbdays cannot be used without --to-nbdays""" + + (unused, stderr_text_client, rc) = \ + self._check_epn_output( + self.clients[0], from_nbdays=3, + raiseonerr=False, validatejson=False + ) + assert "You cannot specify --from-nbdays without --to-nbdays" \ + in stderr_text_client + assert rc > 0 + + @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True) + def test_EPN_nbdays_input_2(self): + """alpha input""" + + (unused, stderr, rc) = self._check_epn_output( + self.clients[0], to_nbdays="abc", + raiseonerr=False, validatejson=False + ) + assert "error: --to-nbdays must be an integer." in stderr + assert rc > 0 + + @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True) + def test_EPN_nbdays_input_3(self): + """from_nbdays > to_nbdays""" + + (unused, stderr, rc) = self._check_epn_output( + self.clients[0], from_nbdays=9, to_nbdays=7, + raiseonerr=False, validatejson=False + ) + assert "error: --from-nbdays must be smaller than --to-nbdays." in \ + stderr + assert rc > 0 + + @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True) + def test_EPN_nbdays_input_4(self): + """decimal input""" + + (unused, stderr, rc) = self._check_epn_output( + self.clients[0], to_nbdays=7.3, + raiseonerr=False, validatejson=False + ) + logger.info(stderr) + assert rc > 0 + assert "error: --to-nbdays must be an integer." in stderr # From here the tests build on one another: # 1) add auth -- 2.26.2 From b4266023e04729db12de2f7e0de4da9e1d00db38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= Date: Fri, 7 Aug 2020 19:08:39 +0200 Subject: [PATCH] ipatests: test_epn: update error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update error messages in the test. Fixes: https://pagure.io/freeipa/issue/8449 Signed-off-by: François Cami Reviewed-By: Rob Crittenden Reviewed-By: Florence Blanc-Renaud Reviewed-By: Rob Crittenden Reviewed-By: Florence Blanc-Renaud --- ipatests/test_integration/test_epn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py index e03521193..af662140a 100644 --- a/ipatests/test_integration/test_epn.py +++ b/ipatests/test_integration/test_epn.py @@ -458,7 +458,7 @@ class TestEPN(IntegrationTest): self.clients[0], to_nbdays="abc", raiseonerr=False, validatejson=False ) - assert "error: --to-nbdays must be an integer." in stderr + assert "error: --to-nbdays must be a positive integer." in stderr assert rc > 0 @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True) @@ -483,7 +483,7 @@ class TestEPN(IntegrationTest): ) logger.info(stderr) assert rc > 0 - assert "error: --to-nbdays must be an integer." in stderr + assert "error: --to-nbdays must be a positive integer." in stderr # From here the tests build on one another: # 1) add auth -- 2.26.2 From 2809084a44e3b174fa48a611e79f04358e1d6dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= Date: Wed, 5 Aug 2020 09:05:31 +0200 Subject: [PATCH] IPA-EPN: enhance input validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhance input validation: * make sure --from-nbdays and --to-nbdays are integer * make sure --from-nbdays < --to-nbdays Fixes: https://pagure.io/freeipa/issue/8444 Signed-off-by: François Cami Reviewed-By: Rob Crittenden Reviewed-By: Florence Blanc-Renaud Reviewed-By: Rob Crittenden Reviewed-By: Florence Blanc-Renaud --- ipaclient/install/ipa_epn.py | 28 +++++++++++++++++++++++++-- ipatests/test_integration/test_epn.py | 3 --- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/ipaclient/install/ipa_epn.py b/ipaclient/install/ipa_epn.py index 82d7b3f57..88c926e88 100644 --- a/ipaclient/install/ipa_epn.py +++ b/ipaclient/install/ipa_epn.py @@ -246,9 +246,33 @@ class EPN(admintool.AdminTool): def validate_options(self): super(EPN, self).validate_options(needs_root=True) - if self.options.to_nbdays: + if self.options.to_nbdays is not None: + try: + if int(self.options.to_nbdays) < 0: + raise RuntimeError('Input is negative.') + except Exception as e: + self.option_parser.error( + "--to-nbdays must be a positive integer. " + "{error}".format(error=e) + ) self.options.dry_run = True - if self.options.from_nbdays and not self.options.to_nbdays: + if self.options.from_nbdays is not None: + try: + if int(self.options.from_nbdays) < 0: + raise RuntimeError('Input is negative.') + except Exception as e: + self.option_parser.error( + "--from-nbdays must be a positive integer. " + "{error}".format(error=e) + ) + if self.options.from_nbdays is not None and \ + self.options.to_nbdays is not None: + if int(self.options.from_nbdays) >= int(self.options.to_nbdays): + self.option_parser.error( + "--from-nbdays must be smaller than --to-nbdays." + ) + if self.options.from_nbdays is not None and \ + self.options.to_nbdays is None: self.option_parser.error( "You cannot specify --from-nbdays without --to-nbdays" ) diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py index af662140a..fc26888cb 100644 --- a/ipatests/test_integration/test_epn.py +++ b/ipatests/test_integration/test_epn.py @@ -450,7 +450,6 @@ class TestEPN(IntegrationTest): in stderr_text_client assert rc > 0 - @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True) def test_EPN_nbdays_input_2(self): """alpha input""" @@ -461,7 +460,6 @@ class TestEPN(IntegrationTest): assert "error: --to-nbdays must be a positive integer." in stderr assert rc > 0 - @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True) def test_EPN_nbdays_input_3(self): """from_nbdays > to_nbdays""" @@ -473,7 +471,6 @@ class TestEPN(IntegrationTest): stderr assert rc > 0 - @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True) def test_EPN_nbdays_input_4(self): """decimal input""" -- 2.26.2