ticket47981_test.py 7.8 KB

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