ticket47714_test.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2015 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 os
  10. import sys
  11. import time
  12. import ldap
  13. import logging
  14. import pytest
  15. import shutil
  16. from lib389 import DirSrv, Entry, tools
  17. from lib389.tools import DirSrvTools
  18. from lib389._constants import *
  19. from lib389.properties import *
  20. log = logging.getLogger(__name__)
  21. installation_prefix = None
  22. ACCT_POLICY_CONFIG_DN = ('cn=config,cn=%s,cn=plugins,cn=config' %
  23. PLUGIN_ACCT_POLICY)
  24. ACCT_POLICY_DN = 'cn=Account Inactivation Policy,%s' % SUFFIX
  25. INACTIVITY_LIMIT = '9'
  26. SEARCHFILTER = '(objectclass=*)'
  27. TEST_USER = 'ticket47714user'
  28. TEST_USER_DN = 'uid=%s,%s' % (TEST_USER, SUFFIX)
  29. TEST_USER_PW = '%s' % TEST_USER
  30. class TopologyStandalone(object):
  31. def __init__(self, standalone):
  32. standalone.open()
  33. self.standalone = standalone
  34. @pytest.fixture(scope="module")
  35. def topology(request):
  36. '''
  37. This fixture is used to standalone topology for the 'module'.
  38. '''
  39. global installation_prefix
  40. if installation_prefix:
  41. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  42. standalone = DirSrv(verbose=False)
  43. # Args for the standalone instance
  44. args_instance[SER_HOST] = HOST_STANDALONE
  45. args_instance[SER_PORT] = PORT_STANDALONE
  46. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  47. args_standalone = args_instance.copy()
  48. standalone.allocate(args_standalone)
  49. # Get the status of the instance and restart it if it exists
  50. instance_standalone = standalone.exists()
  51. # Remove the instance
  52. if instance_standalone:
  53. standalone.delete()
  54. # Create the instance
  55. standalone.create()
  56. # Used to retrieve configuration information (dbdir, confdir...)
  57. standalone.open()
  58. def fin():
  59. standalone.delete()
  60. request.addfinalizer(fin)
  61. # Here we have standalone instance up and running
  62. return TopologyStandalone(standalone)
  63. def _header(topology, label):
  64. topology.standalone.log.info("\n\n###############################################")
  65. topology.standalone.log.info("#######")
  66. topology.standalone.log.info("####### %s" % label)
  67. topology.standalone.log.info("#######")
  68. topology.standalone.log.info("###############################################")
  69. def test_ticket47714_init(topology):
  70. """
  71. 1. Add account policy entry to the DB
  72. 2. Add a test user to the DB
  73. """
  74. _header(topology, 'Testing Ticket 47714 - [RFE] Update lastLoginTime also in Account Policy plugin if account lockout is based on passwordExpirationTime.')
  75. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  76. log.info("\n######################### Adding Account Policy entry: %s ######################\n" % ACCT_POLICY_DN)
  77. topology.standalone.add_s(Entry((ACCT_POLICY_DN, {'objectclass': "top ldapsubentry extensibleObject accountpolicy".split(),
  78. 'accountInactivityLimit': INACTIVITY_LIMIT})))
  79. log.info("\n######################### Adding Test User entry: %s ######################\n" % TEST_USER_DN)
  80. topology.standalone.add_s(Entry((TEST_USER_DN, {'objectclass': "top person organizationalPerson inetOrgPerson".split(),
  81. 'cn': TEST_USER,
  82. 'sn': TEST_USER,
  83. 'givenname': TEST_USER,
  84. 'userPassword': TEST_USER_PW,
  85. 'acctPolicySubentry': ACCT_POLICY_DN})))
  86. def test_ticket47714_run_0(topology):
  87. """
  88. Check this change has no inpact to the existing functionality.
  89. 1. Set account policy config without the new attr alwaysRecordLoginAttr
  90. 2. Bind as a test user
  91. 3. Bind as the test user again and check the lastLoginTime is updated
  92. 4. Waint longer than the accountInactivityLimit time and bind as the test user,
  93. which should fail with CONSTANT_VIOLATION.
  94. """
  95. _header(topology, 'Account Policy - No new attr alwaysRecordLoginAttr in config')
  96. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  97. # Modify Account Policy config entry
  98. topology.standalone.modify_s(ACCT_POLICY_CONFIG_DN, [(ldap.MOD_REPLACE, 'alwaysrecordlogin', 'yes'),
  99. (ldap.MOD_REPLACE, 'stateattrname', 'lastLoginTime'),
  100. (ldap.MOD_REPLACE, 'altstateattrname', 'createTimestamp'),
  101. (ldap.MOD_REPLACE, 'specattrname', 'acctPolicySubentry'),
  102. (ldap.MOD_REPLACE, 'limitattrname', 'accountInactivityLimit')])
  103. # Enable the plugins
  104. topology.standalone.plugins.enable(name=PLUGIN_ACCT_POLICY)
  105. topology.standalone.restart(timeout=120)
  106. log.info("\n######################### Bind as %s ######################\n" % TEST_USER_DN)
  107. try:
  108. topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PW)
  109. except ldap.CONSTRAINT_VIOLATION as e:
  110. log.error('CONSTRAINT VIOLATION ' + e.message['desc'])
  111. time.sleep(2)
  112. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  113. entry = topology.standalone.search_s(TEST_USER_DN, ldap.SCOPE_BASE, SEARCHFILTER, ['lastLoginTime'])
  114. lastLoginTime0 = entry[0].lastLoginTime
  115. log.info("\n######################### Bind as %s again ######################\n" % TEST_USER_DN)
  116. try:
  117. topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PW)
  118. except ldap.CONSTRAINT_VIOLATION as e:
  119. log.error('CONSTRAINT VIOLATION ' + e.message['desc'])
  120. time.sleep(2)
  121. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  122. entry = topology.standalone.search_s(TEST_USER_DN, ldap.SCOPE_BASE, SEARCHFILTER, ['lastLoginTime'])
  123. lastLoginTime1 = entry[0].lastLoginTime
  124. log.info("First lastLoginTime: %s, Second lastLoginTime: %s" % (lastLoginTime0, lastLoginTime1))
  125. assert lastLoginTime0 < lastLoginTime1
  126. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  127. entry = topology.standalone.search_s(ACCT_POLICY_DN, ldap.SCOPE_BASE, SEARCHFILTER)
  128. log.info("\n######################### %s ######################\n" % ACCT_POLICY_CONFIG_DN)
  129. log.info("accountInactivityLimit: %s" % entry[0].accountInactivityLimit)
  130. log.info("\n######################### %s DONE ######################\n" % ACCT_POLICY_CONFIG_DN)
  131. log.info("\n######################### Bind as %s again to fail ######################\n" % TEST_USER_DN)
  132. try:
  133. topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PW)
  134. except ldap.CONSTRAINT_VIOLATION as e:
  135. log.info('CONSTRAINT VIOLATION ' + e.message['desc'])
  136. log.info("%s was successfully inactivated." % TEST_USER_DN)
  137. pass
  138. def test_ticket47714_run_1(topology):
  139. """
  140. Verify a new config attr alwaysRecordLoginAttr
  141. 1. Set account policy config with the new attr alwaysRecordLoginAttr: lastLoginTime
  142. Note: bogus attr is set to stateattrname.
  143. altstateattrname type value is used for checking whether the account is idle or not.
  144. 2. Bind as a test user
  145. 3. Bind as the test user again and check the alwaysRecordLoginAttr: lastLoginTime is updated
  146. """
  147. _header(topology, 'Account Policy - With new attr alwaysRecordLoginAttr in config')
  148. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  149. topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_DELETE, 'lastLoginTime', None)])
  150. # Modify Account Policy config entry
  151. topology.standalone.modify_s(ACCT_POLICY_CONFIG_DN, [(ldap.MOD_REPLACE, 'alwaysrecordlogin', 'yes'),
  152. (ldap.MOD_REPLACE, 'stateattrname', 'bogus'),
  153. (ldap.MOD_REPLACE, 'altstateattrname', 'modifyTimestamp'),
  154. (ldap.MOD_REPLACE, 'alwaysRecordLoginAttr', 'lastLoginTime'),
  155. (ldap.MOD_REPLACE, 'specattrname', 'acctPolicySubentry'),
  156. (ldap.MOD_REPLACE, 'limitattrname', 'accountInactivityLimit')])
  157. # Enable the plugins
  158. topology.standalone.plugins.enable(name=PLUGIN_ACCT_POLICY)
  159. topology.standalone.restart(timeout=120)
  160. log.info("\n######################### Bind as %s ######################\n" % TEST_USER_DN)
  161. try:
  162. topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PW)
  163. except ldap.CONSTRAINT_VIOLATION as e:
  164. log.error('CONSTRAINT VIOLATION ' + e.message['desc'])
  165. time.sleep(1)
  166. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  167. entry = topology.standalone.search_s(TEST_USER_DN, ldap.SCOPE_BASE, SEARCHFILTER, ['lastLoginTime'])
  168. lastLoginTime0 = entry[0].lastLoginTime
  169. log.info("\n######################### Bind as %s again ######################\n" % TEST_USER_DN)
  170. try:
  171. topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PW)
  172. except ldap.CONSTRAINT_VIOLATION as e:
  173. log.error('CONSTRAINT VIOLATION ' + e.message['desc'])
  174. time.sleep(1)
  175. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  176. entry = topology.standalone.search_s(TEST_USER_DN, ldap.SCOPE_BASE, SEARCHFILTER, ['lastLoginTime'])
  177. lastLoginTime1 = entry[0].lastLoginTime
  178. log.info("First lastLoginTime: %s, Second lastLoginTime: %s" % (lastLoginTime0, lastLoginTime1))
  179. assert lastLoginTime0 < lastLoginTime1
  180. topology.standalone.log.info("ticket47714 was successfully verified.")
  181. def test_ticket47714_final(topology):
  182. log.info('Testcase PASSED')
  183. def run_isolated():
  184. '''
  185. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  186. To run isolated without py.test, you need to
  187. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  188. - set the installation prefix
  189. - run this program
  190. '''
  191. global installation_prefix
  192. installation_prefix = None
  193. topo = topology(True)
  194. test_ticket47714_init(topo)
  195. test_ticket47714_run_0(topo)
  196. test_ticket47714_run_1(topo)
  197. test_ticket47714_final(topo)
  198. if __name__ == '__main__':
  199. run_isolated()