URL: https://github.com/freeipa/freeipa/pull/1979 Author: varunmylaraiah Title: #1979: WebUI: Extend password policy tests with more scenarios Action: opened
PR body: """ Extend WebUI test_pwpolicy suite with the following test cases Added tests: krbpwdminlength: lower range integer krbmaxpwdlife: non-integer, abc krbmaxpwdlife: upper range integer,2147483648 krbmaxpwdlife: lower range integer,-1 krbminpwdlife: non-integer,edf krbminpwdlife: upper range integer,2147483648 krbminpwdlife: lower range integer,-1 krbpwdhistorylength: non-integer,HIJ krbpwdhistorylength: upper range integer,2147483648 krbpwdhistorylength: lower range integer,-1 krbpwdmindiffchars: noon-integer,3lm krbpwdmindiffchars: upper range integer,2147483648 krbpwdmindiffchars: lower range integer, -1 krbpwdminlength: non-integer, n0p krbpwdminlength: upper range integer,2147483648 krbpwdminlength: lower range integer, -1 cospriority: non-integer, abc cospriority: upper range integer,2147483648 cospriority: lower range integer,-1 krbpwdmaxfailure: non-integer krbpwdmaxfailure: upper range integer krbpwdmaxfailure: lower range integer krbpwdfailurecountinterval: non-integer krbpwdfailurecountinterval: upper range integer krbpwdfailurecountinterval: lower range integer krbpwdlockoutduration: non-integer krbpwdlockoutduration: upper range integer krbpwdlockoutduration: lower range integer deletePolicy_with various scenario MeasurementUnitAdded_Bug798363 Delete global password policy add_Policy_adder_dialog_bug910463 delete_Policy_deleter_dialog_bug910463 test field: cospriority modifyPolicy(undo/refresh/reset) empty policy name upper bound of data range lower bound of data range non integer for policy priority Details in the ticket https://pagure.io/freeipa/issue/7574 """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/1979/head:pr1979 git checkout pr1979
From 4cc1dba999eb86684c3be0f12dddd5ea2dc2b95f Mon Sep 17 00:00:00 2001 From: Varun Mylaraiah <mva...@redhat.com> Date: Wed, 30 May 2018 19:37:42 +0530 Subject: [PATCH 1/2] Temporary commit : temp commit for pr-ci Signed-off-by: Varun Mylaraiah <mva...@redhat.com> --- .freeipa-pr-ci.yaml | 212 ++++++++++++---------------------------------------- 1 file changed, 47 insertions(+), 165 deletions(-) diff --git a/.freeipa-pr-ci.yaml b/.freeipa-pr-ci.yaml index 21f1c004d7..3130b52816 100644 --- a/.freeipa-pr-ci.yaml +++ b/.freeipa-pr-ci.yaml @@ -3,6 +3,9 @@ topologies: name: build cpu: 2 memory: 3800 + ipaserver: &ipaserver + name: ipaserver + cpu: 1 master_1repl: &master_1repl name: master_1repl cpu: 4 @@ -13,7 +16,7 @@ topologies: memory: 6700 jobs: - fedora-28/build: + fedora-27/build: requires: [] priority: 100 job: @@ -21,189 +24,68 @@ jobs: args: git_repo: '{git_repo}' git_refspec: '{git_refspec}' - template: &ci-master-f28 - name: freeipa/ci-master-f28 - version: 0.1.5 + template: &ci-master-f27 + name: freeipa/ci-master-f27 + version: 1.0.3 timeout: 1800 topology: *build - fedora-28/simple_replication: - requires: [fedora-28/build] + fedora-27/test_webui_a_to_d: + requires: [fedora-27/build] priority: 50 job: - class: RunPytest + class: RunWebuiTests args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_simple_replication.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl + build_url: '{fedora-27/build_url}' + test_suite: test_webui/test_automember.py test_webui/test_cert.py test_webui/test_config.py test_webui/test_delegation.py test_webui/test_dns.py + template: *ci-master-f27 + timeout: 7200 + topology: *ipaserver - fedora-28/caless: - requires: [fedora-28/build] + fedora-27/test_webui_g_to_m: + requires: [fedora-27/build] priority: 50 job: - class: RunPytest + class: RunWebuiTests args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_caless.py::TestServerReplicaCALessToCAFull - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl + build_url: '{fedora-27/build_url}' + test_suite: test_webui/test_group.py test_webui/test_hbac.py test_webui/test_host.py test_webui/test_hostgroup.py test_webui/test_idviews.py test_webui/test_krbtpolicy.py test_webui/test_misc_cases.py + template: *ci-master-f27 + timeout: 7200 + topology: *ipaserver - fedora-28/external_ca: - requires: [fedora-28/build] + fedora-27/test_webui_n_to_r: + requires: [fedora-27/build] priority: 50 job: - class: RunPytest + class: RunWebuiTests args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_external_ca.py::TestExternalCA test_integration/test_external_ca.py::TestSelfExternalSelf test_integration/test_external_ca.py::TestExternalCAInstall - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl_1client + build_url: '{fedora-27/build_url}' + test_suite: test_webui/test_navigation.py test_webui/test_netgroup.py test_webui/test_pwpolicy.py test_webui/test_range.py test_webui/test_rbac.py test_webui/test_realmdomains.py + template: *ci-master-f27 + timeout: 7200 + topology: *ipaserver - fedora-28/test_topologies: - requires: [fedora-28/build] + fedora-27/test_webui_s_to_z: + requires: [fedora-27/build] priority: 50 job: - class: RunPytest + class: RunWebuiTests args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_topologies.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl + build_url: '{fedora-27/build_url}' + test_suite: test_webui/test_selfservice.py test_webui/test_selinuxusermap.py test_webui/test_service.py test_webui/test_sudo.py test_webui/test_trust.py test_webui/test_user.py test_webui/test_vault.py + template: *ci-master-f27 + timeout: 7200 + topology: *ipaserver - fedora-28/test_sudo: - requires: [fedora-28/build] + fedora-27/test_webui: + requires: [fedora-27/build] priority: 50 job: - class: RunPytest + class: RunWebuiTests args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_sudo.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl_1client - - fedora-28/test_commands: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_commands.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl - - fedora-28/test_kerberos_flags: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_kerberos_flags.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl_1client - - fedora-28/test_http_kdc_proxy: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_http_kdc_proxy.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl_1client - - fedora-28/test_forced_client_enrolment: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_forced_client_reenrollment.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl_1client - - fedora-28/test_advise: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_advise.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl - - fedora-28/test_testconfig: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_testconfig.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl - - fedora-28/test_service_permissions: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_service_permissions.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl - - fedora-28/test_netgroup: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_netgroup.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl - - fedora-28/test_vault: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_vault.py - template: *ci-master-f28 - timeout: 4500 - topology: *master_1repl - - fedora-28/test_authconfig: - requires: [fedora-28/build] - priority: 50 - job: - class: RunPytest - args: - build_url: '{fedora-28/build_url}' - test_suite: test_integration/test_authselect.py - template: *ci-master-f28 - timeout: 3600 - topology: *master_1repl_1client - + build_url: '{fedora-27/build_url}' + test_suite: test_webui/ + template: *ci-master-f27 + timeout: 16000 + topology: *ipaserver From dbe5a9103c4db4a139859b8b2b2cf4b02af4d453 Mon Sep 17 00:00:00 2001 From: Varun Mylaraiah <mva...@redhat.com> Date: Wed, 30 May 2018 23:20:09 +0530 Subject: [PATCH 2/2] ui_tests: extend test_pwpolicy.py suite Extend WebUI test_pwpolicy suite with the following test cases Details in the ticket https://pagure.io/freeipa/issue/7574 Added tests: krbpwdminlength: lower range integer krbmaxpwdlife: non-integer, abc krbmaxpwdlife: upper range integer,2147483648 krbmaxpwdlife: lower range integer,-1 krbminpwdlife: non-integer,edf krbminpwdlife: upper range integer,2147483648 krbminpwdlife: lower range integer,-1 krbpwdhistorylength: non-integer,HIJ krbpwdhistorylength: upper range integer,2147483648 krbpwdhistorylength: lower range integer,-1 krbpwdmindiffchars: noon-integer,3lm krbpwdmindiffchars: upper range integer,2147483648 krbpwdmindiffchars: lower range integer, -1 krbpwdminlength: non-integer, n0p krbpwdminlength: upper range integer,2147483648 krbpwdminlength: lower range integer, -1 cospriority: non-integer, abc cospriority: upper range integer,2147483648 cospriority: lower range integer,-1 krbpwdmaxfailure: non-integer krbpwdmaxfailure: upper range integer krbpwdmaxfailure: lower range integer krbpwdfailurecountinterval: non-integer krbpwdfailurecountinterval: upper range integer krbpwdfailurecountinterval: lower range integer krbpwdlockoutduration: non-integer krbpwdlockoutduration: upper range integer krbpwdlockoutduration: lower range integer deletePolicy_with various scenario MeasurementUnitAdded_Bug798363 Delete global password policy add_Policy_adder_dialog_bug910463 delete_Policy_deleter_dialog_bug910463 test field: cospriority modifyPolicy(undo/refresh/reset) empty policy name upper bound of data range lower bound of data range non integer for policy priority Signed-off-by: Varun Mylaraiah <mva...@redhat.com> --- ipatests/test_webui/data_group.py | 9 ++ ipatests/test_webui/data_pwpolicy.py | 73 +++++++++++ ipatests/test_webui/test_pwpolicy.py | 228 ++++++++++++++++++++++++++++++++++- 3 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 ipatests/test_webui/data_pwpolicy.py diff --git a/ipatests/test_webui/data_group.py b/ipatests/test_webui/data_group.py index 7ef4edd390..2207c4efe2 100644 --- a/ipatests/test_webui/data_group.py +++ b/ipatests/test_webui/data_group.py @@ -116,3 +116,12 @@ ('radio', 'type', 'nonposix'), ] } + +PKEY_SPECIAL_CHAR_GROUP = 'itest...group_-$' +DATA_SPECIAL_CHAR_GROUP = { + 'pkey': PKEY_SPECIAL_CHAR_GROUP, + 'add': [ + ('textbox', 'cn', PKEY_SPECIAL_CHAR_GROUP), + ('textarea', 'description', 'special characters group desc'), + ] +} diff --git a/ipatests/test_webui/data_pwpolicy.py b/ipatests/test_webui/data_pwpolicy.py new file mode 100644 index 0000000000..6ca2ed1cf6 --- /dev/null +++ b/ipatests/test_webui/data_pwpolicy.py @@ -0,0 +1,73 @@ +# +# Copyright (C) 2018 FreeIPA Contributors see COPYING for license +# + +import ipatests.test_webui.data_group as group + +ENTITY = 'pwpolicy' +DEFAULT_POLICY = 'global_policy' + +PKEY1 = group.PKEY +DATA1 = { + 'pkey': group.PKEY, + 'add': [ + ('combobox', 'cn', group.PKEY), + ('textbox', 'cospriority', '1'), + ], +} + +PKEY2 = group.PKEY2 +DATA2 = { + 'pkey': group.PKEY2, + 'add': [ + ('combobox', 'cn', group.PKEY2), + ('textbox', 'cospriority', '2'), + ], +} + +PKEY3 = group.PKEY3 +DATA3 = { + 'pkey': group.PKEY3, + 'add': [ + ('combobox', 'cn', group.PKEY3), + ('textbox', 'cospriority', '3'), + ], +} + +PKEY6 = group.PKEY6 +DATA_RESET = { + 'pkey': group.PKEY6, + 'add': [ + ('combobox', 'cn', group.PKEY6), + ('textbox', 'cospriority', '6'), + ], + 'mod': [ + ('textbox', 'krbmaxpwdlife', '3000'), + ('textbox', 'krbminpwdlife', '1'), + ('textbox', 'krbpwdhistorylength', '0'), + ('textbox', 'krbpwdmindiffchars', '2'), + ('textbox', 'krbpwdminlength', '2'), + ('textbox', 'krbpwdmaxfailure', '15'), + ('textbox', 'krbpwdfailurecountinterval', '5'), + ('textbox', 'krbpwdlockoutduration', '3600'), + ('textbox', 'cospriority', '365'), + ], +} + +PKEY_SPECIAL_CHAR = group.PKEY_SPECIAL_CHAR_GROUP +DATA_SPECIAL_CHAR = { + 'pkey': group.PKEY_SPECIAL_CHAR_GROUP, + 'add': [ + ('combobox', 'cn', group.PKEY_SPECIAL_CHAR_GROUP), + ('textbox', 'cospriority', '7'), + ], +} + +PKEY7 = group.PKEY4 +DATA7 = { + 'pkey': group.PKEY4, + 'add': [ + ('combobox', 'cn', group.PKEY4), + ('textbox', 'cospriority', '4'), + ], +} \ No newline at end of file diff --git a/ipatests/test_webui/test_pwpolicy.py b/ipatests/test_webui/test_pwpolicy.py index 91dee21dcc..a79db7e818 100644 --- a/ipatests/test_webui/test_pwpolicy.py +++ b/ipatests/test_webui/test_pwpolicy.py @@ -23,9 +23,17 @@ from ipatests.test_webui.ui_driver import UI_driver from ipatests.test_webui.ui_driver import screenshot +import ipatests.test_webui.data_group as group +import ipatests.test_webui.data_pwpolicy as pwpolicy import pytest -ENTITY = 'pwpolicy' +try: + from selenium.webdriver.common.by import By + from selenium.webdriver.common.keys import Keys + from selenium.webdriver.common.action_chains import ActionChains +except ImportError: + pass + DATA = { 'pkey': 'admins', 'add': [ @@ -41,9 +49,15 @@ ('textbox', 'krbpwdmaxfailure', '15'), ('textbox', 'krbpwdfailurecountinterval', '5'), ('textbox', 'krbpwdlockoutduration', '3600'), + ('textbox', 'cospriority', '365'), ], } +FIELDS = ['krbmaxpwdlife', 'krbminpwdlife', 'krbpwdhistorylength', + 'krbpwdmindiffchars', 'krbpwdminlength', 'krbpwdmaxfailure', + 'krbpwdfailurecountinterval', 'krbpwdlockoutduration', + 'cospriority'] + @pytest.mark.tier1 class test_pwpolicy(UI_driver): @@ -54,4 +68,214 @@ def test_crud(self): Basic CRUD: pwpolicy """ self.init_app() - self.basic_crud(ENTITY, DATA) + self.basic_crud(pwpolicy.ENTITY, DATA) + + @screenshot + def test_misc(self): + """ + various test cases covered in one place + """ + # Basic requirement : create user group for test + self.init_app() + self.navigate_to_entity(group.ENTITY) + self.add_record(group.ENTITY, [group.DATA, group.DATA2, group.DATA3, + group.DATA4, group.DATA5, group.DATA6, + group.DATA_SPECIAL_CHAR_GROUP]) + + # add then cancel + self.add_record(pwpolicy.ENTITY, pwpolicy.DATA1, dialog_btn='cancel') + + # test add and add another record + self.add_record(pwpolicy.ENTITY, [pwpolicy.DATA1, pwpolicy.DATA2]) + + # test add and edit record + self.add_record(pwpolicy.ENTITY, DATA, dialog_btn='add_and_edit') + + # test add password policy for special characters group + self.add_record(pwpolicy.ENTITY, pwpolicy.DATA_SPECIAL_CHAR, + delete=True) + + # empty group and priority (requires the field) + self.navigate_to_entity(pwpolicy.ENTITY) + self.facet_button_click('add') + self.dialog_button_click('add') + self.assert_field_validation_required(field='cn') + self.assert_field_validation_required(field='cospriority') + self.close_all_dialogs() + + # test delete default policy and + # confirming by keyboard to test ticket-4097 + expected_error = "invalid 'group': cannot delete global password policy" + self.navigate_to_entity(pwpolicy.ENTITY) + self.select_record(pwpolicy.DEFAULT_POLICY) + self.facet_button_click('remove') + self.dialog_button_click('ok') + self.assert_last_error_dialog(expected_error, details=True) + actions = ActionChains(self.driver) + actions.send_keys(Keys.TAB) + actions.send_keys(Keys.ENTER).perform() + self.wait(0.5) + self.assert_record(pwpolicy.DEFAULT_POLICY) + + # test add/delete Passwordpolicy confirming using ENTER key ticket-3200 + expected_msg = 'Password Policy successfully added' + self.add_record(pwpolicy.ENTITY, pwpolicy.DATA3, dialog_btn=None) + actions = ActionChains(self.driver) + actions.send_keys(Keys.ENTER).perform() + self.wait_for_request(d=0.5) + self.assert_notification(assert_text=expected_msg) + self.assert_record(pwpolicy.PKEY3) + self.close_notifications() + self.delete_record(pwpolicy.PKEY3, confirm_btn=None) + actions = ActionChains(self.driver) + actions.send_keys(Keys.ENTER).perform() + self.wait_for_request(d=0.5) + self.assert_notification(assert_text='1 item(s) deleted') + self.assert_record(pwpolicy.PKEY3, negative=True) + self.close_notifications() + + # test delete multiple records + records = [DATA, pwpolicy.DATA1, pwpolicy.DATA2] + self.navigate_to_entity(pwpolicy.ENTITY) + self.select_multiple_records(records) + self.facet_button_click('remove') + self.dialog_button_click('ok') + + @screenshot + def test_negative_value(self): + """ + Negative test for Password policy fields in edit page + """ + self.init_app() + self.navigate_to_entity(pwpolicy.ENTITY) + non_interger_expected_error = 'Must be an integer' + minimum_value_expected_error = 'Minimum value is 0' + non_integer = 'nonInteger' + maximum_value = '2147483649' + minimum_value = '-1' + + self.add_record(pwpolicy.ENTITY, pwpolicy.DATA1, + dialog_btn='add_and_edit') + + for field in FIELDS: + # bigger than max value + if field == 'krbmaxpwdlife': + self.modify_policy(field, 'Maximum value is 20000', + maximum_value) + elif field == 'krbpwdmindiffchars': + self.modify_policy(field, 'Maximum value is 5', maximum_value) + else: + self.modify_policy(field, 'Maximum value is 2147483647', + maximum_value) + + # string used instead of integer + self.modify_policy(field, non_interger_expected_error, + non_integer) + + # smaller than max value + self.modify_policy(field, minimum_value_expected_error, + minimum_value) + self.navigate_to_entity(pwpolicy.ENTITY) + self.delete_record(pwpolicy.group.PKEY) + + # Negative test for policy priority + field_priority = 'cospriority' + self.add_record(pwpolicy.ENTITY, pwpolicy.DATA7, dialog_btn=None) + # non integer for policy priority + self.fill_input(field_priority, non_integer) + self.assert_field_validation(non_interger_expected_error, + field=field_priority) + # lower bound of data range + self.fill_input(field_priority, minimum_value) + self.assert_field_validation(minimum_value_expected_error, + field=field_priority) + # upper bound of data range + self.fill_input(field_priority, maximum_value) + self.assert_field_validation(expect_error='Maximum value is 2147483647', + field=field_priority) + self.close_all_dialogs() + + def modify_policy(self, pwdfield, expected_error, value): + """ + modifying password policy values and asserting expected error + """ + self.fill_textbox(pwdfield, value) + self.wait_for_request() + self.assert_field_validation(expected_error, field=pwdfield) + self.facet_button_click('revert') + + @screenshot + def test_undo_refresh_revert(self): + """ + Test to verify undo/refresh/revert + """ + self.init_app() + self.add_record(pwpolicy.ENTITY, pwpolicy.DATA_RESET) + self.navigate_to_record(pwpolicy.PKEY6) + + # test undo + self.fill_fields(pwpolicy.DATA_RESET['mod']) + mod_field = 0 + for field in FIELDS: + modified_value = (pwpolicy.DATA_RESET['mod'][mod_field][2]) + self.click_undo_button(field) + self.verify_btn_action(field, modified_value) + mod_field + 1 + + # test refresh + mod_field = 0 + for field in FIELDS: + self.fill_fields(pwpolicy.DATA_RESET['mod']) + modified_value = (pwpolicy.DATA_RESET['mod'][mod_field][2]) + self.facet_button_click('refresh') + self.verify_btn_action(field, modified_value) + mod_field + 1 + + # test revert + mod_field = 0 + for field in FIELDS: + self.fill_fields(pwpolicy.DATA_RESET['mod']) + modified_value = (pwpolicy.DATA_RESET['mod'][mod_field][2]) + self.facet_button_click('revert') + self.verify_btn_action(field, modified_value) + mod_field + 1 + + # cleanup + self.navigate_to_entity(pwpolicy.ENTITY) + self.delete_record(pwpolicy.group.PKEY6) + + def verify_btn_action(self, field, mod_value, negative=True): + """ + comparing current value with modified value + """ + current_value = self.get_field_value(field, element="input") + if negative: + assert current_value != mod_value + else: + assert current_value == mod_value + + @screenshot + def test_verify_measurement_unit(self): + """ + verifying measurement unit for password policy ticket-2437 + """ + self.init_app() + self.navigate_to_entity(pwpolicy.ENTITY) + self.navigate_to_record('global_policy') + krbmaxpwdlife = self.get_text('label[name="krbmaxpwdlife"]') + krbminpwdlife = self.get_text('label[name="krbminpwdlife"]') + krbpwdhistorylength = self.get_text('label[name="krbpwdhistorylength"]') + krbpwdfailurecountinterval = \ + self.get_text('label[name="krbpwdfailurecountinterval"]') + krbpwdlockoutduration = \ + self.get_text('label[name="krbpwdlockoutduration"]') + assert "Max lifetime (days)" in krbmaxpwdlife + assert "Min lifetime (hours)" in krbminpwdlife + assert "History size (number of passwords)" in krbpwdhistorylength + assert "Failure reset interval (seconds)" in krbpwdfailurecountinterval + assert "Lockout duration (seconds)" in krbpwdlockoutduration + + # cleanup + self.delete(group.ENTITY, [group.DATA, group.DATA2, group.DATA3, + group.DATA4, group.DATA5, group.DATA6, + group.DATA_SPECIAL_CHAR_GROUP])
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/freeipa-devel@lists.fedorahosted.org/message/T6D5T3WY7LVZ74MUGGSCIXPT7EFBUGZD/