pwp_history_test.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2016 Red Hat, Inc.
  3. # All rights reserved.
  4. #
  5. # License: GPL (version 3 or any later version).
  6. # See LICENSE for details.
  7. # --- END COPYRIGHT BLOCK ---
  8. #
  9. import pytest
  10. import time
  11. from lib389.tasks import *
  12. from lib389.utils import *
  13. from lib389.topologies import topology_st
  14. from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES
  15. from lib389.idm.organizationalunit import OrganizationalUnits
  16. from lib389._constants import DN_DM, DEFAULT_SUFFIX, PASSWORD
  17. pytestmark = pytest.mark.tier1
  18. logging.getLogger(__name__).setLevel(logging.DEBUG)
  19. log = logging.getLogger(__name__)
  20. def test_basic(topology_st):
  21. """Test basic password policy history feature functionality
  22. :id: 83d74f7d-3036-4944-8839-1b40bbf265ff
  23. :setup: Standalone instance
  24. :steps:
  25. 1. Configure password history policy as bellow:
  26. passwordHistory: on
  27. passwordInHistory: 3
  28. passwordChange: on
  29. passwordStorageScheme: CLEAR
  30. 2. Add a test user
  31. 3. Attempt to change password to the same password
  32. 4. Change password four times
  33. 5. Check that we only have 3 passwords stored in history
  34. 6. Attempt to change the password to previous passwords
  35. 7. Reset password by Directory Manager (admin reset)
  36. 8. Try and change the password to the previous password before the reset
  37. 9. Test passwordInHistory set to "0" rejects only the current password
  38. 10. Test passwordInHistory set to "2" rejects previous passwords
  39. :expectedresults:
  40. 1. Password history policy should be configured successfully
  41. 2. User should be added successfully
  42. 3. Password change should be correctly rejected
  43. with Constrant Violation error
  44. 4. Password should be successfully changed
  45. 5. Only 3 passwords should be stored in history
  46. 6. Password changes should be correctly rejected
  47. with Constrant Violation error
  48. 7. Password should be successfully reset
  49. 8. Password change should be correctly rejected
  50. with Constrant Violation error
  51. 9. Success
  52. 10. Success
  53. """
  54. #
  55. # Configure password history policy and add a test user
  56. #
  57. try:
  58. topology_st.standalone.config.replace_many(('passwordHistory', 'on'),
  59. ('passwordInHistory', '3'),
  60. ('passwordChange', 'on'),
  61. ('passwordStorageScheme', 'CLEAR'),
  62. ('nsslapd-auditlog-logging-enabled', 'on'))
  63. log.info('Configured password policy.')
  64. except ldap.LDAPError as e:
  65. log.fatal('Failed to configure password policy: ' + str(e))
  66. assert False
  67. time.sleep(1)
  68. # Add aci so users can change their own password
  69. USER_ACI = '(targetattr="userpassword || passwordHistory")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)'
  70. ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX)
  71. ou = ous.get('people')
  72. ou.add('aci', USER_ACI)
  73. # Create user
  74. users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
  75. user = users.create(properties=TEST_USER_PROPERTIES)
  76. user.set('userpassword', 'password')
  77. user.rebind('password')
  78. #
  79. # Test that password history is enforced.
  80. #
  81. # Attempt to change password to the same password
  82. try:
  83. user.set('userpassword', 'password')
  84. log.info('Incorrectly able to to set password to existing password.')
  85. assert False
  86. except ldap.CONSTRAINT_VIOLATION:
  87. log.info('Password change correctly rejected')
  88. except ldap.LDAPError as e:
  89. log.fatal('Failed to attempt to change password: ' + str(e))
  90. assert False
  91. #
  92. # Keep changing password until we fill the password history (3)
  93. #
  94. user.set('userpassword', 'password1')
  95. user.rebind('password1')
  96. user.set('userpassword', 'password2')
  97. user.rebind('password2')
  98. user.set('userpassword', 'password3')
  99. user.rebind('password3')
  100. user.set('userpassword', 'password4')
  101. user.rebind('password4')
  102. time.sleep(1)
  103. #
  104. # Check that we only have 3 passwords stored in history
  105. #
  106. pwds = user.get_attr_vals('passwordHistory')
  107. if len(pwds) != 3:
  108. log.fatal('Incorrect number of passwords stored in history: %d' %
  109. len(pwds))
  110. log.error('password history: ' + str(pwds))
  111. assert False
  112. else:
  113. log.info('Correct number of passwords found in history.')
  114. #
  115. # Attempt to change the password to previous passwords
  116. #
  117. try:
  118. user.set('userpassword', 'password1')
  119. log.fatal('Incorrectly able to to set password to previous password1.')
  120. log.error('password history: ' + str(user.get_attr_vals('passwordhistory')))
  121. assert False
  122. except ldap.CONSTRAINT_VIOLATION:
  123. log.info('Password change correctly rejected')
  124. except ldap.LDAPError as e:
  125. log.fatal('Failed to attempt to change password: ' + str(e))
  126. assert False
  127. try:
  128. user.set('userpassword', 'password2')
  129. log.fatal('Incorrectly able to to set password to previous password2.')
  130. log.error('password history: ' + str(user.get_attr_vals('passwordhistory')))
  131. assert False
  132. except ldap.CONSTRAINT_VIOLATION:
  133. log.info('Password change correctly rejected')
  134. except ldap.LDAPError as e:
  135. log.fatal('Failed to attempt to change password: ' + str(e))
  136. assert False
  137. try:
  138. user.set('userpassword', 'password3')
  139. log.fatal('Incorrectly able to to set password to previous password3.')
  140. log.error('password history: ' + str(user.get_attr_vals('passwordhistory')))
  141. assert False
  142. except ldap.CONSTRAINT_VIOLATION:
  143. log.info('Password change correctly rejected')
  144. except ldap.LDAPError as e:
  145. log.fatal('Failed to attempt to change password: ' + str(e))
  146. assert False
  147. #
  148. # Reset password by Directory Manager(admin reset)
  149. #
  150. try:
  151. topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
  152. except ldap.LDAPError as e:
  153. log.fatal('Failed to bind as rootDN: ' + str(e))
  154. assert False
  155. user.set('userpassword', 'password-reset')
  156. time.sleep(1)
  157. # Try and change the password to the previous password before the reset
  158. try:
  159. user.rebind('password-reset')
  160. user.set('userpassword', 'password4')
  161. log.fatal('Incorrectly able to to set password to previous password4.')
  162. log.error('password history: ' + str(user.get_attr_vals('passwordhistory')))
  163. assert False
  164. except ldap.CONSTRAINT_VIOLATION:
  165. log.info('Password change correctly rejected')
  166. except ldap.LDAPError as e:
  167. log.fatal('Failed to attempt to change password: ' + str(e))
  168. assert False
  169. if ds_is_newer("1.4.1.2"):
  170. #
  171. # Test passwordInHistory to 0
  172. #
  173. try:
  174. topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
  175. except ldap.LDAPError as e:
  176. log.fatal('Failed to bind as rootDN: ' + str(e))
  177. assert False
  178. try:
  179. topology_st.standalone.config.replace('passwordInHistory', '0')
  180. log.info('Configured passwordInHistory to 0.')
  181. except ldap.LDAPError as e:
  182. log.fatal('Failed to configure password policy (passwordInHistory to 0): ' + str(e))
  183. assert False
  184. # Verify the older passwords in the entry (passwordhistory) are ignored
  185. user.rebind('password-reset')
  186. user.set('userpassword', 'password4')
  187. try:
  188. user.set('userpassword', 'password4')
  189. log.fatal('Incorrectly able to to set password to current password4.')
  190. log.error('password history: ' + str(user.get_attr_vals('passwordhistory')))
  191. assert False
  192. except ldap.CONSTRAINT_VIOLATION:
  193. log.info('Password change correctly rejected')
  194. except ldap.LDAPError as e:
  195. log.fatal('Failed to attempt to change password: ' + str(e))
  196. assert False
  197. # Need to make one successful update so history list is reset
  198. user.set('userpassword', 'password5')
  199. #
  200. # Set the history count back to a positive value and make sure things still work
  201. # as expected
  202. #
  203. try:
  204. topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
  205. except ldap.LDAPError as e:
  206. log.fatal('Failed to bind as rootDN: ' + str(e))
  207. assert False
  208. try:
  209. topology_st.standalone.config.replace('passwordInHistory', '2')
  210. log.info('Configured passwordInHistory to 2.')
  211. except ldap.LDAPError as e:
  212. log.fatal('Failed to configure password policy (passwordInHistory to 2): ' + str(e))
  213. assert False
  214. time.sleep(1)
  215. try:
  216. user.rebind('password5')
  217. user.set('userpassword', 'password5')
  218. log.fatal('Incorrectly able to to set password to current password5.')
  219. log.error('password history: ' + str(user.get_attr_vals('passwordhistory')))
  220. assert False
  221. except ldap.CONSTRAINT_VIOLATION:
  222. log.info('Password change correctly rejected')
  223. except ldap.LDAPError as e:
  224. log.fatal('Failed to attempt to change password: ' + str(e))
  225. assert False
  226. # Test that old password that was in history is not being checked
  227. try:
  228. user.set('userpassword', 'password1')
  229. except ldap.LDAPError as e:
  230. log.fatal('Failed to attempt to change password: ' + str(e))
  231. log.error('password history: ' + str(user.get_attr_vals('passwordhistory')))
  232. assert False
  233. # Done
  234. log.info('Test suite PASSED.')
  235. if __name__ == '__main__':
  236. # Run isolated
  237. # -s for DEBUG mode
  238. CURRENT_FILE = os.path.realpath(__file__)
  239. pytest.main("-s %s" % CURRENT_FILE)