regression_test.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. # Copyright (C) 2017 Red Hat, Inc.
  2. # All rights reserved.
  3. #
  4. # License: GPL (version 3 or any later version).
  5. # See LICENSE for details.
  6. # --- END COPYRIGHT BLOCK ---
  7. #
  8. import pytest
  9. import time
  10. from lib389._constants import PASSWORD, DN_DM, DEFAULT_SUFFIX
  11. from lib389.idm.user import UserAccounts
  12. from lib389.utils import ldap, os, logging
  13. from lib389.topologies import topology_st as topo
  14. from lib389.idm.organizationalunit import OrganizationalUnits
  15. pytestmark = pytest.mark.tier1
  16. DEBUGGING = os.getenv("DEBUGGING", default=False)
  17. if DEBUGGING:
  18. logging.getLogger(__name__).setLevel(logging.DEBUG)
  19. else:
  20. logging.getLogger(__name__).setLevel(logging.INFO)
  21. log = logging.getLogger(__name__)
  22. user_data = {'cn': 'CNpwtest1', 'sn': 'SNpwtest1', 'uid': 'UIDpwtest1', 'mail': '[email protected]',
  23. 'givenname': 'GNpwtest1'}
  24. TEST_PASSWORDS = list(user_data.values())
  25. # Add substring/token values of "CNpwtest1"
  26. TEST_PASSWORDS += ['CNpwtest1ZZZZ', 'ZZZZZCNpwtest1',
  27. 'ZCNpwtest1', 'CNpwtest1Z', 'ZCNpwtest1Z',
  28. 'ZZCNpwtest1', 'CNpwtest1ZZ', 'ZZCNpwtest1ZZ',
  29. 'ZZZCNpwtest1', 'CNpwtest1ZZZ', 'ZZZCNpwtest1ZZZ',
  30. 'ZZZZZZCNpwtest1ZZZZZZZZ']
  31. TEST_PASSWORDS2 = (
  32. 'CN12pwtest31', 'SN3pwtest231', 'UID1pwtest123', '[email protected]', '2GN1pwtest123', 'People123')
  33. @pytest.fixture(scope="module")
  34. def passw_policy(topo, request):
  35. """Configure password policy with PasswordCheckSyntax attribute set to on"""
  36. log.info('Configure Pwpolicy with PasswordCheckSyntax and nsslapd-pwpolicy-local set to on')
  37. topo.standalone.simple_bind_s(DN_DM, PASSWORD)
  38. topo.standalone.config.set('PasswordExp', 'on')
  39. topo.standalone.config.set('PasswordCheckSyntax', 'off')
  40. topo.standalone.config.set('nsslapd-pwpolicy-local', 'on')
  41. subtree = 'ou=people,{}'.format(DEFAULT_SUFFIX)
  42. log.info('Configure subtree password policy for {}'.format(subtree))
  43. topo.standalone.subtreePwdPolicy(subtree, {'passwordchange': b'on',
  44. 'passwordCheckSyntax': b'on',
  45. 'passwordLockout': b'on',
  46. 'passwordResetFailureCount': b'3',
  47. 'passwordLockoutDuration': b'3',
  48. 'passwordMaxFailure': b'2'})
  49. time.sleep(1)
  50. def fin():
  51. log.info('Reset pwpolicy configuration settings')
  52. topo.standalone.simple_bind_s(DN_DM, PASSWORD)
  53. topo.standalone.config.set('PasswordExp', 'off')
  54. topo.standalone.config.set('PasswordCheckSyntax', 'off')
  55. topo.standalone.config.set('nsslapd-pwpolicy-local', 'off')
  56. request.addfinalizer(fin)
  57. @pytest.fixture(scope="module")
  58. def create_user(topo, request):
  59. """Add test users using UserAccounts"""
  60. log.info('Adding user-uid={},ou=people,{}'.format(user_data['uid'], DEFAULT_SUFFIX))
  61. users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
  62. user_properties = {
  63. 'uidNumber': '1001',
  64. 'gidNumber': '2001',
  65. 'cn': 'pwtest1',
  66. 'userpassword': PASSWORD,
  67. 'homeDirectory': '/home/pwtest1'}
  68. user_properties.update(user_data)
  69. tuser = users.create(properties=user_properties)
  70. def fin():
  71. log.info('Deleting user-{}'.format(tuser.dn))
  72. tuser.delete()
  73. request.addfinalizer(fin)
  74. return tuser
  75. def test_pwp_local_unlock(topo, passw_policy, create_user):
  76. """Test subtree policies use the same global default for passwordUnlock
  77. :id: 741a8417-5f65-4012-b9ed-87987ce3ca1b
  78. :setup: Standalone instance
  79. :steps:
  80. 1. Test user can bind
  81. 2. Bind with bad passwords to lockout account, and verify account is locked
  82. 3. Wait for lockout interval, and bind with valid password
  83. :expectedresults:
  84. 1. Bind successful
  85. 2. Entry is locked
  86. 3. Entry can bind with correct password
  87. """
  88. # Add aci so users can change their own password
  89. USER_ACI = '(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)'
  90. ous = OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX)
  91. ou = ous.get('people')
  92. ou.add('aci', USER_ACI)
  93. log.info("Verify user can bind...")
  94. create_user.bind(PASSWORD)
  95. log.info('Test passwordUnlock default - user should be able to reset password after lockout')
  96. for i in range(0, 2):
  97. try:
  98. create_user.bind("bad-password")
  99. except ldap.INVALID_CREDENTIALS:
  100. # expected
  101. pass
  102. except ldap.LDAPError as e:
  103. log.fatal("Got unexpected failure: " + str(e))
  104. raise e
  105. log.info('Verify account is locked')
  106. with pytest.raises(ldap.CONSTRAINT_VIOLATION):
  107. create_user.bind(PASSWORD)
  108. log.info('Wait for lockout duration...')
  109. time.sleep(4)
  110. log.info('Check if user can now bind with correct password')
  111. create_user.bind(PASSWORD)
  112. @pytest.mark.bz1465600
  113. @pytest.mark.parametrize("user_pasw", TEST_PASSWORDS)
  114. def test_trivial_passw_check(topo, passw_policy, create_user, user_pasw):
  115. """PasswordCheckSyntax attribute fails to validate cn, sn, uid, givenname, ou and mail attributes
  116. :id: bf9fe1ef-56cb-46a3-a6f8-5530398a06dc
  117. :setup: Standalone instance.
  118. :steps:
  119. 1. Configure local password policy with PasswordCheckSyntax set to on.
  120. 2. Add users with cn, sn, uid, givenname, mail and userPassword attributes.
  121. 3. Configure subtree password policy for ou=people subtree.
  122. 4. Reset userPassword with trivial values like cn, sn, uid, givenname, ou and mail attributes.
  123. :expectedresults:
  124. 1. Enabling PasswordCheckSyntax should PASS.
  125. 2. Add users should PASS.
  126. 3. Configure subtree password policy should PASS.
  127. 4. Resetting userPassword to cn, sn, uid and mail should be rejected.
  128. """
  129. create_user.rebind(PASSWORD)
  130. log.info('Replace userPassword attribute with {}'.format(user_pasw))
  131. with pytest.raises(ldap.CONSTRAINT_VIOLATION) as excinfo:
  132. create_user.reset_password(user_pasw)
  133. log.fatal('Failed: Userpassword with {} is accepted'.format(user_pasw))
  134. assert 'password based off of user entry' in str(excinfo.value)
  135. # reset password
  136. topo.standalone.simple_bind_s(DN_DM, PASSWORD)
  137. create_user.set('userPassword', PASSWORD)
  138. @pytest.mark.parametrize("user_pasw", TEST_PASSWORDS)
  139. def test_global_vs_local(topo, passw_policy, create_user, user_pasw):
  140. """Passwords rejected if its similar to uid, cn, sn, givenname, ou and mail attributes
  141. :id: dfd6cf5d-8bcd-4895-a691-a43ad9ec1be8
  142. :setup: Standalone instance
  143. :steps:
  144. 1. Configure global password policy with PasswordCheckSyntax set to off
  145. 2. Add users with cn, sn, uid, mail, givenname and userPassword attributes
  146. 3. Replace userPassword similar to cn, sn, uid, givenname, ou and mail attributes
  147. :expectedresults:
  148. 1. Disabling the local policy should PASS.
  149. 2. Add users should PASS.
  150. 3. Resetting userPasswords similar to cn, sn, uid, givenname, ou and mail attributes should PASS.
  151. """
  152. log.info('Configure Pwpolicy with PasswordCheckSyntax and nsslapd-pwpolicy-local set to off')
  153. topo.standalone.simple_bind_s(DN_DM, PASSWORD)
  154. topo.standalone.config.set('nsslapd-pwpolicy-local', 'off')
  155. create_user.rebind(PASSWORD)
  156. log.info('Replace userPassword attribute with {}'.format(user_pasw))
  157. create_user.reset_password(user_pasw)
  158. # reset password
  159. create_user.set('userPassword', PASSWORD)
  160. if __name__ == '__main__':
  161. # Run isolated
  162. # -s for DEBUG mode
  163. CURRENT_FILE = os.path.realpath(__file__)
  164. pytest.main(["-s", CURRENT_FILE])