ticket47815_test.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import os
  2. import sys
  3. import time
  4. import ldap
  5. import logging
  6. import socket
  7. import pytest
  8. from lib389 import DirSrv, Entry, tools
  9. from lib389.tools import DirSrvTools
  10. from lib389._constants import *
  11. from lib389.properties import *
  12. from constants import *
  13. log = logging.getLogger(__name__)
  14. installation_prefix = None
  15. class TopologyStandalone(object):
  16. def __init__(self, standalone):
  17. standalone.open()
  18. self.standalone = standalone
  19. @pytest.fixture(scope="module")
  20. def topology(request):
  21. '''
  22. This fixture is used to standalone topology for the 'module'.
  23. At the beginning, It may exists a standalone instance.
  24. It may also exists a backup for the standalone instance.
  25. Principle:
  26. If standalone instance exists:
  27. restart it
  28. If backup of standalone exists:
  29. create/rebind to standalone
  30. restore standalone instance from backup
  31. else:
  32. Cleanup everything
  33. remove instance
  34. remove backup
  35. Create instance
  36. Create backup
  37. '''
  38. global installation_prefix
  39. if installation_prefix:
  40. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  41. standalone = DirSrv(verbose=False)
  42. # Args for the standalone instance
  43. args_instance[SER_HOST] = HOST_STANDALONE
  44. args_instance[SER_PORT] = PORT_STANDALONE
  45. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  46. args_standalone = args_instance.copy()
  47. standalone.allocate(args_standalone)
  48. # Get the status of the backups
  49. backup_standalone = standalone.checkBackupFS()
  50. # Get the status of the instance and restart it if it exists
  51. instance_standalone = standalone.exists()
  52. if instance_standalone:
  53. # assuming the instance is already stopped, just wait 5 sec max
  54. standalone.stop(timeout=5)
  55. standalone.start(timeout=10)
  56. if backup_standalone:
  57. # The backup exist, assuming it is correct
  58. # we just re-init the instance with it
  59. if not instance_standalone:
  60. standalone.create()
  61. # Used to retrieve configuration information (dbdir, confdir...)
  62. standalone.open()
  63. # restore standalone instance from backup
  64. standalone.stop(timeout=10)
  65. standalone.restoreFS(backup_standalone)
  66. standalone.start(timeout=10)
  67. else:
  68. # We should be here only in two conditions
  69. # - This is the first time a test involve standalone instance
  70. # - Something weird happened (instance/backup destroyed)
  71. # so we discard everything and recreate all
  72. # Remove the backup. So even if we have a specific backup file
  73. # (e.g backup_standalone) we clear backup that an instance may have created
  74. if backup_standalone:
  75. standalone.clearBackupFS()
  76. # Remove the instance
  77. if instance_standalone:
  78. standalone.delete()
  79. # Create the instance
  80. standalone.create()
  81. # Used to retrieve configuration information (dbdir, confdir...)
  82. standalone.open()
  83. # Time to create the backups
  84. standalone.stop(timeout=10)
  85. standalone.backupfile = standalone.backupFS()
  86. standalone.start(timeout=10)
  87. # clear the tmp directory
  88. standalone.clearTmpDir(__file__)
  89. #
  90. # Here we have standalone instance up and running
  91. # Either coming from a backup recovery
  92. # or from a fresh (re)init
  93. # Time to return the topology
  94. return TopologyStandalone(standalone)
  95. def test_ticket47815(topology):
  96. """
  97. Test betxn plugins reject an invalid option, and make sure that the rejected entry
  98. is not in the entry cache.
  99. Enable memberOf, automember, and retrocl plugins
  100. Add the automember config entry
  101. Add the automember group
  102. Add a user that will be rejected by a betxn plugin - result error 53
  103. Attempt the same add again, and it should result in another error 53 (not error 68)
  104. """
  105. result = 0
  106. result2 = 0
  107. log.info('Testing Ticket 47815 - Add entries that should be rejected by the betxn plugins, and are not left in the entry cache')
  108. # Enabled the plugins
  109. topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
  110. topology.standalone.plugins.enable(name=PLUGIN_AUTOMEMBER)
  111. topology.standalone.plugins.enable(name=PLUGIN_RETRO_CHANGELOG)
  112. # configure automember config entry
  113. log.info('Adding automember config')
  114. try:
  115. topology.standalone.add_s(Entry(('cn=group cfg,cn=Auto Membership Plugin,cn=plugins,cn=config', {
  116. 'objectclass': 'top autoMemberDefinition'.split(),
  117. 'autoMemberScope': 'dc=example,dc=com',
  118. 'autoMemberFilter': 'cn=user',
  119. 'autoMemberDefaultGroup': 'cn=group,dc=example,dc=com',
  120. 'autoMemberGroupingAttr': 'member:dn',
  121. 'cn': 'group cfg'})))
  122. except:
  123. log.error('Failed to add automember config')
  124. exit(1)
  125. topology.standalone.stop(timeout=120)
  126. time.sleep(1)
  127. topology.standalone.start(timeout=120)
  128. time.sleep(3)
  129. # need to reopen a connection toward the instance
  130. topology.standalone.open()
  131. # add automember group
  132. log.info('Adding automember group')
  133. try:
  134. topology.standalone.add_s(Entry(('cn=group,dc=example,dc=com', {
  135. 'objectclass': 'top groupOfNames'.split(),
  136. 'cn': 'group'})))
  137. except:
  138. log.error('Failed to add automember group')
  139. exit(1)
  140. # add user that should result in an error 53
  141. log.info('Adding invalid entry')
  142. try:
  143. topology.standalone.add_s(Entry(('cn=user,dc=example,dc=com', {
  144. 'objectclass': 'top person'.split(),
  145. 'sn': 'user',
  146. 'cn': 'user'})))
  147. except ldap.UNWILLING_TO_PERFORM:
  148. log.debug('Adding invalid entry failed as expected')
  149. result = 53
  150. except ldap.LDAPError, e:
  151. log.error('Unexpected result ' + e.message['desc'])
  152. assert False
  153. if result == 0:
  154. log.error('Add operation unexpectedly succeeded')
  155. assert False
  156. # Attempt to add user again, should result in error 53 again
  157. try:
  158. topology.standalone.add_s(Entry(('cn=user,dc=example,dc=com', {
  159. 'objectclass': 'top person'.split(),
  160. 'sn': 'user',
  161. 'cn': 'user'})))
  162. except ldap.UNWILLING_TO_PERFORM:
  163. log.debug('2nd add of invalid entry failed as expected')
  164. result2 = 53
  165. except ldap.LDAPError, e:
  166. log.error('Unexpected result ' + e.message['desc'])
  167. assert False
  168. if result2 == 0:
  169. log.error('2nd Add operation unexpectedly succeeded')
  170. assert False
  171. # If we got here we passed!
  172. log.info('Ticket47815 Test - Passed')
  173. def test_ticket47815_final(topology):
  174. topology.standalone.delete()
  175. def run_isolated():
  176. '''
  177. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  178. To run isolated without py.test, you need to
  179. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  180. - set the installation prefix
  181. - run this program
  182. '''
  183. global installation_prefix
  184. installation_prefix = None
  185. topo = topology(True)
  186. test_ticket47815(topo)
  187. test_ticket47815_final(topo)
  188. if __name__ == '__main__':
  189. run_isolated()