#50256 Ticket 50255 - Port password policy test to use DSLdapObject
Closed 3 years ago by spichugi. Opened 5 years ago by mreynolds.
mreynolds/389-ds-base port_citest  into  master

@@ -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.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 @@ 

  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 @@ 

      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 @@ 

          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 @@ 

          '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 @@ 

        """

  

      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 @@ 

          '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 @@ 

          'homeDirectory': '/home/test_user0',

          'userPassword': OLD_PASSWD

          })

+ 

      test_user1 = user.create(properties={

          'uid': 'test_user1',

          'cn': 'test1',
@@ -249,15 +259,18 @@ 

          '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__':

@@ -10,11 +10,10 @@ 

  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 @@ 

  @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 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 @@ 

          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 @@ 

      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 @@ 

      """

  

      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 @@ 

      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__':

@@ -5,8 +5,10 @@ 

  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 @@ 

      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 @@ 

      """

      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 @@ 

      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)

@@ -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 @@ 

      """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 @@ 

      """

  

      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 @@ 

  

      # 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 @@ 

      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__':

@@ -13,11 +13,13 @@ 

  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 @@ 

  @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 @@ 

      """

  

      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 @@ 

          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 @@ 

      #

      # 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',

@@ -5,6 +5,7 @@ 

  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 @@ 

  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 @@ 

  

  

  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'))

@@ -13,14 +13,17 @@ 

  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 @@ 

                                                 ('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 @@ 

          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 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',

y_o_l_o c_o_o_l f_o_r_m_a_t :P
(I actually have no issue with this, just funny formatting)

+         '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 @@ 

      """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 @@ 

          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 @@ 

  

      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 @@ 

      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 @@ 

  

      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 @@ 

      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 @@ 

  

      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 @@ 

      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 @@ 

               '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 @@ 

  

      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 @@ 

      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__':

@@ -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 @@ 

  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 @@ 

  logging.getLogger(__name__).setLevel(logging.INFO)

  log = logging.getLogger(__name__)

  

+ 

  def _test_bind(user, password):

      result = True

      try:
@@ -33,16 +34,9 @@ 

      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 @@ 

          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 @@ 

          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 @@ 

          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

@@ -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 @@ 

          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 @@ 

          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)

@@ -12,6 +12,7 @@ 

  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 @@ 

          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')

@@ -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 @@ 

      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 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 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 @@ 

          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 @@ 

              # 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 @@ 

          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 @@ 

      """

  

      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__':

@@ -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

  

file modified
+47 -49
@@ -24,54 +24,48 @@ 

      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 @@ 

          :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

file modified
+1 -1
@@ -283,7 +283,7 @@ 

              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",

Description:

While investigating ticket 50255 I had issues with the CI test because it was not use DSLdapObject. So this patch just refactors the test to use the current DSLDAPObject model.

https://pagure.io/389-ds-base/issue/50255

Please do not review this until PR 50258 is merged...

But I really really want to review it .... ;)

But I really really want to review it .... ;)

Hehe, its actually a much larger patch I just haven't rebase yet. I redoing the entire pwp suite of tests, but I need to fix my CLI work first :-(

No problems, I'm just starting the 50258 review now

rebased onto 1d71ebb51550b6a0c632d5a5bb8c3d05cea2b105

5 years ago

rebased onto 7c375d2b53486a2774465d10943d316890aa7682

5 years ago

rebased onto 31941eee1b85790fe5abf59fdb1c263deccc5f17

5 years ago

Patch is ready for review, but you need to revert this commit in master branch to test it:

commit e580506

Once "Ticket 49873 - Contention on virtual attribute lookup" is finally fixed that revert will not be required to run this patch

I think this might throw the _s api warning, you could use "dm = DirectoryManager(inst).bind()", but also to keep in mind, when you do a "conn = user.bind()", that makes a new ldap connection, so the original inst connection is NOT alterted/reset so dm keeps working there.

y_o_l_o c_o_o_l f_o_r_m_a_t :P
(I actually have no issue with this, just funny formatting)

Okay, looks pretty good to me. Some minor comments, but great stuff :)

Assuming this comment is intentional?

I think I was debugging something, it should probably be removed

rebased onto 35bbe1c7edc27381b17899ed643fe931e4095604

5 years ago

@firstyear changes made, and the bind functions do not complain, please review...

FYI to run the patch you need to revert commit e580506 for the time being

Awesome! Thanks man, I think this looks good. Ack :)

rebased onto 5bc92e9

5 years ago

Pull-Request has been merged by mreynolds

5 years ago

389-ds-base is moving from Pagure to Github. This means that new issues and pull requests
will be accepted only in 389-ds-base's github repository.

This pull request has been cloned to Github as issue and is available here:
- https://github.com/389ds/389-ds-base/issues/3315

If you want to continue to work on the PR, please navigate to the github issue,
download the patch from the attachments and file a new pull request.

Thank you for understanding. We apologize for all inconvenience.

Pull-Request has been closed by spichugi

3 years ago