ticket47970_test.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import os
  2. import sys
  3. import time
  4. import ldap
  5. import ldap.sasl
  6. import logging
  7. import socket
  8. import pytest
  9. from lib389 import DirSrv, Entry, tools, tasks
  10. from lib389.tools import DirSrvTools
  11. from lib389._constants import *
  12. from lib389.properties import *
  13. from lib389.tasks import *
  14. from constants import *
  15. log = logging.getLogger(__name__)
  16. installation_prefix = None
  17. USER1_DN = "uid=user1,%s" % DEFAULT_SUFFIX
  18. USER2_DN = "uid=user2,%s" % DEFAULT_SUFFIX
  19. class TopologyStandalone(object):
  20. def __init__(self, standalone):
  21. standalone.open()
  22. self.standalone = standalone
  23. @pytest.fixture(scope="module")
  24. def topology(request):
  25. '''
  26. This fixture is used to standalone topology for the 'module'.
  27. At the beginning, It may exists a standalone instance.
  28. It may also exists a backup for the standalone instance.
  29. Principle:
  30. If standalone instance exists:
  31. restart it
  32. If backup of standalone exists:
  33. create/rebind to standalone
  34. restore standalone instance from backup
  35. else:
  36. Cleanup everything
  37. remove instance
  38. remove backup
  39. Create instance
  40. Create backup
  41. '''
  42. global installation_prefix
  43. if installation_prefix:
  44. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  45. standalone = DirSrv(verbose=False)
  46. # Args for the standalone instance
  47. args_instance[SER_HOST] = HOST_STANDALONE
  48. args_instance[SER_PORT] = PORT_STANDALONE
  49. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  50. args_standalone = args_instance.copy()
  51. standalone.allocate(args_standalone)
  52. # Get the status of the backups
  53. backup_standalone = standalone.checkBackupFS()
  54. # Get the status of the instance and restart it if it exists
  55. instance_standalone = standalone.exists()
  56. if instance_standalone:
  57. # assuming the instance is already stopped, just wait 5 sec max
  58. standalone.stop(timeout=5)
  59. standalone.start(timeout=10)
  60. if backup_standalone:
  61. # The backup exist, assuming it is correct
  62. # we just re-init the instance with it
  63. if not instance_standalone:
  64. standalone.create()
  65. # Used to retrieve configuration information (dbdir, confdir...)
  66. standalone.open()
  67. # restore standalone instance from backup
  68. standalone.stop(timeout=10)
  69. standalone.restoreFS(backup_standalone)
  70. standalone.start(timeout=10)
  71. else:
  72. # We should be here only in two conditions
  73. # - This is the first time a test involve standalone instance
  74. # - Something weird happened (instance/backup destroyed)
  75. # so we discard everything and recreate all
  76. # Remove the backup. So even if we have a specific backup file
  77. # (e.g backup_standalone) we clear backup that an instance may have created
  78. if backup_standalone:
  79. standalone.clearBackupFS()
  80. # Remove the instance
  81. if instance_standalone:
  82. standalone.delete()
  83. # Create the instance
  84. standalone.create()
  85. # Used to retrieve configuration information (dbdir, confdir...)
  86. standalone.open()
  87. # Time to create the backups
  88. standalone.stop(timeout=10)
  89. standalone.backupfile = standalone.backupFS()
  90. standalone.start(timeout=10)
  91. # clear the tmp directory
  92. standalone.clearTmpDir(__file__)
  93. #
  94. # Here we have standalone instance up and running
  95. # Either coming from a backup recovery
  96. # or from a fresh (re)init
  97. # Time to return the topology
  98. return TopologyStandalone(standalone)
  99. def test_ticket47970(topology):
  100. """
  101. Testing that a failed SASL bind does not trigger account lockout -
  102. which would attempt to update the passwordRetryCount on the root dse entry
  103. """
  104. log.info('Testing Ticket 47970 - Testing that a failed SASL bind does not trigger account lockout')
  105. #
  106. # Enable account lockout
  107. #
  108. try:
  109. topology.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE, 'passwordLockout', 'on')])
  110. log.info('account lockout enabled.')
  111. except ldap.LDAPError, e:
  112. log.error('Failed to enable account lockout: ' + e.message['desc'])
  113. assert False
  114. try:
  115. topology.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE, 'passwordMaxFailure', '5')])
  116. log.info('passwordMaxFailure set.')
  117. except ldap.LDAPError, e:
  118. log.error('Failed to to set passwordMaxFailure: ' + e.message['desc'])
  119. assert False
  120. #
  121. # Perform SASL bind that should fail
  122. #
  123. failed_as_expected = False
  124. try:
  125. user_name = "mark"
  126. pw = "secret"
  127. auth_tokens = ldap.sasl.digest_md5(user_name, pw)
  128. topology.standalone.sasl_interactive_bind_s("", auth_tokens)
  129. except ldap.INVALID_CREDENTIALS, e:
  130. log.info("SASL Bind failed as expected")
  131. failed_as_expected = True
  132. if not failed_as_expected:
  133. log.error("SASL bind unexpectedly succeeded!")
  134. assert False
  135. #
  136. # Check that passwordRetryCount was not set on the root dse entry
  137. #
  138. try:
  139. entry = topology.standalone.search_s("", ldap.SCOPE_BASE,
  140. "passwordRetryCount=*",
  141. ['passwordRetryCount'])
  142. except ldap.LDAPError, e:
  143. log.error('Failed to search Root DSE entry: ' + e.message['desc'])
  144. assert False
  145. if entry:
  146. log.error('Root DSE was incorrectly updated')
  147. assert False
  148. # We passed
  149. log.info('Root DSE was correctly not updated')
  150. log.info("Test Passed.")
  151. def test_ticket47970_final(topology):
  152. topology.standalone.stop(timeout=10)
  153. def run_isolated():
  154. '''
  155. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  156. To run isolated without py.test, you need to
  157. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  158. - set the installation prefix
  159. - run this program
  160. '''
  161. global installation_prefix
  162. installation_prefix = None
  163. topo = topology(True)
  164. test_ticket47970(topo)
  165. if __name__ == '__main__':
  166. run_isolated()