ticket47981_test.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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 ldap.sasl
  14. import logging
  15. import pytest
  16. from lib389 import DirSrv, Entry, tools, tasks
  17. from lib389.tools import DirSrvTools
  18. from lib389._constants import *
  19. from lib389.properties import *
  20. from lib389.tasks import *
  21. log = logging.getLogger(__name__)
  22. BRANCH = 'ou=people,' + DEFAULT_SUFFIX
  23. USER_DN = 'uid=user1,%s' % (BRANCH)
  24. BRANCH_CONTAINER = 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
  25. BRANCH_COS_DEF = 'cn=nsPwPolicy_CoS,ou=people,dc=example,dc=com'
  26. BRANCH_PWP = 'cn=cn\\3DnsPwPolicyEntry\\2Cou\\3DPeople\\2Cdc\\3Dexample\\2Cdc\\3Dcom,' + \
  27. 'cn=nsPwPolicyContainer,ou=People,dc=example,dc=com'
  28. BRANCH_COS_TMPL = 'cn=cn\\3DnsPwTemplateEntry\\2Cou\\3DPeople\\2Cdc\\3Dexample\\2Cdc\\3Dcom,' + \
  29. 'cn=nsPwPolicyContainer,ou=People,dc=example,dc=com'
  30. SECOND_SUFFIX = 'o=netscaperoot'
  31. BE_NAME = 'netscaperoot'
  32. class TopologyStandalone(object):
  33. def __init__(self, standalone):
  34. standalone.open()
  35. self.standalone = standalone
  36. @pytest.fixture(scope="module")
  37. def topology(request):
  38. '''
  39. This fixture is used to standalone topology for the 'module'.
  40. '''
  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 instance and restart it if it exists
  49. instance_standalone = standalone.exists()
  50. # Remove the instance
  51. if instance_standalone:
  52. standalone.delete()
  53. # Create the instance
  54. standalone.create()
  55. # Used to retrieve configuration information (dbdir, confdir...)
  56. standalone.open()
  57. def fin():
  58. standalone.delete()
  59. request.addfinalizer(fin)
  60. # Here we have standalone instance up and running
  61. return TopologyStandalone(standalone)
  62. def addSubtreePwPolicy(inst):
  63. #
  64. # Add subtree policy to the people branch
  65. #
  66. try:
  67. inst.add_s(Entry((BRANCH_CONTAINER, {
  68. 'objectclass': 'top nsContainer'.split(),
  69. 'cn': 'nsPwPolicyContainer'
  70. })))
  71. except ldap.LDAPError as e:
  72. log.error('Failed to add subtree container for ou=people: error ' + e.message['desc'])
  73. assert False
  74. # Add the password policy subentry
  75. try:
  76. inst.add_s(Entry((BRANCH_PWP, {
  77. 'objectclass': 'top ldapsubentry passwordpolicy'.split(),
  78. 'cn': 'cn=nsPwPolicyEntry,ou=people,dc=example,dc=com',
  79. 'passwordMustChange': 'off',
  80. 'passwordExp': 'off',
  81. 'passwordHistory': 'off',
  82. 'passwordMinAge': '0',
  83. 'passwordChange': 'off',
  84. 'passwordStorageScheme': 'ssha'
  85. })))
  86. except ldap.LDAPError as e:
  87. log.error('Failed to add passwordpolicy: error ' + e.message['desc'])
  88. assert False
  89. # Add the COS template
  90. try:
  91. inst.add_s(Entry((BRANCH_COS_TMPL, {
  92. 'objectclass': 'top ldapsubentry costemplate extensibleObject'.split(),
  93. 'cn': 'cn=nsPwPolicyEntry,ou=people,dc=example,dc=com',
  94. 'cosPriority': '1',
  95. 'cn': 'cn=nsPwTemplateEntry,ou=people,dc=example,dc=com',
  96. 'pwdpolicysubentry': BRANCH_PWP
  97. })))
  98. except ldap.LDAPError as e:
  99. log.error('Failed to add COS template: error ' + e.message['desc'])
  100. assert False
  101. # Add the COS definition
  102. try:
  103. inst.add_s(Entry((BRANCH_COS_DEF, {
  104. 'objectclass': 'top ldapsubentry cosSuperDefinition cosPointerDefinition'.split(),
  105. 'cn': 'cn=nsPwPolicyEntry,ou=people,dc=example,dc=com',
  106. 'costemplatedn': BRANCH_COS_TMPL,
  107. 'cosAttribute': 'pwdpolicysubentry default operational-default'
  108. })))
  109. except ldap.LDAPError as e:
  110. log.error('Failed to add COS def: error ' + e.message['desc'])
  111. assert False
  112. time.sleep(0.5)
  113. def delSubtreePwPolicy(inst):
  114. try:
  115. inst.delete_s(BRANCH_COS_DEF)
  116. except ldap.LDAPError as e:
  117. log.error('Failed to delete COS def: error ' + e.message['desc'])
  118. assert False
  119. try:
  120. inst.delete_s(BRANCH_COS_TMPL)
  121. except ldap.LDAPError as e:
  122. log.error('Failed to delete COS template: error ' + e.message['desc'])
  123. assert False
  124. try:
  125. inst.delete_s(BRANCH_PWP)
  126. except ldap.LDAPError as e:
  127. log.error('Failed to delete COS password policy: error ' + e.message['desc'])
  128. assert False
  129. try:
  130. inst.delete_s(BRANCH_CONTAINER)
  131. except ldap.LDAPError as e:
  132. log.error('Failed to delete COS container: error ' + e.message['desc'])
  133. assert False
  134. time.sleep(0.5)
  135. def test_ticket47981(topology):
  136. """
  137. If there are multiple suffixes, and the last suffix checked does not contain any COS entries,
  138. while other suffixes do, then the vattr cache is not invalidated as it should be. Then any
  139. cached entries will still contain the old COS attributes/values.
  140. """
  141. log.info('Testing Ticket 47981 - Test that COS def changes are correctly reflected in affected users')
  142. #
  143. # Create a second backend that does not have any COS entries
  144. #
  145. log.info('Adding second suffix that will not contain any COS entries...\n')
  146. topology.standalone.backend.create(SECOND_SUFFIX, {BACKEND_NAME: BE_NAME})
  147. topology.standalone.mappingtree.create(SECOND_SUFFIX, bename=BE_NAME)
  148. try:
  149. topology.standalone.add_s(Entry((SECOND_SUFFIX, {
  150. 'objectclass': 'top organization'.split(),
  151. 'o': BE_NAME})))
  152. except ldap.ALREADY_EXISTS:
  153. pass
  154. except ldap.LDAPError as e:
  155. log.error('Failed to create suffix entry: error ' + e.message['desc'])
  156. assert False
  157. #
  158. # Add People branch, it might already exist
  159. #
  160. log.info('Add our test entries to the default suffix, and proceed with the test...')
  161. try:
  162. topology.standalone.add_s(Entry((BRANCH, {
  163. 'objectclass': 'top extensibleObject'.split(),
  164. 'ou': 'level4'
  165. })))
  166. except ldap.ALREADY_EXISTS:
  167. pass
  168. except ldap.LDAPError as e:
  169. log.error('Failed to add ou=people: error ' + e.message['desc'])
  170. assert False
  171. #
  172. # Add a user to the branch
  173. #
  174. try:
  175. topology.standalone.add_s(Entry((USER_DN, {
  176. 'objectclass': 'top extensibleObject'.split(),
  177. 'uid': 'user1'
  178. })))
  179. except ldap.LDAPError as e:
  180. log.error('Failed to add user1: error ' + e.message['desc'])
  181. assert False
  182. #
  183. # Enable password policy and add the subtree policy
  184. #
  185. try:
  186. topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-pwpolicy-local', 'on')])
  187. except ldap.LDAPError as e:
  188. log.error('Failed to set pwpolicy-local: error ' + e.message['desc'])
  189. assert False
  190. addSubtreePwPolicy(topology.standalone)
  191. #
  192. # Now check the user has its expected passwordPolicy subentry
  193. #
  194. try:
  195. entries = topology.standalone.search_s(USER_DN,
  196. ldap.SCOPE_BASE,
  197. '(objectclass=top)',
  198. ['pwdpolicysubentry', 'dn'])
  199. if not entries[0].hasAttr('pwdpolicysubentry'):
  200. log.fatal('User does not have expected pwdpolicysubentry!')
  201. assert False
  202. except ldap.LDAPError as e:
  203. log.fatal('Unable to search for entry %s: error %s' % (USER_DN, e.message['desc']))
  204. assert False
  205. #
  206. # Delete the password policy and make sure it is removed from the same user
  207. #
  208. delSubtreePwPolicy(topology.standalone)
  209. try:
  210. entries = topology.standalone.search_s(USER_DN, ldap.SCOPE_BASE, '(objectclass=top)', ['pwdpolicysubentry'])
  211. if entries[0].hasAttr('pwdpolicysubentry'):
  212. log.fatal('User unexpectedly does have the pwdpolicysubentry!')
  213. assert False
  214. except ldap.LDAPError as e:
  215. log.fatal('Unable to search for entry %s: error %s' % (USER_DN, e.message['desc']))
  216. assert False
  217. #
  218. # Add the subtree policvy back and see if the user now has it
  219. #
  220. addSubtreePwPolicy(topology.standalone)
  221. try:
  222. entries = topology.standalone.search_s(USER_DN, ldap.SCOPE_BASE, '(objectclass=top)', ['pwdpolicysubentry'])
  223. if not entries[0].hasAttr('pwdpolicysubentry'):
  224. log.fatal('User does not have expected pwdpolicysubentry!')
  225. assert False
  226. except ldap.LDAPError as e:
  227. log.fatal('Unable to search for entry %s: error %s' % (USER_DN, e.message['desc']))
  228. assert False
  229. if __name__ == '__main__':
  230. # Run isolated
  231. # -s for DEBUG mode
  232. CURRENT_FILE = os.path.realpath(__file__)
  233. pytest.main("-s %s" % CURRENT_FILE)