pwdPolicy_attribute_test.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. from lib389.tasks import *
  11. from lib389.utils import *
  12. from lib389.topologies import topology_st
  13. OU_PEOPLE = 'ou=people,{}'.format(DEFAULT_SUFFIX)
  14. TEST_USER_NAME = 'simplepaged_test'
  15. TEST_USER_DN = 'uid={},{}'.format(TEST_USER_NAME, OU_PEOPLE)
  16. TEST_USER_PWD = 'simplepaged_test'
  17. PW_POLICY_CONT_USER = 'cn="cn=nsPwPolicyEntry,uid=simplepaged_test,' \
  18. 'ou=people,dc=example,dc=com",' \
  19. 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
  20. PW_POLICY_CONT_PEOPLE = 'cn="cn=nsPwPolicyEntry,' \
  21. 'ou=people,dc=example,dc=com",' \
  22. 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
  23. logging.getLogger(__name__).setLevel(logging.INFO)
  24. log = logging.getLogger(__name__)
  25. @pytest.fixture(scope="module")
  26. def test_user(topology_st, request):
  27. """User for binding operation"""
  28. log.info('Adding user {}'.format(TEST_USER_DN))
  29. try:
  30. topology_st.standalone.add_s(Entry((TEST_USER_DN, {
  31. 'objectclass': 'top person'.split(),
  32. 'objectclass': 'organizationalPerson',
  33. 'objectclass': 'inetorgperson',
  34. 'cn': TEST_USER_NAME,
  35. 'sn': TEST_USER_NAME,
  36. 'userpassword': TEST_USER_PWD,
  37. 'mail': '%[email protected]' % TEST_USER_NAME,
  38. 'uid': TEST_USER_NAME
  39. })))
  40. except ldap.LDAPError as e:
  41. log.error('Failed to add user (%s): error (%s)' % (TEST_USER_DN,
  42. e.message['desc']))
  43. raise e
  44. def fin():
  45. log.info('Deleting user {}'.format(TEST_USER_DN))
  46. topology_st.standalone.delete_s(TEST_USER_DN)
  47. request.addfinalizer(fin)
  48. @pytest.fixture(scope="module")
  49. def password_policy(topology_st, test_user):
  50. """Set up password policy for subtree and user"""
  51. log.info('Enable fine-grained policy')
  52. try:
  53. topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
  54. 'nsslapd-pwpolicy-local',
  55. 'on')])
  56. except ldap.LDAPError as e:
  57. log.error('Failed to set fine-grained policy: error {}'.format(
  58. e.message['desc']))
  59. raise e
  60. log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
  61. try:
  62. subprocess.call(['%s/ns-newpwpolicy.pl' % topology_st.standalone.get_sbin_dir(),
  63. '-D', DN_DM, '-w', PASSWORD,
  64. '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
  65. '-S', OU_PEOPLE, '-Z', SERVERID_STANDALONE])
  66. except subprocess.CalledProcessError as e:
  67. log.error('Failed to create pw policy policy for {}: error {}'.format(
  68. OU_PEOPLE, e.message['desc']))
  69. raise e
  70. log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
  71. try:
  72. topology_st.standalone.modify_s(OU_PEOPLE, [(ldap.MOD_REPLACE,
  73. 'pwdpolicysubentry',
  74. PW_POLICY_CONT_PEOPLE)])
  75. except ldap.LDAPError as e:
  76. log.error('Failed to pwdpolicysubentry pw policy ' \
  77. 'policy for {}: error {}'.format(OU_PEOPLE,
  78. e.message['desc']))
  79. raise e
  80. log.info('Create password policy for subtree {}'.format(TEST_USER_DN))
  81. try:
  82. subprocess.call(['%s/ns-newpwpolicy.pl' % topology_st.standalone.get_sbin_dir(),
  83. '-D', DN_DM, '-w', PASSWORD,
  84. '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
  85. '-U', TEST_USER_DN, '-Z', SERVERID_STANDALONE])
  86. except subprocess.CalledProcessError as e:
  87. log.error('Failed to create pw policy policy for {}: error {}'.format(
  88. TEST_USER_DN, e.message['desc']))
  89. raise e
  90. log.info('Add pwdpolicysubentry attribute to {}'.format(TEST_USER_DN))
  91. try:
  92. topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
  93. 'pwdpolicysubentry',
  94. PW_POLICY_CONT_USER)])
  95. except ldap.LDAPError as e:
  96. log.error('Failed to pwdpolicysubentry pw policy ' \
  97. 'policy for {}: error {}'.format(TEST_USER_DN,
  98. e.message['desc']))
  99. raise e
  100. @pytest.mark.parametrize('subtree_pwchange,user_pwchange,exception',
  101. [('on', 'off', ldap.UNWILLING_TO_PERFORM),
  102. ('off', 'off', ldap.UNWILLING_TO_PERFORM),
  103. ('off', 'on', None), ('on', 'on', None)])
  104. def test_change_pwd(topology_st, test_user, password_policy,
  105. subtree_pwchange, user_pwchange, exception):
  106. """Verify that 'passwordChange' attr works as expected
  107. User should have a priority over a subtree.
  108. :Feature: Password policy
  109. :Setup: Standalone instance, test user,
  110. password policy entries for a user and a subtree
  111. :Steps: 1. Set passwordChange on the user and the subtree
  112. to various combinations
  113. 2. Bind as test user
  114. 3. Try to change password
  115. :Assert: Subtree/User passwordChange - result
  116. off/on, on/on - success
  117. on/off, off/off - UNWILLING_TO_PERFORM
  118. """
  119. log.info('Set passwordChange to "{}" - {}'.format(subtree_pwchange,
  120. PW_POLICY_CONT_PEOPLE))
  121. try:
  122. topology_st.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE,
  123. 'passwordChange',
  124. subtree_pwchange)])
  125. except ldap.LDAPError as e:
  126. log.error('Failed to set passwordChange ' \
  127. 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE,
  128. e.message['desc']))
  129. raise e
  130. log.info('Set passwordChange to "{}" - {}'.format(user_pwchange,
  131. PW_POLICY_CONT_USER))
  132. try:
  133. topology_st.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE,
  134. 'passwordChange',
  135. user_pwchange)])
  136. except ldap.LDAPError as e:
  137. log.error('Failed to set passwordChange ' \
  138. 'policy for {}: error {}'.format(PW_POLICY_CONT_USER,
  139. e.message['desc']))
  140. raise e
  141. time.sleep(1)
  142. try:
  143. log.info('Bind as user and modify userPassword')
  144. topology_st.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
  145. if exception:
  146. with pytest.raises(exception):
  147. topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
  148. 'userPassword',
  149. 'new_pass')])
  150. else:
  151. topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
  152. 'userPassword',
  153. 'new_pass')])
  154. except ldap.LDAPError as e:
  155. log.error('Failed to change userpassword for {}: error {}'.format(
  156. TEST_USER_DN, e.message['info']))
  157. raise e
  158. finally:
  159. log.info('Bind as DM')
  160. topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
  161. topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
  162. 'userPassword',
  163. TEST_USER_PWD)])
  164. def test_pwd_min_age(topology_st, test_user, password_policy):
  165. """If we set passwordMinAge to some value, for example to 10, then it
  166. should not allow the user to change the password within 10 seconds after
  167. his previous change.
  168. :Feature: Password policy
  169. :Setup: Standalone instance, test user,
  170. password policy entries for a user and a subtree
  171. :Steps: 1. Set passwordMinAge to 10 on the user pwpolicy entry
  172. 2. Set passwordMinAge to 10 on the subtree pwpolicy entry
  173. 3. Set passwordMinAge to 10 on the cn=config entry
  174. 4. Bind as test user
  175. 5. Try to change password two times in a row
  176. 6. Wait 12 seconds
  177. 7. Try to change password
  178. :Assert: User should be not allowed to change the password
  179. right after previous change - CONSTRAINT_VIOLATION
  180. User should be not allowed to change the password
  181. after 12 seconds passed
  182. """
  183. num_seconds = '10'
  184. log.info('Set passwordminage to "{}" - {}'.format(num_seconds, PW_POLICY_CONT_PEOPLE))
  185. try:
  186. topology_st.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE,
  187. 'passwordminage',
  188. num_seconds)])
  189. except ldap.LDAPError as e:
  190. log.error('Failed to set passwordminage ' \
  191. 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE,
  192. e.message['desc']))
  193. raise e
  194. log.info('Set passwordminage to "{}" - {}'.format(num_seconds, PW_POLICY_CONT_USER))
  195. try:
  196. topology_st.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE,
  197. 'passwordminage',
  198. num_seconds)])
  199. except ldap.LDAPError as e:
  200. log.error('Failed to set passwordminage ' \
  201. 'policy for {}: error {}'.format(PW_POLICY_CONT_USER,
  202. e.message['desc']))
  203. raise e
  204. log.info('Set passwordminage to "{}" - {}'.format(num_seconds, DN_CONFIG))
  205. try:
  206. topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
  207. 'passwordminage',
  208. num_seconds)])
  209. except ldap.LDAPError as e:
  210. log.error('Failed to set passwordminage ' \
  211. 'policy for {}: error {}'.format(DN_CONFIG,
  212. e.message['desc']))
  213. raise e
  214. time.sleep(1)
  215. try:
  216. log.info('Bind as user and modify userPassword')
  217. topology_st.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
  218. topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
  219. 'userPassword',
  220. 'new_pass')])
  221. except ldap.LDAPError as e:
  222. log.error('Failed to change userpassword for {}: error {}'.format(
  223. TEST_USER_DN, e.message['info']))
  224. raise e
  225. time.sleep(1)
  226. log.info('Bind as user and modify userPassword straight away after previous change')
  227. topology_st.standalone.simple_bind_s(TEST_USER_DN, 'new_pass')
  228. with pytest.raises(ldap.CONSTRAINT_VIOLATION):
  229. topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
  230. 'userPassword',
  231. 'new_new_pass')])
  232. log.info('Wait {} second'.format(int(num_seconds) + 2))
  233. time.sleep(int(num_seconds) + 2)
  234. try:
  235. log.info('Bind as user and modify userPassword')
  236. topology_st.standalone.simple_bind_s(TEST_USER_DN, 'new_pass')
  237. topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
  238. 'userPassword',
  239. TEST_USER_PWD)])
  240. except ldap.LDAPError as e:
  241. log.error('Failed to change userpassword for {}: error {}'.format(
  242. TEST_USER_DN, e.message['info']))
  243. raise e
  244. finally:
  245. log.info('Bind as DM')
  246. topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
  247. topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
  248. 'userPassword',
  249. TEST_USER_PWD)])
  250. if __name__ == '__main__':
  251. # Run isolated
  252. # -s for DEBUG mode
  253. CURRENT_FILE = os.path.realpath(__file__)
  254. pytest.main("-s %s" % CURRENT_FILE)