From 5bc92e99e57afaa6a8098eb57715126c35f434db Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Mar 14 2019 04:45:15 +0000 Subject: Ticket 50255 - Port password policy test to use DSLdapObject Description: While investigating ticket 50255 I had issues with the CI test because it was not use DSLdapObject. So This patch just refectors the test to use the current DSLDAPObject model. https://pagure.io/389-ds-base/issue/50255 Reviewed by: firstyear(Thanks!) --- diff --git a/dirsrvtests/tests/suites/password/pwdModify_test.py b/dirsrvtests/tests/suites/password/pwdModify_test.py index 3a554cb..3e8d3bf 100644 --- a/dirsrvtests/tests/suites/password/pwdModify_test.py +++ b/dirsrvtests/tests/suites/password/pwdModify_test.py @@ -6,7 +6,6 @@ # --- END COPYRIGHT BLOCK --- # import pytest -import subprocess import re from ldap.controls import LDAPControl from lib389._constants import * @@ -15,7 +14,6 @@ from lib389.utils import * from lib389.topologies import topology_st as topo from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES from lib389.idm.organizationalunit import OrganizationalUnits -from lib389.idm.nscontainer import nsContainers from lib389.pwpolicy import PwPolicyManager DEBUGGING = os.getenv("DEBUGGING", default=False) @@ -30,6 +28,7 @@ OLD_PASSWD = 'password' NEW_PASSWD = 'newpassword' SHORT_PASSWD = 'wd' TESTPEOPLE_OU = "TestPeople_bug834047" +USER_ACI = '(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)' @pytest.fixture(scope="function") @@ -41,6 +40,7 @@ def pwd_policy_setup(topo, request): passwordHistory off """ log.info("Change the pwd storage type to clear and change the password once to refresh it(for the rest of tests") + topo.standalone.simple_bind_s(DN_DM, PASSWORD) topo.standalone.config.set('passwordStorageScheme', 'CLEAR') assert topo.standalone.passwd_s(user_2.dn, OLD_PASSWD, NEW_PASSWD) topo.standalone.config.set('passwordHistory', 'on') @@ -84,12 +84,17 @@ def test_pwd_modify_with_different_operation(topo): 10. Operation should violates the policy 11. Operation should be successful """ + topo.standalone.enable_tls() os.environ["LDAPTLS_CACERTDIR"] = topo.standalone.get_ssca_dir() users = UserAccounts(topo.standalone, DEFAULT_SUFFIX) TEST_USER_PROPERTIES['userpassword'] = OLD_PASSWD global user user = users.create(properties=TEST_USER_PROPERTIES) + ous = OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX) + ou = ous.get('people') + ou.add('aci', USER_ACI) + with pytest.raises(ldap.NO_SUCH_OBJECT): log.info("Attempt for Password change for an entry that does not exists") assert topo.standalone.passwd_s('uid=testuser1,ou=People,dc=example,dc=com', OLD_PASSWD, NEW_PASSWD) @@ -133,6 +138,7 @@ def test_pwd_modify_with_different_operation(topo): 'homeDirectory': '/home/testuser2', 'userPassword': OLD_PASSWD }) + topo.standalone.simple_bind_s(user.dn, NEW_PASSWD) with pytest.raises(ldap.INSUFFICIENT_ACCESS): assert topo.standalone.passwd_s(user_2.dn, OLD_PASSWD, NEW_PASSWD) @@ -218,8 +224,11 @@ def test_pwd_modify_with_subsuffix(topo): """ log.info("Add a new SubSuffix") + topo.standalone.simple_bind_s(DN_DM, PASSWORD) + ous = OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX) ou_temp = ous.create(properties={'ou': TESTPEOPLE_OU}) + ou_temp.add('aci', USER_ACI) log.info("Add the container & create password policies") policy = PwPolicyManager(topo.standalone) @@ -228,7 +237,7 @@ def test_pwd_modify_with_subsuffix(topo): 'passwordInHistory': '6', 'passwordChange': 'on', 'passwordStorageScheme': 'CLEAR'}) - + log.info("Add two New users under the SubEntry") user = UserAccounts(topo.standalone, DEFAULT_SUFFIX, rdn='ou=TestPeople_bug834047') test_user0 = user.create(properties={ @@ -240,6 +249,7 @@ def test_pwd_modify_with_subsuffix(topo): 'homeDirectory': '/home/test_user0', 'userPassword': OLD_PASSWD }) + test_user1 = user.create(properties={ 'uid': 'test_user1', 'cn': 'test1', @@ -249,15 +259,18 @@ def test_pwd_modify_with_subsuffix(topo): 'homeDirectory': '/home/test_user3', 'userPassword': OLD_PASSWD }) - log.info(f"Changing password of {test_user0.dn} to newpassword") - topo.standalone.simple_bind_s(test_user0.dn, OLD_PASSWD) - topo.standalone.modify_s(test_user0.dn, [(ldap.MOD_REPLACE, 'userPassword', ensure_bytes(NEW_PASSWD))]) - topo.standalone.simple_bind_s(test_user0.dn, NEW_PASSWD) + + log.info("Changing password of {} to newpassword".format(test_user0.dn)) + test_user0.rebind(OLD_PASSWD) + test_user0.reset_password(NEW_PASSWD) + test_user0.rebind(NEW_PASSWD) + log.info("Try to delete password- case when password is specified") - topo.standalone.modify_s(test_user0.dn, [(ldap.MOD_DELETE, 'userPassword', ensure_bytes(NEW_PASSWD))]) - topo.standalone.simple_bind_s(test_user1.dn, OLD_PASSWD) + test_user0.remove('userPassword', NEW_PASSWD) + + test_user1.rebind(OLD_PASSWD) log.info("Try to delete password- case when password is not specified") - topo.standalone.modify_s(test_user1.dn, [(ldap.MOD_DELETE, 'userPassword', None)]) + test_user1.remove_all('userPassword') if __name__ == '__main__': diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py index 9bd9465..1c0dab1 100644 --- a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py +++ b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py @@ -10,11 +10,10 @@ import pytest from lib389.tasks import * from lib389.utils import * from lib389.topologies import topology_st - -from lib389._constants import (DEFAULT_SUFFIX, DN_DM, PASSWORD, HOST_STANDALONE, SERVERID_STANDALONE, - PORT_STANDALONE) - -import subprocess +from lib389.pwpolicy import PwPolicyManager +from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES +from lib389.idm.organizationalunit import OrganizationalUnits +from lib389._constants import (DEFAULT_SUFFIX, DN_DM, PASSWORD) OU_PEOPLE = 'ou=people,{}'.format(DEFAULT_SUFFIX) TEST_USER_NAME = 'simplepaged_test' @@ -34,27 +33,24 @@ log = logging.getLogger(__name__) @pytest.fixture(scope="module") def create_user(topology_st, request): """User for binding operation""" - - log.info('Adding user {}'.format(TEST_USER_DN)) + topology_st.standalone.config.set('nsslapd-auditlog-logging-enabled', 'on') + log.info('Adding test user {}') + users = UserAccounts(topology_st.standalone, OU_PEOPLE, rdn=None) + user_props = TEST_USER_PROPERTIES.copy() + user_props.update({'uid': TEST_USER_NAME, 'userpassword': TEST_USER_PWD}) try: - topology_st.standalone.add_s(Entry((TEST_USER_DN, { - 'objectclass': 'top person'.split(), - 'objectclass': 'organizationalPerson', - 'objectclass': 'inetorgperson', - 'cn': TEST_USER_NAME, - 'sn': TEST_USER_NAME, - 'userpassword': TEST_USER_PWD, - 'mail': '%s@redhat.com' % TEST_USER_NAME, - 'uid': TEST_USER_NAME - }))) - except ldap.LDAPError as e: - log.error('Failed to add user (%s): error (%s)' % (TEST_USER_DN, - e.message['desc'])) - raise e + user = users.create(properties=user_props) + except: + pass # debug only + + USER_ACI = '(targetattr="*")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///%s";)' % user.dn + ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) + ou_people = ous.get('people') + ou_people.add('aci', USER_ACI) def fin(): - log.info('Deleting user {}'.format(TEST_USER_DN)) - topology_st.standalone.delete_s(TEST_USER_DN) + log.info('Deleting user {}'.format(user.dn)) + topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) request.addfinalizer(fin) @@ -63,65 +59,19 @@ def create_user(topology_st, request): def password_policy(topology_st, create_user): """Set up password policy for subtree and user""" - log.info('Enable fine-grained policy') - try: - topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, - 'nsslapd-pwpolicy-local', - b'on')]) - except ldap.LDAPError as e: - log.error('Failed to set fine-grained policy: error {}'.format( - e.message['desc'])) - raise e - + pwp = PwPolicyManager(topology_st.standalone) + policy_props = {} log.info('Create password policy for subtree {}'.format(OU_PEOPLE)) - try: - subprocess.call(['%s/ns-newpwpolicy.pl' % topology_st.standalone.get_sbin_dir(), - '-D', DN_DM, '-w', PASSWORD, - '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE, - '-S', OU_PEOPLE, '-Z', SERVERID_STANDALONE]) - except subprocess.CalledProcessError as e: - log.error('Failed to create pw policy policy for {}: error {}'.format( - OU_PEOPLE, e.message['desc'])) - raise e + pwp.create_subtree_policy(OU_PEOPLE, policy_props) - log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE)) - try: - topology_st.standalone.modify_s(OU_PEOPLE, [(ldap.MOD_REPLACE, - 'pwdpolicysubentry', - ensure_bytes(PW_POLICY_CONT_PEOPLE))]) - except ldap.LDAPError as e: - log.error('Failed to pwdpolicysubentry pw policy ' \ - 'policy for {}: error {}'.format(OU_PEOPLE, - e.message['desc'])) - raise e - - log.info('Create password policy for subtree {}'.format(TEST_USER_DN)) - try: - subprocess.call(['%s/ns-newpwpolicy.pl' % topology_st.standalone.get_sbin_dir(), - '-D', DN_DM, '-w', PASSWORD, - '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE, - '-U', TEST_USER_DN, '-Z', SERVERID_STANDALONE]) - except subprocess.CalledProcessError as e: - log.error('Failed to create pw policy policy for {}: error {}'.format( - TEST_USER_DN, e.message['desc'])) - raise e - - log.info('Add pwdpolicysubentry attribute to {}'.format(TEST_USER_DN)) - try: - topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE, - 'pwdpolicysubentry', - ensure_bytes(PW_POLICY_CONT_USER))]) - except ldap.LDAPError as e: - log.error('Failed to pwdpolicysubentry pw policy ' \ - 'policy for {}: error {}'.format(TEST_USER_DN, - e.message['desc'])) - raise e + log.info('Create password policy for user {}'.format(TEST_USER_DN)) + pwp.create_user_policy(TEST_USER_DN, policy_props) @pytest.mark.parametrize('subtree_pwchange,user_pwchange,exception', [('on', 'off', ldap.UNWILLING_TO_PERFORM), ('off', 'off', ldap.UNWILLING_TO_PERFORM), - ('off', 'on', None), ('on', 'on', None)]) + ('off', 'on', False), ('on', 'on', False)]) def test_change_pwd(topology_st, create_user, password_policy, subtree_pwchange, user_pwchange, exception): """Verify that 'passwordChange' attr works as expected @@ -145,43 +95,33 @@ def test_change_pwd(topology_st, create_user, password_policy, 4. Operation should be successful """ - log.info('Set passwordChange to "{}" - {}'.format(subtree_pwchange, - PW_POLICY_CONT_PEOPLE)) - try: - topology_st.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE, - 'passwordChange', - ensure_bytes(subtree_pwchange))]) - except ldap.LDAPError as e: - log.error('Failed to set passwordChange ' \ - 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE, - e.message['desc'])) - raise e + users = UserAccounts(topology_st.standalone, OU_PEOPLE, rdn=None) + user = users.get(TEST_USER_NAME) + + log.info('Set passwordChange to "{}" - {}'.format(subtree_pwchange, OU_PEOPLE)) + pwp = PwPolicyManager(topology_st.standalone) + subtree_policy = pwp.get_pwpolicy_entry(OU_PEOPLE) + subtree_policy.set('passwordChange', subtree_pwchange) - log.info('Set passwordChange to "{}" - {}'.format(user_pwchange, - PW_POLICY_CONT_USER)) - try: - topology_st.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE, - 'passwordChange', - ensure_bytes(user_pwchange))]) - except ldap.LDAPError as e: - log.error('Failed to set passwordChange ' \ - 'policy for {}: error {}'.format(PW_POLICY_CONT_USER, - e.message['desc'])) - raise e + time.sleep(1) + + log.info('Set passwordChange to "{}" - {}'.format(user_pwchange, TEST_USER_DN)) + pwp2 = PwPolicyManager(topology_st.standalone) + user_policy = pwp2.get_pwpolicy_entry(TEST_USER_DN) + user_policy.set('passwordChange', user_pwchange) + user_policy.set('passwordExp', 'on') + + print("MARK attach gdb") time.sleep(1) try: log.info('Bind as user and modify userPassword') - topology_st.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD) + user.rebind(TEST_USER_PWD) if exception: with pytest.raises(exception): - topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE, - 'userPassword', - b'new_pass')]) + user.reset_password('new_pass') else: - topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE, - 'userPassword', - b'new_pass')]) + user.reset_password('new_pass') except ldap.LDAPError as e: log.error('Failed to change userpassword for {}: error {}'.format( TEST_USER_DN, e.message['info'])) @@ -189,9 +129,7 @@ def test_change_pwd(topology_st, create_user, password_policy, finally: log.info('Bind as DM') topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) - topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE, - 'userPassword', - ensure_bytes(TEST_USER_PWD))]) + user.reset_password(TEST_USER_PWD) def test_pwd_min_age(topology_st, create_user, password_policy): @@ -223,69 +161,41 @@ def test_pwd_min_age(topology_st, create_user, password_policy): """ num_seconds = '10' + users = UserAccounts(topology_st.standalone, OU_PEOPLE, rdn=None) + user = users.get(TEST_USER_NAME) - log.info('Set passwordminage to "{}" - {}'.format(num_seconds, PW_POLICY_CONT_PEOPLE)) - try: - topology_st.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE, - 'passwordminage', - ensure_bytes(num_seconds))]) - except ldap.LDAPError as e: - log.error('Failed to set passwordminage ' \ - 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE, - e.message['desc'])) - raise e + log.info('Set passwordminage to "{}" - {}'.format(num_seconds, OU_PEOPLE)) + pwp = PwPolicyManager(topology_st.standalone) + subtree_policy = pwp.get_pwpolicy_entry(OU_PEOPLE) + subtree_policy.set('passwordminage', num_seconds) - log.info('Set passwordminage to "{}" - {}'.format(num_seconds, PW_POLICY_CONT_USER)) - try: - topology_st.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE, - 'passwordminage', - ensure_bytes(num_seconds))]) - except ldap.LDAPError as e: - log.error('Failed to set passwordminage ' \ - 'policy for {}: error {}'.format(PW_POLICY_CONT_USER, - e.message['desc'])) - raise e + log.info('Set passwordminage to "{}" - {}'.format(num_seconds, TEST_USER_DN)) + user_policy = pwp.get_pwpolicy_entry(TEST_USER_DN) + user_policy.set('passwordminage', num_seconds) log.info('Set passwordminage to "{}" - {}'.format(num_seconds, DN_CONFIG)) - try: - topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, - 'passwordminage', - ensure_bytes(num_seconds))]) - except ldap.LDAPError as e: - log.error('Failed to set passwordminage ' \ - 'policy for {}: error {}'.format(DN_CONFIG, - e.message['desc'])) - raise e + topology_st.standalone.config.set('passwordminage', num_seconds) + time.sleep(1) - try: - log.info('Bind as user and modify userPassword') - topology_st.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD) - topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE, - 'userPassword', - b'new_pass')]) - except ldap.LDAPError as e: - log.error('Failed to change userpassword for {}: error {}'.format( - TEST_USER_DN, e.message['info'])) - raise e + log.info('Bind as user and modify userPassword') + user.rebind(TEST_USER_PWD) + user.reset_password('new_pass') + time.sleep(1) log.info('Bind as user and modify userPassword straight away after previous change') - topology_st.standalone.simple_bind_s(TEST_USER_DN, 'new_pass') + user.rebind('new_pass') with pytest.raises(ldap.CONSTRAINT_VIOLATION): - topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE, - 'userPassword', - b'new_new_pass')]) + user.reset_password('new_new_pass') log.info('Wait {} second'.format(int(num_seconds) + 2)) time.sleep(int(num_seconds) + 2) try: log.info('Bind as user and modify userPassword') - topology_st.standalone.simple_bind_s(TEST_USER_DN, 'new_pass') - topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE, - 'userPassword', - ensure_bytes(TEST_USER_PWD))]) + user.rebind('new_pass') + user.reset_password(TEST_USER_PWD) except ldap.LDAPError as e: log.error('Failed to change userpassword for {}: error {}'.format( TEST_USER_DN, e.message['info'])) @@ -293,9 +203,7 @@ def test_pwd_min_age(topology_st, create_user, password_policy): finally: log.info('Bind as DM') topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) - topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE, - 'userPassword', - ensure_bytes(TEST_USER_PWD))]) + user.reset_password(TEST_USER_PWD) if __name__ == '__main__': diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_controls_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_controls_test.py index f7aca8f..0819854 100644 --- a/dirsrvtests/tests/suites/password/pwdPolicy_controls_test.py +++ b/dirsrvtests/tests/suites/password/pwdPolicy_controls_test.py @@ -5,8 +5,10 @@ import ldap import time from ldap.controls.ppolicy import PasswordPolicyControl from lib389.topologies import topology_st as topo -from lib389._constants import (DN_DM, PASSWORD, DN_CONFIG) -from lib389.tasks import Entry +from lib389.idm.user import UserAccounts +from lib389._constants import (DN_DM, PASSWORD, DEFAULT_SUFFIX) +from lib389.idm.organizationalunit import OrganizationalUnits + DEBUGGING = os.getenv("DEBUGGING", default=False) if DEBUGGING: @@ -15,8 +17,9 @@ else: logging.getLogger(__name__).setLevel(logging.INFO) log = logging.getLogger(__name__) -USER_DN = 'uid=test entry,dc=example,dc=com' +USER_DN = 'uid=test entry,ou=people,dc=example,dc=com' USER_PW = b'password123' +USER_ACI = '(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)' @pytest.fixture @@ -25,37 +28,33 @@ def init_user(topo, request): """ try: topo.standalone.simple_bind_s(DN_DM, PASSWORD) - topo.standalone.delete_s(USER_DN) + users = UserAccounts(topo.standalone, DEFAULT_SUFFIX) + user = users.get('test entry') + user.delete() except ldap.NO_SUCH_OBJECT: pass except ldap.LDAPError as e: log.error("Failed to delete user, error: {}".format(e.message['desc'])) assert False - user_data = {'objectClass': 'top person inetOrgPerson'.split(), - 'uid': 'test entry', + user_data = {'uid': 'test entry', 'cn': 'test entry', - 'sn': 'user', + 'sn': 'test entry', + 'uidNumber': '3000', + 'gidNumber': '4000', + 'homeDirectory': '/home/test_entry', 'userPassword': USER_PW} - try: - topo.standalone.add_s(Entry((USER_DN, user_data))) - except ldap.LDAPError as e: - log.error("Failed to add user, error: {}".format(e.message['desc'])) - assert False + users.create(properties=user_data) def change_passwd(topo): """Reset users password as the user, then re-bind as Directory Manager """ - try: - topo.standalone.simple_bind_s(USER_DN, USER_PW) - topo.standalone.modify_s(USER_DN, [(ldap.MOD_REPLACE, - 'userpassword', - USER_PW)]) - topo.standalone.simple_bind_s(DN_DM, PASSWORD) - except ldap.LDAPError as e: - log.error("Failed to change user's password, error: {}".format(e.message['desc'])) - assert False + users = UserAccounts(topo.standalone, DEFAULT_SUFFIX) + user = users.get('test entry') + user.rebind(USER_PW) + user.reset_password(USER_PW) + topo.standalone.simple_bind_s(DN_DM, PASSWORD) def bind_and_get_control(topo, err=0): @@ -113,14 +112,14 @@ def test_pwd_must_change(topo, init_user): topo.standalone.config.set('passwordWarning', '199') topo.standalone.config.set('passwordMustChange', 'on') + ous = OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX) + ou = ous.get('people') + ou.add('aci', USER_ACI) + log.info('Reset userpassword as Directory Manager') - try: - topo.standalone.modify_s(USER_DN, [(ldap.MOD_REPLACE, - 'userpassword', - USER_PW)]) - except ldap.LDAPError as e: - log.error("Failed to change user's password, error: {}".format(e.message['desc'])) - assert False + users = UserAccounts(topo.standalone, DEFAULT_SUFFIX) + user = users.get('test entry') + user.reset_password(USER_PW) log.info('Bind should return ctrl with error code 2 (changeAfterReset)') time.sleep(2) diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_inherit_global_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_inherit_global_test.py index dacb9aa..e8f531d 100644 --- a/dirsrvtests/tests/suites/password/pwdPolicy_inherit_global_test.py +++ b/dirsrvtests/tests/suites/password/pwdPolicy_inherit_global_test.py @@ -1,5 +1,5 @@ # --- BEGIN COPYRIGHT BLOCK --- -# Copyright (C) 2016 Red Hat, Inc. +# Copyright (C) 2019 Red Hat, Inc. # All rights reserved. # # License: GPL (version 3 or any later version). @@ -7,31 +7,25 @@ # --- END COPYRIGHT BLOCK --- # import logging -import subprocess import time import ldap import pytest from lib389.utils import * -from lib389 import Entry from lib389._constants import * +from lib389.pwpolicy import PwPolicyManager from lib389.topologies import topology_st from lib389.idm.organizationalunit import OrganizationalUnits +from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES logging.getLogger(__name__).setLevel(logging.INFO) log = logging.getLogger(__name__) -CONFIG_DN = 'cn=config' OU_PEOPLE = 'ou=People,' + DEFAULT_SUFFIX -PWP_CONTAINER = 'nsPwPolicyContainer' -PWP_CONTAINER_DN = 'cn=' + PWP_CONTAINER + ',' + OU_PEOPLE -PWP_ENTRY_DN = 'cn=nsPwPolicyEntry,' + OU_PEOPLE -PWP_CONTAINER_PEOPLE = 'cn="%s",%s' % (PWP_ENTRY_DN, PWP_CONTAINER_DN) -PWP_TEMPLATE_ENTRY_DN = 'cn=nsPwTemplateEntry,' + OU_PEOPLE ATTR_INHERIT_GLOBAL = 'nsslapd-pwpolicy-inherit-global' ATTR_CHECK_SYNTAX = 'passwordCheckSyntax' -BN = 'uid=buser,' + DEFAULT_SUFFIX +BN = 'uid=buser,' + OU_PEOPLE TEMP_USER = 'cn=test{}' TEMP_USER_DN = '%s,%s' % (TEMP_USER, OU_PEOPLE) @@ -41,28 +35,21 @@ def create_user(topology_st, request): """User for binding operation""" log.info('Adding user {}'.format(BN)) - try: - topology_st.standalone.add_s(Entry((BN, - {'objectclass': ['top', - 'person', - 'organizationalPerson', - 'inetOrgPerson'], - 'cn': 'bind user', - 'sn': 'bind user', - 'userPassword': PASSWORD}))) - log.info('Adding an aci for the bind user') - BN_ACI = '(targetattr="*")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///%s";)' % BN - ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) - ou_people = ous.get('people') - ou_people.add('aci', BN_ACI) - except ldap.LDAPError as e: - log.error('Failed to add user (%s): error (%s)' % (BN, - e.message['desc'])) - raise e + + users = UserAccounts(topology_st.standalone, OU_PEOPLE, rdn=None) + user_props = TEST_USER_PROPERTIES.copy() + user_props.update({'uid': 'buser', 'cn': 'buser', 'userpassword': PASSWORD}) + user = users.create(properties=user_props) + + log.info('Adding an aci for the bind user') + BN_ACI = '(targetattr="*")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///%s";)' % user.dn + ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) + ou_people = ous.get('people') + ou_people.add('aci', BN_ACI) def fin(): log.info('Deleting user {}'.format(BN)) - topology_st.standalone.delete_s(BN) + user.delete() ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) ou_people = ous.get('people') ou_people.remove('aci', BN_ACI) @@ -80,62 +67,27 @@ def password_policy(topology_st, create_user): """ log.info('Enable fine-grained policy') - try: - topology_st.standalone.config.set('nsslapd-pwpolicy-local', 'on') - except ldap.LDAPError as e: - log.error('Failed to set fine-grained policy: error {}'.format( - e.message['desc'])) - raise e - - log.info('Create password policy for subtree {}'.format(OU_PEOPLE)) - try: - subprocess.call(['%s/ns-newpwpolicy.pl' % topology_st.standalone.get_sbin_dir(), - '-D', DN_DM, '-w', PASSWORD, - '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE, - '-S', OU_PEOPLE, '-Z', SERVERID_STANDALONE]) - except subprocess.CalledProcessError as e: - log.error('Failed to create pw policy policy for {}: error {}'.format( - OU_PEOPLE, e.message['desc'])) - raise e - - log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE)) - try: - ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) - ou_people = ous.get('people') - ou_people.set('pwdpolicysubentry', PWP_CONTAINER_PEOPLE) - except ldap.LDAPError as e: - log.error('Failed to pwdpolicysubentry pw policy ' \ - 'policy for {}: error {}'.format(OU_PEOPLE, - e.message['desc'])) - raise e - - log.info("Set the default settings for the policy container.") - topology_st.standalone.modify_s(PWP_CONTAINER_PEOPLE, - [(ldap.MOD_REPLACE, 'passwordMustChange', b'off'), - (ldap.MOD_REPLACE, 'passwordExp', b'off'), - (ldap.MOD_REPLACE, 'passwordMinAge', b'0'), - (ldap.MOD_REPLACE, 'passwordChange', b'off'), - (ldap.MOD_REPLACE, 'passwordStorageScheme', b'ssha')]) - - check_attr_val(topology_st, CONFIG_DN, ATTR_INHERIT_GLOBAL, 'off') - check_attr_val(topology_st, CONFIG_DN, ATTR_CHECK_SYNTAX, 'off') - - -def check_attr_val(topology_st, dn, attr, expected): + pwp = PwPolicyManager(topology_st.standalone) + policy_props = { + 'passwordMustChange': 'off', + 'passwordExp': 'off', + 'passwordMinAge': '0', + 'passwordChange': 'off', + 'passwordStorageScheme': 'ssha' + } + pwp.create_subtree_policy(OU_PEOPLE, policy_props) + check_attr_val(topology_st.standalone, ATTR_INHERIT_GLOBAL, 'off') + check_attr_val(topology_st.standalone, ATTR_CHECK_SYNTAX, 'off') + + +def check_attr_val(inst, attr, expected): """Check that entry has the value""" - try: - centry = topology_st.standalone.search_s(dn, ldap.SCOPE_BASE, 'cn=*') - assert centry[0], 'Failed to get %s' % dn - - val = centry[0].getValue(attr) - assert str(val, 'utf-8') == expected, 'Default value of %s is not %s, but %s' % ( + val = inst.config.get_attr_val_utf8(attr) + assert val == expected, 'Default value of %s is not %s, but %s' % ( attr, expected, val) - log.info('Default value of %s is %s' % (attr, expected)) - except ldap.LDAPError as e: - log.fatal('Failed to search ' + dn + ': ' + e.message['desc']) - raise e + log.info('Default value of %s is %s' % (attr, expected)) @pytest.mark.parametrize('inherit_value,checksyntax_value', @@ -168,40 +120,27 @@ def test_entry_has_no_restrictions(topology_st, password_policy, create_user, # Wait a second for cn=config to apply time.sleep(1) - check_attr_val(topology_st, CONFIG_DN, ATTR_INHERIT_GLOBAL, inherit_value) - check_attr_val(topology_st, CONFIG_DN, ATTR_CHECK_SYNTAX, checksyntax_value) + check_attr_val(topology_st.standalone, ATTR_INHERIT_GLOBAL, inherit_value) + check_attr_val(topology_st.standalone, ATTR_CHECK_SYNTAX, checksyntax_value) log.info('Bind as test user') topology_st.standalone.simple_bind_s(BN, PASSWORD) log.info('Make sure an entry added to ou=people has ' 'no password syntax restrictions.') - try: - topology_st.standalone.add_s(Entry((TEMP_USER_DN.format('0'), - {'objectclass': ['top', - 'person', - 'organizationalPerson', - 'inetOrgPerson'], - 'cn': TEMP_USER.format('0'), - 'sn': TEMP_USER.format('0'), - 'userPassword': 'short'}))) - except ldap.LDAPError as e: - log.fatal('Failed to add cn=test0 with userPassword: short: ' + - e.message['desc']) - raise e - finally: - log.info('Bind as DM user') - topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) - log.info('Remove {}'.format(TEMP_USER_DN.format('0'))) - try: - topology_st.standalone.delete_s(TEMP_USER_DN.format('0')) - except ldap.NO_SUCH_OBJECT as e: - log.fatal('There is no {}, it is a problem'.format(TEMP_USER_DN.format('0'))) - raise e - - -@pytest.mark.parametrize('container', [DN_CONFIG, PWP_CONTAINER_PEOPLE]) -def test_entry_has_restrictions(topology_st, password_policy, create_user, container): + + users = UserAccounts(topology_st.standalone, OU_PEOPLE, rdn=None) + user_props = TEST_USER_PROPERTIES.copy() + user_props.update({'cn': 'test0', 'userpassword': 'short'}) + user = users.create(properties=user_props) + + topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) + + # Remove test user + user.delete() + + +def test_entry_has_restrictions(topology_st, password_policy, create_user): """Set 'nsslapd-pwpolicy-inherit-global: on' and 'passwordCheckSyntax: on'. Make sure that syntax rules work, if set them at both: cn=config and ou=people policy container. @@ -232,55 +171,35 @@ def test_entry_has_restrictions(topology_st, password_policy, create_user, conta log.info('Set {} to {}'.format(ATTR_CHECK_SYNTAX, 'on')) topology_st.standalone.config.set(ATTR_INHERIT_GLOBAL, 'on') topology_st.standalone.config.set(ATTR_CHECK_SYNTAX, 'on') - topology_st.standalone.modify_s(container, [(ldap.MOD_REPLACE, - 'passwordMinLength', b'9')]) + + pwp = PwPolicyManager(topology_st.standalone) + policy = pwp.get_pwpolicy_entry(OU_PEOPLE) + policy.set('passwordMinLength', '9') # Wait a second for cn=config to apply time.sleep(1) - check_attr_val(topology_st, CONFIG_DN, ATTR_INHERIT_GLOBAL, 'on') - check_attr_val(topology_st, CONFIG_DN, ATTR_CHECK_SYNTAX, 'on') + check_attr_val(topology_st.standalone, ATTR_INHERIT_GLOBAL, 'on') + check_attr_val(topology_st.standalone, ATTR_CHECK_SYNTAX, 'on') log.info('Bind as test user') topology_st.standalone.simple_bind_s(BN, PASSWORD) + users = UserAccounts(topology_st.standalone, OU_PEOPLE, rdn=None) + user_props = TEST_USER_PROPERTIES.copy() log.info('Try to add user with a short password (<9)') with pytest.raises(ldap.CONSTRAINT_VIOLATION): - topology_st.standalone.add_s(Entry((TEMP_USER_DN.format('0'), - {'objectclass': ['top', - 'person', - 'organizationalPerson', - 'inetOrgPerson'], - 'cn': TEMP_USER.format('0'), - 'sn': TEMP_USER.format('0'), - 'userPassword': 'short'}))) + user_props.update({'cn': 'test0', 'userpassword': 'short'}) + user = users.create(properties=user_props) log.info('Try to add user with a long password (>9)') - try: - topology_st.standalone.add_s(Entry((TEMP_USER_DN.format('1'), - {'objectclass': ['top', - 'person', - 'organizationalPerson', - 'inetOrgPerson'], - 'cn': TEMP_USER.format('1'), - 'sn': TEMP_USER.format('1'), - 'userPassword': 'Reallylong1'}))) - except ldap.LDAPError as e: - log.fatal('Failed to add cn=test1 with userPassword: short: ' - + e.message['desc']) - raise e - finally: - log.info('Bind as DM user') - topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) - log.info('Remove {}'.format(TEMP_USER_DN.format('0'))) - try: - topology_st.standalone.delete_s(TEMP_USER_DN.format('0')) - except ldap.NO_SUCH_OBJECT as e: - log.info('There is no {}, it is okay'.format(TEMP_USER_DN.format('0'))) - try: - topology_st.standalone.delete_s(TEMP_USER_DN.format('1')) - except ldap.NO_SUCH_OBJECT as e: - log.fatal('There is no {}, it is a problem'.format(TEMP_USER_DN.format('1'))) - raise e + user_props.update({'cn': 'test1', 'userpassword': 'Reallylong1'}) + user = users.create(properties=user_props) + + log.info('Bind as DM user') + topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) + + # Remove test user 1 + user.delete() if __name__ == '__main__': diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py index 0fd0fdb..4b93307 100644 --- a/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py +++ b/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py @@ -13,11 +13,13 @@ from lib389.tasks import * from lib389.utils import * from lib389.topologies import topology_st from lib389._constants import DEFAULT_SUFFIX, PASSWORD, DN_DM +from lib389.idm.user import UserAccounts +from lib389.idm.organizationalunit import OrganizationalUnits -logging.getLogger(__name__).setLevel(logging.DEBUG) -log = logging.getLogger(__name__) USER_DN = 'uid=user,ou=People,%s' % DEFAULT_SUFFIX +USER_RDN = 'user' +USER_ACI = '(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)' logging.getLogger(__name__).setLevel(logging.INFO) log = logging.getLogger(__name__) @@ -36,65 +38,41 @@ def password_policy(topology_st): @pytest.fixture(scope="module") def create_user(topology_st): """Create the test user.""" - - topology_st.standalone.add_s(Entry(( - USER_DN, { - 'objectClass': 'top account simplesecurityobject'.split(), - 'uid': 'user', - 'description': 'd_e_s_c', - 'userpassword': PASSWORD - }))) + users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX) + users.create(properties={ + 'uid': USER_RDN, + 'cn': USER_RDN, + 'sn': USER_RDN, + 'uidNumber': '3000', + 'gidNumber': '4000', + 'homeDirectory': '/home/user', + 'description': 'd_e_s_c', + 'userPassword': PASSWORD + }) def setPolicy(inst, attr, value): - """Bind as ROot DN, set polcy, and then bind as user""" + """Bind as Root DN, set policy, and then bind as user""" - try: - inst.simple_bind_s(DN_DM, PASSWORD) - except ldap.LDAPError as e: - log.fatal("Failed to bind as Directory Manager: " + str(e)) - assert False + inst.simple_bind_s(DN_DM, PASSWORD) - value = str(value) - """ - if value == '0': - # Remove the policy attribute - try: - inst.modify_s("cn=config", - [(ldap.MOD_DELETE, attr, None)]) - except ldap.LDAPError as e: - log.fatal("Failed to rmeove password policy %s: %s" % - (attr, str(e))) - assert False - else: - """ # Set the policy value + value = str(value) inst.config.set(attr, value) - try: - inst.simple_bind_s(USER_DN, PASSWORD) - except ldap.LDAPError as e: - log.fatal("Failed to bind: " + str(e)) - assert False + inst.simple_bind_s(USER_DN, PASSWORD) def resetPasswd(inst): """Reset the user password for the next test""" # First, bind as the ROOT DN so we can set the password - try: - inst.simple_bind_s(DN_DM, PASSWORD) - except ldap.LDAPError as e: - log.fatal("Failed to bind as Directory Manager: " + str(e)) - assert False + inst.simple_bind_s(DN_DM, PASSWORD) # Now set the password - try: - inst.modify_s(USER_DN, - [(ldap.MOD_REPLACE, 'userpassword', ensure_bytes(PASSWORD))]) - except ldap.LDAPError as e: - log.fatal("Failed to reset user password: " + str(e)) - assert False + users = UserAccounts(inst, DEFAULT_SUFFIX) + user = users.get(USER_RDN) + user.reset_password(PASSWORD) def tryPassword(inst, policy_attr, value, reset_value, pw_bad, pw_good, msg): @@ -105,9 +83,10 @@ def tryPassword(inst, policy_attr, value, reset_value, pw_bad, pw_good, msg): """ setPolicy(inst, policy_attr, value) + users = UserAccounts(inst, DEFAULT_SUFFIX) + user = users.get(USER_RDN) try: - inst.modify_s(USER_DN, - [(ldap.MOD_REPLACE, 'userpassword', ensure_bytes(pw_bad))]) + user.reset_password(pw_bad) log.fatal('Invalid password was unexpectedly accepted (%s)' % (policy_attr)) assert False @@ -120,12 +99,7 @@ def tryPassword(inst, policy_attr, value, reset_value, pw_bad, pw_good, msg): assert False # Change password that is allowed - try: - inst.modify_s(USER_DN, - [(ldap.MOD_REPLACE, 'userpassword', ensure_bytes(pw_good))]) - except ldap.LDAPError as e: - log.fatal("Failed to change password: " + str(e)) - assert False + user.reset_password(pw_good) # Reset for the next test resetPasswd(inst) @@ -234,6 +208,9 @@ def test_basic(topology_st, create_user, password_policy): # # Test each syntax category # + ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) + ou = ous.get('people') + ou.add('aci', USER_ACI) # Min Length tryPassword(topology_st.standalone, 'passwordMinLength', 10, 2, 'passwd', diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_token_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_token_test.py index 7a4de9c..b0bab20 100644 --- a/dirsrvtests/tests/suites/password/pwdPolicy_token_test.py +++ b/dirsrvtests/tests/suites/password/pwdPolicy_token_test.py @@ -5,6 +5,7 @@ import time import ldap from lib389._constants import * from lib389.idm.user import UserAccounts +from lib389.idm.organizationalunit import OrganizationalUnits from lib389.topologies import topology_st as topo DEBUGGING = os.getenv("DEBUGGING", default=False) @@ -15,6 +16,7 @@ else: log = logging.getLogger(__name__) USER_DN = 'uid=Test_user1,ou=People,dc=example,dc=com' +USER_ACI = '(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)' TOKEN = 'test_user1' user_properties = { @@ -29,6 +31,10 @@ user_properties = { def pwd_setup(topo): + ous = OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX) + ou = ous.get('people') + ou.add('aci', USER_ACI) + topo.standalone.config.replace_many(('passwordCheckSyntax', 'on'), ('passwordMinLength', '4'), ('passwordMinCategories', '1')) diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py index ef840c7..eb28b71 100644 --- a/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py +++ b/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py @@ -13,14 +13,17 @@ from lib389.tasks import * from lib389.utils import * from lib389.topologies import topology_st from lib389.idm.user import UserAccounts +from lib389.idm.organizationalunit import OrganizationalUnits from lib389._constants import (DEFAULT_SUFFIX, DN_CONFIG, PASSWORD, DN_DM, HOST_STANDALONE, PORT_STANDALONE, SERVERID_STANDALONE) from dateutil.parser import parse as dt_parse import datetime CONFIG_ATTR = 'passwordSendExpiringTime' -USER_DN = 'uid=tuser,{}'.format(DEFAULT_SUFFIX) +USER_DN = 'uid=tuser,ou=people,{}'.format(DEFAULT_SUFFIX) +USER_RDN = 'tuser' USER_PASSWD = 'secret123' +USER_ACI = '(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)' logging.getLogger(__name__).setLevel(logging.INFO) log = logging.getLogger(__name__) @@ -50,13 +53,14 @@ def global_policy(topology_st, request): ('passwordMaxAge', '172800'), ('passwordWarning', '86400'), (CONFIG_ATTR, 'on')) + def fin(): """Resets the defaults""" log.info('Reset the defaults') + topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) for key in attrs.keys(): - topology_st.standalone.modify_s(DN_CONFIG, [ - (ldap.MOD_REPLACE, key, ensure_bytes(attrs[key]))]) + topology_st.standalone.config.replace(key, attrs[key]) request.addfinalizer(fin) # A short sleep is required after the modifying password policy or cn=config @@ -82,20 +86,19 @@ def global_policy_default(topology_st, request): attrs[key] = entry.getValue(key) log.info('Set the new values') - topology_st.standalone.modify_s(DN_CONFIG, [ - (ldap.MOD_REPLACE, 'passwordExp', b'on'), - (ldap.MOD_REPLACE, 'passwordMaxAge', b'8640000'), - (ldap.MOD_REPLACE, 'passwordWarning', b'86400'), - (ldap.MOD_REPLACE, CONFIG_ATTR, b'off')]) + topology_st.standalone.config.replace_many( + ('passwordExp', 'on'), + ('passwordMaxAge', '8640000'), + ('passwordWarning', '86400'), + (CONFIG_ATTR, 'off')) def fin(): """Resets the defaults""" log.info('Reset the defaults') + topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) for key in attrs.keys(): - topology_st.standalone.modify_s(DN_CONFIG, [ - (ldap.MOD_REPLACE, key, ensure_bytes(attrs[key])) - ]) + topology_st.standalone.config.replace(key, attrs[key]) request.addfinalizer(fin) # A short sleep is required after modifying password policy or cn=config @@ -106,21 +109,26 @@ def global_policy_default(topology_st, request): def add_user(topology_st, request): """Adds a user for binding""" - user_data = {'objectClass': b'top person inetOrgPerson'.split(), - 'uid': b'tuser', - 'cn': b'test user', - 'sn': b'user', - 'userPassword': USER_PASSWD} - log.info('Add the user') - topology_st.standalone.add_s(Entry((USER_DN, user_data))) + users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX) + user = users.create(properties={ + 'uid': USER_RDN, + 'cn': USER_RDN, + 'sn': USER_RDN, + 'uidNumber': '3000', + 'gidNumber': '4000', + 'homeDirectory': '/home/user', + 'description': 'd_e_s_c', + 'userPassword': USER_PASSWD + }) def fin(): """Removes the user entry""" log.info('Remove the user entry') - topology_st.standalone.delete_s(USER_DN) + topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) + user.delete() request.addfinalizer(fin) @@ -160,67 +168,15 @@ def set_conf_attr(topology_st, attr, val): """Sets the value of a given attribute under cn=config""" log.info("Setting {} to {}".format(attr, val)) - topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, attr, ensure_bytes(val))]) + topology_st.standalone.config.set(attr, val) # A short sleep is required after modifying cn=config time.sleep(0.5) def get_conf_attr(topology_st, attr): - """Gets the value of a given - attribute under cn=config entry - """ - - entry = topology_st.standalone.getEntry(DN_CONFIG, ldap.SCOPE_BASE, - '(objectClass=*)', [attr]) - val = entry.getValue(attr) - # Return the value if no exeception is raised - return val - - -@pytest.mark.parametrize("value", (' ', 'junk123', 'on', 'off')) -def test_different_values(topology_st, value): - """Try to set passwordSendExpiringTime attribute - to various values both valid and invalid - - :id: 3e6d79fb-b4c8-4860-897e-5b207815a75d - :setup: Standalone instance - :steps: - 1. Try to set passwordSendExpiringTime to 'on' and 'off' - under cn=config entry - 2. Try to set passwordSendExpiringTime to ' ' and 'junk123' - under cn=config entry - 3. Run the search command to check the - value of passwordSendExpiringTime attribute - :expectedresults: - 1. Valid values should be accepted and saved - 2. Should be rejected with an OPERATIONS_ERROR - 3. The attribute should be changed for valid values - and unchanged for invalid + """Gets the value of a given attribute under cn=config entry """ - - log.info('Get the default value') - defval = get_conf_attr(topology_st, CONFIG_ATTR) - - if value not in ('on', 'off'): - log.info('An invalid value is being tested') - with pytest.raises(ldap.OPERATIONS_ERROR): - set_conf_attr(topology_st, CONFIG_ATTR, value) - - log.info('Now check the value is unchanged') - assert get_conf_attr(topology_st, CONFIG_ATTR) == defval - - log.info("Invalid value {} was rejected correctly".format(value)) - else: - log.info('A valid value is being tested') - set_conf_attr(topology_st, CONFIG_ATTR, value) - - log.info('Now check that the value has been changed') - assert get_conf_attr(topology_st, CONFIG_ATTR) == value - - log.info("{} is now set to {}".format(CONFIG_ATTR, value)) - - log.info('Set passwordSendExpiringTime back to the default value') - set_conf_attr(topology_st, CONFIG_ATTR, defval) + return topology_st.standalone.config.get_attr_val_utf8(attr) @pytest.mark.parametrize("value", (' ', 'junk123', 'on', 'off')) @@ -261,7 +217,7 @@ def test_different_values(topology_st, value): set_conf_attr(topology_st, CONFIG_ATTR, value) log.info('Now check that the value has been changed') - assert str(get_conf_attr(topology_st, CONFIG_ATTR), 'utf-8') == value + assert str(get_conf_attr(topology_st, CONFIG_ATTR)) == value log.info("{} is now set to {}".format(CONFIG_ATTR, value)) @@ -292,15 +248,19 @@ def test_expiry_time(topology_st, global_policy, add_user): res_ctrls = None + ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) + ou = ous.get('people') + ou.add('aci', USER_ACI) + log.info('Get the password expiry warning time') - log.info("Binding with ({}) and requesting the password expiry warning time" \ + log.info("Binding with ({}) and requesting the password expiry warning time" .format(USER_DN)) res_ctrls = get_password_warning(topology_st) log.info('Check whether the time is returned') assert res_ctrls - log.info("user's password will expire in {:d} seconds" \ + log.info("user's password will expire in {:d} seconds" .format(res_ctrls[0].timeBeforeExpiration)) log.info("Rebinding as DM") @@ -337,16 +297,16 @@ def test_password_warning(topology_st, global_policy, add_user, attr, val): log.info('Set configuration parameter') set_conf_attr(topology_st, attr, val) - log.info("Binding with ({}) and requesting password expiry warning time" \ + log.info("Binding with ({}) and requesting password expiry warning time" .format(USER_DN)) res_ctrls = get_password_warning(topology_st) log.info('Check the state of the control') if not res_ctrls: - log.info("Password Expiry warning time is not returned as {} is set to {}" \ + log.info("Password Expiry warning time is not returned as {} is set to {}" .format(attr, val)) else: - log.info("({}) password will expire in {:d} seconds" \ + log.info("({}) password will expire in {:d} seconds" .format(USER_DN, res_ctrls[0].timeBeforeExpiration)) log.info("Rebinding as DM") @@ -382,18 +342,17 @@ def test_with_different_password_states(topology_st, global_policy, add_user): res_ctrls = None - log.info("Expire user's password by changing" \ - "passwordExpirationTime timestamp") - old_ts = topology_st.standalone.search_s(USER_DN, ldap.SCOPE_SUBTREE, - '(objectClass=*)', ['passwordExpirationTime'])[0].getValue( - 'passwordExpirationTime') + log.info("Expire user's password by changing passwordExpirationTime timestamp") + users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX) + user = users.get(USER_RDN) + old_ts = user.get_attr_val_utf8('passwordExpirationTime') log.info("Old passwordExpirationTime: {}".format(old_ts)) + new_ts = (dt_parse(old_ts) - datetime.timedelta(31)).strftime('%Y%m%d%H%M%SZ') log.info("New passwordExpirationTime: {}".format(new_ts)) - topology_st.standalone.modify_s(USER_DN, [(ldap.MOD_REPLACE, 'passwordExpirationTime', ensure_bytes(new_ts))]) + user.replace('passwordExpirationTime', new_ts) - log.info("Attempting to bind with user {} and retrive the password" \ - " expiry warning time".format(USER_DN)) + log.info("Attempting to bind with user {} and retrive the password expiry warning time".format(USER_DN)) with pytest.raises(ldap.INVALID_CREDENTIALS) as ex: res_ctrls = get_password_warning(topology_st) @@ -403,16 +362,16 @@ def test_with_different_password_states(topology_st, global_policy, add_user): topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) log.info("Reverting back user's passwordExpirationTime") - topology_st.standalone.modify_s(USER_DN, [(ldap.MOD_REPLACE, 'passwordExpirationTime', ensure_bytes(old_ts))]) - log.info("Rebinding with {} and retrieving the password" \ - " expiry warning time".format(USER_DN)) + user.replace('passwordExpirationTime', old_ts) + + log.info("Rebinding with {} and retrieving the password expiry warning time".format(USER_DN)) res_ctrls = get_password_warning(topology_st) log.info('Check that the control is returned') assert res_ctrls - log.info("user's password will expire in {:d} seconds" \ + log.info("user's password will expire in {:d} seconds" .format(res_ctrls[0].timeBeforeExpiration)) log.info("Rebinding as DM") @@ -441,7 +400,7 @@ def test_default_behavior(topology_st, global_policy_default, add_user): res_ctrls = None - log.info("Binding with {} and requesting the password expiry warning time" \ + log.info("Binding with {} and requesting the password expiry warning time" .format(USER_DN)) res_ctrls = get_password_warning(topology_st) @@ -482,11 +441,12 @@ def test_when_maxage_and_warning_are_the_same(topology_st, global_policy_default res_ctrls = None log.info("First change user's password to reset its password expiration time") - topology_st.standalone.simple_bind_s(USER_DN, USER_PASSWD) + users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX) + user = users.get(USER_RDN) + user.rebind(USER_PASSWD) + user.reset_password(USER_PASSWD) - topology_st.standalone.modify_s(USER_DN, [(ldap.MOD_REPLACE, - 'userPassword', ensure_bytes(USER_PASSWD))]) - log.info("Binding with {} and requesting the password expiry warning time" \ + log.info("Binding with {} and requesting the password expiry warning time" .format(USER_DN)) res_ctrls = get_password_warning(topology_st) @@ -494,8 +454,7 @@ def test_when_maxage_and_warning_are_the_same(topology_st, global_policy_default 'if passwordSendExpiringTime is set to off') assert res_ctrls - log.info("user's password will expire in {:d} seconds" \ - .format(res_ctrls[0].timeBeforeExpiration)) + log.info("user's password will expire in {:d} seconds".format(res_ctrls[0].timeBeforeExpiration)) log.info("Rebinding as DM") topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) @@ -524,8 +483,7 @@ def test_with_local_policy(topology_st, global_policy, local_policy): res_ctrls = None - log.info("Attempting to get password expiry warning time for" \ - " user {}".format(USER_DN)) + log.info("Attempting to get password expiry warning time for user {}".format(USER_DN)) res_ctrls = get_password_warning(topology_st) log.info('Check that the control is not returned') @@ -580,10 +538,8 @@ def test_search_shadowWarning_when_passwordWarning_is_lower(topology_st, global_ assert topology_st.standalone.simple_bind_s(testuser.dn, USER_PASSWD) log.info("Check if attribute shadowWarning is present") - assert testuser.present('shadowWarning') - - log.info("Rebinding as DM") topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) + assert testuser.present('shadowWarning') if __name__ == '__main__': diff --git a/dirsrvtests/tests/suites/password/pwd_algo_test.py b/dirsrvtests/tests/suites/password/pwd_algo_test.py index ebc617e..77c549a 100644 --- a/dirsrvtests/tests/suites/password/pwd_algo_test.py +++ b/dirsrvtests/tests/suites/password/pwd_algo_test.py @@ -1,5 +1,5 @@ # --- BEGIN COPYRIGHT BLOCK --- -# Copyright (C) 2016 Red Hat, Inc. +# Copyright (C) 2019 Red Hat, Inc. # All rights reserved. # # License: GPL (version 3 or any later version). @@ -10,8 +10,8 @@ import pytest from lib389.tasks import * from lib389.utils import * from lib389.topologies import topology_st -from lib389._constants import DEFAULT_SUFFIX, HOST_STANDALONE, DN_DM, PORT_STANDALONE -from lib389.idm.user import UserAccounts +from lib389._constants import DEFAULT_SUFFIX, HOST_STANDALONE, PORT_STANDALONE +from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES DEBUGGING = os.getenv('DEBUGGING', False) USER_DN = 'uid=user,ou=People,%s' % DEFAULT_SUFFIX @@ -19,6 +19,7 @@ USER_DN = 'uid=user,ou=People,%s' % DEFAULT_SUFFIX logging.getLogger(__name__).setLevel(logging.INFO) log = logging.getLogger(__name__) + def _test_bind(user, password): result = True try: @@ -33,16 +34,9 @@ def _test_algo(inst, algo_name): inst.config.set('passwordStorageScheme', algo_name) users = UserAccounts(inst, DEFAULT_SUFFIX) - - user = users.create(properties={ - 'uid': 'user', - 'cn' : 'user', - 'sn' : 'user', - 'uidNumber' : '1000', - 'gidNumber' : '2000', - 'homeDirectory' : '/home/user', - 'userpassword': 'Secret123' - }) + user_props = TEST_USER_PROPERTIES.copy() + user_props.update({'uid': 'user', 'cn': 'buser', 'userpassword': 'Secret123'}) + user = users.create(properties=user_props) # Make sure when we read the userPassword field, it is the correct ALGO pw_field = user.get_attr_val_utf8('userPassword') @@ -64,9 +58,10 @@ def _test_algo(inst, algo_name): assert (not _test_bind(user, 'Secret12')) # Bind with a superset password, should fail assert (not _test_bind(user, 'Secret123456')) + # Delete the user user.delete() - # done! + def _test_bind_for_pbkdf2_algo(inst, password): result = True @@ -86,23 +81,21 @@ def _test_algo_for_pbkdf2(inst, algo_name): print('Testing %s' % algo_name) # Create the user with a password - inst.add_s(Entry(( - USER_DN, { - 'objectClass': 'top account simplesecurityobject'.split(), - 'uid': 'user', - 'userpassword': ['Secret123', ] - }))) + users = UserAccounts(inst, DEFAULT_SUFFIX) + user_props = TEST_USER_PROPERTIES.copy() + user_props.update({'uid': 'user', 'cn': 'buser', 'userpassword': 'Secret123'}) + user = users.create(properties=user_props) # Make sure when we read the userPassword field, it is the correct ALGO - pw_field = inst.search_s(USER_DN, ldap.SCOPE_BASE, '(objectClass=*)', ['userPassword'])[0] + pw_field = user.get_attr_val_utf8_l('userPassword') if DEBUGGING: - print(pw_field.getValue('userPassword')) + print(pw_field) if algo_name != 'CLEAR': lalgo_name = algo_name.lower() - lpw_algo_name = pw_field.getValue('userPassword').lower() - assert (lpw_algo_name.startswith(ensure_bytes('{'+lalgo_name+'}'))) + assert (pw_field.startswith('{' + lalgo_name + '}')) + # Now make sure a bind works assert (_test_bind_for_pbkdf2_algo(inst, 'Secret123')) # Bind with a wrong shorter password, should fail @@ -120,24 +113,26 @@ def _test_algo_for_pbkdf2(inst, algo_name): assert (not _test_bind_for_pbkdf2_algo(inst, 'Secret12')) # Bind with a superset password, should fail assert (not _test_bind_for_pbkdf2_algo(inst, 'Secret123456')) + # Delete the user inst.delete_s(USER_DN) - # done! + @pytest.mark.parametrize("algo", ('CLEAR', 'CRYPT', 'CRYPT-MD5', 'CRYPT-SHA256', 'CRYPT-SHA512', 'MD5', 'SHA', 'SHA256', 'SHA384', 'SHA512', 'SMD5', 'SSHA', - 'SSHA256', 'SSHA384', 'SSHA512', 'PBKDF2_SHA256', 'DEFAULT',) ) + 'SSHA256', 'SSHA384', 'SSHA512', 'PBKDF2_SHA256', 'DEFAULT',)) def test_pwd_algo_test(topology_st, algo): """Assert that all of our password algorithms correctly PASS and FAIL varying password conditions. """ if algo == 'DEFAULT': - if ds_is_older('1.4.0'): - pytest.skip("Not implemented") + if ds_is_older('1.4.0'): + pytest.skip("Not implemented") _test_algo(topology_st.standalone, algo) log.info('Test %s PASSED' % algo) + @pytest.mark.ds397 def test_pbkdf2_algo(topology_st): """Changing password storage scheme to PBKDF2_SHA256 diff --git a/dirsrvtests/tests/suites/password/pwd_log_test.py b/dirsrvtests/tests/suites/password/pwd_log_test.py index a113228..1bf1b50 100644 --- a/dirsrvtests/tests/suites/password/pwd_log_test.py +++ b/dirsrvtests/tests/suites/password/pwd_log_test.py @@ -1,5 +1,5 @@ # --- BEGIN COPYRIGHT BLOCK --- -# Copyright (C) 2016 Red Hat, Inc. +# Copyright (C) 2019 Red Hat, Inc. # All rights reserved. # # License: GPL (version 3 or any later version). @@ -8,16 +8,16 @@ # import logging - import pytest from lib389.tasks import * from lib389.topologies import topology_st - +from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES from lib389._constants import DN_CONFIG, DEFAULT_SUFFIX logging.getLogger(__name__).setLevel(logging.DEBUG) log = logging.getLogger(__name__) + @pytest.mark.ds365 def test_hide_unhashed_pwd(topology_st): """Change userPassword, enable hiding of un-hashed @@ -41,45 +41,19 @@ def test_hide_unhashed_pwd(topology_st): 6. Audit logs should hide password which is un-hashed """ - USER_DN = 'uid=test_entry,' + DEFAULT_SUFFIX + users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX) + user_props = TEST_USER_PROPERTIES.copy() + user_props.update({'uid': 'user', 'cn': 'buser', 'userpassword': 'Secret123'}) + user = users.create(properties=user_props) - # - # Add the test entry - # - topology_st.standalone.add_s(Entry((USER_DN, { - 'objectclass': 'top extensibleObject'.split(), - 'uid': 'test_entry', - 'userpassword': 'password' - }))) - - # # Enable the audit log - # - topology_st.standalone.modify_s(DN_CONFIG, - [(ldap.MOD_REPLACE, - 'nsslapd-auditlog-logging-enabled', - b'on')]) - ''' - try: - ent = topology_st.standalone.getEntry(DN_CONFIG, attrlist=[ - 'nsslapd-instancedir', - 'nsslapd-errorlog', - 'nsslapd-accesslog', - 'nsslapd-certdir', - 'nsslapd-schemadir']) - ''' - # + topology_st.standalone.config.set('nsslapd-auditlog-logging-enabled','on') + # Allow the unhashed password to be written to audit log - # - topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, - 'nsslapd-auditlog-logging-hide-unhashed-pw', b'off')]) + topology_st.standalone.config.set('nsslapd-auditlog-logging-hide-unhashed-pw', 'off') - # # Set new password, and check the audit log - # - topology_st.standalone.modify_s(USER_DN, [(ldap.MOD_REPLACE, - 'userpassword', - b'mypassword')]) + user.reset_password('mypassword') # Check audit log time.sleep(1) @@ -87,21 +61,11 @@ def test_hide_unhashed_pwd(topology_st): log.fatal('failed to find unhashed password in auditlog') assert False - # # Hide unhashed password in audit log - # - topology_st.standalone.modify_s(DN_CONFIG, - [(ldap.MOD_REPLACE, - 'nsslapd-auditlog-logging-hide-unhashed-pw', - b'on')]) - log.info('Test complete') + topology_st.standalone.config.set('nsslapd-auditlog-logging-hide-unhashed-pw', 'on') - # # Modify password, and check the audit log - # - topology_st.standalone.modify_s(USER_DN, [(ldap.MOD_REPLACE, - 'userpassword', - b'hidepassword')]) + user.reset_password('hidepassword') # Check audit log time.sleep(1) diff --git a/dirsrvtests/tests/suites/password/pwp_history_test.py b/dirsrvtests/tests/suites/password/pwp_history_test.py index 5972e82..4580d7c 100644 --- a/dirsrvtests/tests/suites/password/pwp_history_test.py +++ b/dirsrvtests/tests/suites/password/pwp_history_test.py @@ -12,6 +12,7 @@ from lib389.tasks import * from lib389.utils import * from lib389.topologies import topology_st from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES +from lib389.idm.organizationalunit import OrganizationalUnits from lib389._constants import DN_DM, DEFAULT_SUFFIX, PASSWORD logging.getLogger(__name__).setLevel(logging.DEBUG) @@ -71,6 +72,13 @@ def test_basic(topology_st): assert False time.sleep(1) + # Add aci so users can change their own password + USER_ACI = '(targetattr="userpassword || passwordHistory")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)' + ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) + ou = ous.get('people') + ou.add('aci', USER_ACI) + + # Create user users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX) user = users.create(properties=TEST_USER_PROPERTIES) user.set('userpassword', 'password') diff --git a/dirsrvtests/tests/suites/password/regression_test.py b/dirsrvtests/tests/suites/password/regression_test.py index 6890e33..7afce41 100644 --- a/dirsrvtests/tests/suites/password/regression_test.py +++ b/dirsrvtests/tests/suites/password/regression_test.py @@ -7,12 +7,10 @@ # import pytest import time -from lib389._constants import SUFFIX, PASSWORD, DN_DM, DN_CONFIG, PLUGIN_RETRO_CHANGELOG, DEFAULT_SUFFIX, DEFAULT_CHANGELOG_DB -from lib389 import Entry +from lib389._constants import PASSWORD, DN_DM, DEFAULT_SUFFIX from lib389.idm.user import UserAccounts -from lib389.utils import ldap, os, logging, ensure_bytes +from lib389.utils import ldap, os, logging from lib389.topologies import topology_st as topo -from lib389.topologies import topology_m1 as topo_master from lib389.idm.organizationalunit import OrganizationalUnits DEBUGGING = os.getenv("DEBUGGING", default=False) @@ -47,8 +45,7 @@ def passw_policy(topo, request): topo.standalone.config.set('PasswordCheckSyntax', 'off') topo.standalone.config.set('nsslapd-pwpolicy-local', 'on') - subtree = 'ou=people,{}'.format(SUFFIX) - print(subtree) + subtree = 'ou=people,{}'.format(DEFAULT_SUFFIX) log.info('Configure subtree password policy for {}'.format(subtree)) topo.standalone.subtreePwdPolicy(subtree, {'passwordchange': b'on', 'passwordCheckSyntax': b'on', @@ -60,6 +57,7 @@ def passw_policy(topo, request): def fin(): log.info('Reset pwpolicy configuration settings') + topo.standalone.simple_bind_s(DN_DM, PASSWORD) topo.standalone.config.set('PasswordExp', 'off') topo.standalone.config.set('PasswordCheckSyntax', 'off') topo.standalone.config.set('nsslapd-pwpolicy-local', 'off') @@ -71,11 +69,12 @@ def passw_policy(topo, request): def create_user(topo, request): """Add test users using UserAccounts""" - log.info('Adding user-uid={},ou=people,{}'.format(user_data['uid'], SUFFIX)) - users = UserAccounts(topo.standalone, SUFFIX) + log.info('Adding user-uid={},ou=people,{}'.format(user_data['uid'], DEFAULT_SUFFIX)) + users = UserAccounts(topo.standalone, DEFAULT_SUFFIX) user_properties = { 'uidNumber': '1001', 'gidNumber': '2001', + 'cn': 'pwtest1', 'userpassword': PASSWORD, 'homeDirectory': '/home/pwtest1'} user_properties.update(user_data) @@ -103,6 +102,11 @@ def test_pwp_local_unlock(topo, passw_policy, create_user): 2. Entry is locked 3. Entry can bind with correct password """ + # Add aci so users can change their own password + USER_ACI = '(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)' + ous = OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX) + ou = ous.get('people') + ou.add('aci', USER_ACI) log.info("Verify user can bind...") create_user.bind(PASSWORD) @@ -115,7 +119,7 @@ def test_pwp_local_unlock(topo, passw_policy, create_user): # expected pass except ldap.LDAPError as e: - log.fatal("Got unexpected failure: " + atr(e)) + log.fatal("Got unexpected failure: " + str(e)) raise e log.info('Verify account is locked') @@ -148,16 +152,16 @@ def test_trivial_passw_check(topo, passw_policy, create_user, user_pasw): 4. Resetting userPassword to cn, sn, uid and mail should be rejected. """ - conn = create_user.bind(PASSWORD) - try: - log.info('Replace userPassword attribute with {}'.format(user_pasw)) - with pytest.raises(ldap.CONSTRAINT_VIOLATION) as excinfo: - conn.modify_s(create_user.dn, [(ldap.MOD_REPLACE, 'userPassword', ensure_bytes(user_pasw))]) - log.fatal('Failed: Userpassword with {} is accepted'.format(user_pasw)) - assert 'password based off of user entry' in str(excinfo.value) - finally: - conn.unbind_s() - create_user.set('userPassword', PASSWORD) + create_user.rebind(PASSWORD) + log.info('Replace userPassword attribute with {}'.format(user_pasw)) + with pytest.raises(ldap.CONSTRAINT_VIOLATION) as excinfo: + create_user.reset_password(user_pasw) + log.fatal('Failed: Userpassword with {} is accepted'.format(user_pasw)) + assert 'password based off of user entry' in str(excinfo.value) + + # reset password + topo.standalone.simple_bind_s(DN_DM, PASSWORD) + create_user.set('userPassword', PASSWORD) @pytest.mark.parametrize("user_pasw", TEST_PASSWORDS) @@ -177,19 +181,15 @@ def test_global_vs_local(topo, passw_policy, create_user, user_pasw): """ log.info('Configure Pwpolicy with PasswordCheckSyntax and nsslapd-pwpolicy-local set to off') + topo.standalone.simple_bind_s(DN_DM, PASSWORD) topo.standalone.config.set('nsslapd-pwpolicy-local', 'off') - conn = create_user.bind(PASSWORD) + create_user.rebind(PASSWORD) log.info('Replace userPassword attribute with {}'.format(user_pasw)) - try: - try: - conn.modify_s(create_user.dn, [(ldap.MOD_REPLACE, 'userPassword', ensure_bytes(user_pasw))]) - except ldap.LDAPError as e: - log.fatal('Failed to replace userPassword: error {}'.format(e.message['desc'])) - raise e - finally: - conn.unbind_s() - create_user.set('userPassword', PASSWORD) + create_user.reset_password(user_pasw) + + # reset password + create_user.set('userPassword', PASSWORD) if __name__ == '__main__': diff --git a/src/lib389/lib389/cli_conf/pwpolicy.py b/src/lib389/lib389/cli_conf/pwpolicy.py index b972aeb..f911997 100644 --- a/src/lib389/lib389/cli_conf/pwpolicy.py +++ b/src/lib389/lib389/cli_conf/pwpolicy.py @@ -8,7 +8,7 @@ import json import ldap -from lib389.utils import ensure_str, ensure_list_str +from lib389.utils import ensure_str from lib389.pwpolicy import PwPolicyEntries, PwPolicyManager from lib389.idm.account import Account diff --git a/src/lib389/lib389/pwpolicy.py b/src/lib389/lib389/pwpolicy.py index 19ca29d..bd6071e 100644 --- a/src/lib389/lib389/pwpolicy.py +++ b/src/lib389/lib389/pwpolicy.py @@ -24,54 +24,48 @@ class PwPolicyManager(object): def __init__(self, instance): self._instance = instance self.log = instance.log - self.arg_to_attr = { - 'pwdlocal': 'nsslapd-pwpolicy-local', - 'pwdscheme': 'passwordstoragescheme', - 'pwdchange': 'passwordChange', - 'pwdmustchange': 'passwordMustChange', - 'pwdhistory': 'passwordHistory', - 'pwdhistorycount': 'passwordInHistory', - 'pwdadmin': 'passwordAdminDN', - 'pwdtrack': 'passwordTrackUpdateTime', - 'pwdwarning': 'passwordWarning', - 'pwdisglobal': 'passwordIsGlobalPolicy', - 'pwdexpire': 'passwordExp', - 'pwdmaxage': 'passwordMaxAge', - 'pwdminage': 'passwordMinAge', - 'pwdgracelimit': 'passwordGraceLimit', - 'pwdsendexpiring': 'passwordSendExpiringTime', - 'pwdlockout': 'passwordLockout', - 'pwdunlock': 'passwordUnlock', - 'pwdlockoutduration': 'passwordLockoutDuration', - 'pwdmaxfailures': 'passwordMaxFailure', - 'pwdresetfailcount': 'passwordResetFailureCount', - 'pwdchecksyntax': 'passwordCheckSyntax', - 'pwdminlen': 'passwordMinLength', - 'pwdmindigits': 'passwordMinDigits', - 'pwdminalphas': 'passwordMinAlphas', - 'pwdminuppers': 'passwordMinUppers', - 'pwdminlowers': 'passwordMinLowers', - 'pwdminspecials': 'passwordMinSpecials', - 'pwdmin8bits': 'passwordMin8bit', - 'pwdmaxrepeats': 'passwordMaxRepeats', - 'pwdpalindrome': 'passwordPalindrome', - 'pwdmaxseq': 'passwordMaxSequence', - 'pwdmaxseqsets': 'passwordMaxSeqSets', - 'pwdmaxclasschars': 'passwordMaxClassChars', - 'pwdmincatagories': 'passwordMinCategories', - 'pwdmintokenlen': 'passwordMinTokenLength', - 'pwdbadwords': 'passwordBadWords', - 'pwduserattrs': 'passwordUserAttributes', - 'pwddictcheck': 'passwordDictCheck', - 'pwddictpath': 'passwordDictPath', - 'pwdallowhash': 'nsslapd-allow-hashed-passwords' - } - - def get_attr_list(self): - attr_list = [] - for arg, attr in list(self.arg_to_attr.items()): - attr_list.append(attr) - return attr_list + self.pwp_attributes = [ + 'passwordstoragescheme', + 'passwordChange', + 'passwordMustChange', + 'passwordHistory', + 'passwordInHistory', + 'passwordAdminDN', + 'passwordTrackUpdateTime', + 'passwordWarning', + 'passwordMaxAge', + 'passwordMinAge', + 'passwordExp', + 'passwordGraceLimit', + 'passwordSendExpiringTime', + 'passwordLockout', + 'passwordUnlock', + 'passwordMaxFailure', + 'passwordLockoutDuration', + 'passwordResetFailureCount', + 'passwordCheckSyntax', + 'passwordMinLength', + 'passwordMinDigits', + 'passwordMinAlphas', + 'passwordMinUppers', + 'passwordMinLowers', + 'passwordMinSpecials', + 'passwordMaxRepeats', + 'passwordMin8bit', + 'passwordMinCategories', + 'passwordMinTokenLength', + 'passwordDictPath', + 'passwordDictCheck', + 'passwordPalindrome', + 'passwordMaxSequence', + 'passwordMaxClassChars', + 'passwordMaxSeqSets', + 'passwordBadWords', + 'passwordUserAttributes', + 'passwordIsGlobalPolicy', + 'nsslapd-pwpolicy-local', + 'nsslapd-allow-hashed-passwords' + ] def is_subtree_policy(self, dn): """Check if the entry has a subtree password policy. If we can find a @@ -83,7 +77,11 @@ class PwPolicyManager(object): :returns: True if the entry has a subtree policy, False otherwise """ cos_templates = CosTemplates(self._instance, 'cn=nsPwPolicyContainer,{}'.format(dn)) - return cos_templates.exists('cn=nsPwTemplateEntry,%s' % dn) + try: + cos_templates.get('cn=nsPwTemplateEntry,%s' % dn) + return True + except: + return False def create_user_policy(self, dn, properties): """Creates all entries which are needed for the user diff --git a/src/lib389/lib389/utils.py b/src/lib389/lib389/utils.py index afc8951..a7c1d75 100644 --- a/src/lib389/lib389/utils.py +++ b/src/lib389/lib389/utils.py @@ -283,7 +283,7 @@ def selinux_label_port(port, remove_label=False): raise ValueError("Port {} was already labelled with: ({}) Please choose a different port number".format(port, policy['type'])) if (remove_label and label_set) or (not remove_label and not label_set): - for i in range(3): + for i in range(5): try: subprocess.check_call(["semanage", "port",