regression_test.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2020 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 pytest
  11. import os
  12. import time
  13. import ldap
  14. from random import sample
  15. from lib389.utils import ds_is_older, ensure_list_bytes, ensure_bytes, ensure_str
  16. from lib389.topologies import topology_m1h1c1 as topo, topology_st, topology_m2 as topo_m2
  17. from lib389._constants import *
  18. from lib389.plugins import MemberOfPlugin
  19. from lib389 import Entry
  20. from lib389.idm.user import UserAccount, UserAccounts, TEST_USER_PROPERTIES
  21. from lib389.idm.group import Groups, Group
  22. from lib389.replica import ReplicationManager
  23. from lib389.tasks import *
  24. from lib389.idm.nscontainer import nsContainers
  25. # Skip on older versions
  26. pytestmark = [pytest.mark.tier1,
  27. pytest.mark.skipif(ds_is_older('1.3.7'), reason="Not implemented")]
  28. USER_CN = 'user_'
  29. GROUP_CN = 'group1'
  30. DEBUGGING = os.getenv('DEBUGGING', False)
  31. SUBTREE_1 = 'cn=sub1,%s' % SUFFIX
  32. SUBTREE_2 = 'cn=sub2,%s' % SUFFIX
  33. if DEBUGGING:
  34. logging.getLogger(__name__).setLevel(logging.DEBUG)
  35. else:
  36. logging.getLogger(__name__).setLevel(logging.INFO)
  37. log = logging.getLogger(__name__)
  38. def add_users(topo_m2, users_num, suffix):
  39. """Add users to the default suffix
  40. Return the list of added user DNs.
  41. """
  42. users_list = []
  43. users = UserAccounts(topo_m2.ms["master1"], suffix, rdn=None)
  44. log.info('Adding %d users' % users_num)
  45. for num in sample(list(range(1000)), users_num):
  46. num_ran = int(round(num))
  47. USER_NAME = 'test%05d' % num_ran
  48. user = users.create(properties={
  49. 'uid': USER_NAME,
  50. 'sn': USER_NAME,
  51. 'cn': USER_NAME,
  52. 'uidNumber': '%s' % num_ran,
  53. 'gidNumber': '%s' % num_ran,
  54. 'homeDirectory': '/home/%s' % USER_NAME,
  55. 'mail': '%[email protected]' % USER_NAME,
  56. 'userpassword': 'pass%s' % num_ran,
  57. })
  58. users_list.append(user)
  59. return users_list
  60. def config_memberof(server):
  61. # Configure fractional to prevent total init to send memberof
  62. memberof = MemberOfPlugin(server)
  63. memberof.enable()
  64. memberof.set_autoaddoc('nsMemberOf')
  65. server.restart()
  66. ents = server.agreement.list(suffix=DEFAULT_SUFFIX)
  67. for ent in ents:
  68. log.info('update %s to add nsDS5ReplicatedAttributeListTotal' % ent.dn)
  69. server.agreement.setProperties(agmnt_dn=ents[0].dn,
  70. properties={RA_FRAC_EXCLUDE: '(objectclass=*) $ EXCLUDE memberOf',
  71. RA_FRAC_EXCLUDE_TOTAL_UPDATE: '(objectclass=*) $ EXCLUDE '})
  72. def send_updates_now(server):
  73. ents = server.agreement.list(suffix=DEFAULT_SUFFIX)
  74. for ent in ents:
  75. server.agreement.pause(ent.dn)
  76. server.agreement.resume(ent.dn)
  77. def _find_memberof(server, member_dn, group_dn):
  78. # To get the specific server's (M1, C1 and H1) user and group
  79. user = UserAccount(server, member_dn)
  80. assert user.exists()
  81. group = Group(server, group_dn)
  82. assert group.exists()
  83. # test that the user entry should have memberof attribute with specified group dn value
  84. assert group._dn.lower() in user.get_attr_vals_utf8_l('memberOf')
  85. @pytest.mark.bz1352121
  86. def test_memberof_with_repl(topo):
  87. """Test that we allowed to enable MemberOf plugin in dedicated consumer
  88. :id: ef71cd7c-e792-41bf-a3c0-b3b38391cbe5
  89. :setup: 1 Master - 1 Hub - 1 Consumer
  90. :steps:
  91. 1. Configure replication to EXCLUDE memberof
  92. 2. Enable memberof plugin
  93. 3. Create users/groups
  94. 4. Make user_0 member of group_0
  95. 5. Checks that user_0 is memberof group_0 on M,H,C
  96. 6. Make group_0 member of group_1 (nest group)
  97. 7. Checks that user_0 is memberof group_0 and group_1 on M,H,C
  98. 8. Check group_0 is memberof group_1 on M,H,C
  99. 9. Remove group_0 from group_1
  100. 10. Check group_0 and user_0 are NOT memberof group_1 on M,H,C
  101. 11. Remove user_0 from group_0
  102. 12. Check user_0 is not memberof group_0 and group_1 on M,H,C
  103. 13. Disable memberof on C
  104. 14. make user_0 member of group_1
  105. 15. Checks that user_0 is memberof group_0 on M,H but not on C
  106. 16. Enable memberof on C
  107. 17. Checks that user_0 is memberof group_0 on M,H but not on C
  108. 18. Run memberof fixup task
  109. 19. Checks that user_0 is memberof group_0 on M,H,C
  110. :expectedresults:
  111. 1. Configuration should be successful
  112. 2. Plugin should be enabled
  113. 3. Users and groups should be created
  114. 4. user_0 should be member of group_0
  115. 5. user_0 should be memberof group_0 on M,H,C
  116. 6. group_0 should be member of group_1
  117. 7. user_0 should be memberof group_0 and group_1 on M,H,C
  118. 8. group_0 should be memberof group_1 on M,H,C
  119. 9. group_0 from group_1 removal should be successful
  120. 10. group_0 and user_0 should not be memberof group_1 on M,H,C
  121. 11. user_0 from group_0 remove should be successful
  122. 12. user_0 should not be memberof group_0 and group_1 on M,H,C
  123. 13. memberof should be disabled on C
  124. 14. user_0 should be member of group_1
  125. 15. user_0 should be memberof group_0 on M,H and should not on C
  126. 16. Enable memberof on C should be successful
  127. 17. user_0 should be memberof group_0 on M,H should not on C
  128. 18. memberof fixup task should be successful
  129. 19. user_0 should be memberof group_0 on M,H,C
  130. """
  131. M1 = topo.ms["master1"]
  132. H1 = topo.hs["hub1"]
  133. C1 = topo.cs["consumer1"]
  134. # Step 1 & 2
  135. M1.config.enable_log('audit')
  136. config_memberof(M1)
  137. M1.restart()
  138. H1.config.enable_log('audit')
  139. config_memberof(H1)
  140. H1.restart()
  141. C1.config.enable_log('audit')
  142. config_memberof(C1)
  143. C1.restart()
  144. #Declare lists of users and groups
  145. test_users = []
  146. test_groups = []
  147. # Step 3
  148. # In for loop create users and add them in the user list
  149. # it creates user_0 to user_9 (range is fun)
  150. for i in range(10):
  151. CN = '%s%d' % (USER_CN, i)
  152. users = UserAccounts(M1, SUFFIX)
  153. user_props = TEST_USER_PROPERTIES.copy()
  154. user_props.update({'uid': CN, 'cn': CN, 'sn': '_%s' % CN})
  155. testuser = users.create(properties=user_props)
  156. time.sleep(2)
  157. test_users.append(testuser)
  158. # In for loop create groups and add them to the group list
  159. # it creates group_0 to group_2 (range is fun)
  160. for i in range(3):
  161. CN = '%s%d' % (GROUP_CN, i)
  162. groups = Groups(M1, SUFFIX)
  163. testgroup = groups.create(properties={'cn': CN})
  164. time.sleep(2)
  165. test_groups.append(testgroup)
  166. # Step 4
  167. # Now start testing by adding differnt user to differn group
  168. if not ds_is_older('1.3.7'):
  169. test_groups[0].remove('objectClass', 'nsMemberOf')
  170. member_dn = test_users[0].dn
  171. grp0_dn = test_groups[0].dn
  172. grp1_dn = test_groups[1].dn
  173. test_groups[0].add_member(member_dn)
  174. time.sleep(2)
  175. # Step 5
  176. for i in [M1, H1, C1]:
  177. _find_memberof(i, member_dn, grp0_dn)
  178. # Step 6
  179. test_groups[1].add_member(test_groups[0].dn)
  180. time.sleep(2)
  181. # Step 7
  182. for i in [grp0_dn, grp1_dn]:
  183. for inst in [M1, H1, C1]:
  184. _find_memberof(inst, member_dn, i)
  185. # Step 8
  186. for i in [M1, H1, C1]:
  187. _find_memberof(i, grp0_dn, grp1_dn)
  188. # Step 9
  189. test_groups[1].remove_member(test_groups[0].dn)
  190. time.sleep(2)
  191. # Step 10
  192. # For negative testcase, we are using assertionerror
  193. for inst in [M1, H1, C1]:
  194. for i in [grp0_dn, member_dn]:
  195. with pytest.raises(AssertionError):
  196. _find_memberof(inst, i, grp1_dn)
  197. # Step 11
  198. test_groups[0].remove_member(member_dn)
  199. time.sleep(2)
  200. # Step 12
  201. for inst in [M1, H1, C1]:
  202. for grp in [grp0_dn, grp1_dn]:
  203. with pytest.raises(AssertionError):
  204. _find_memberof(inst, member_dn, grp)
  205. # Step 13
  206. C1.plugins.disable(name=PLUGIN_MEMBER_OF)
  207. C1.restart()
  208. # Step 14
  209. test_groups[0].add_member(member_dn)
  210. time.sleep(2)
  211. # Step 15
  212. for i in [M1, H1]:
  213. _find_memberof(i, member_dn, grp0_dn)
  214. with pytest.raises(AssertionError):
  215. _find_memberof(C1, member_dn, grp0_dn)
  216. # Step 16
  217. memberof = MemberOfPlugin(C1)
  218. memberof.enable()
  219. C1.restart()
  220. # Step 17
  221. for i in [M1, H1]:
  222. _find_memberof(i, member_dn, grp0_dn)
  223. with pytest.raises(AssertionError):
  224. _find_memberof(C1, member_dn, grp0_dn)
  225. # Step 18
  226. memberof.fixup(SUFFIX)
  227. # have to sleep instead of task.wait() because the task opens a thread and exits
  228. time.sleep(5)
  229. # Step 19
  230. for i in [M1, H1, C1]:
  231. _find_memberof(i, member_dn, grp0_dn)
  232. @pytest.mark.skipif(ds_is_older('1.3.7'), reason="Not implemented")
  233. def test_scheme_violation_errors_logged(topo_m2):
  234. """Check that ERR messages are verbose enough, if a member entry
  235. doesn't have the appropriate objectclass to support 'memberof' attribute
  236. :id: e2af0aaa-447e-4e85-a5ce-57ae66260d0b
  237. :setup: Standalone instance
  238. :steps:
  239. 1. Enable memberofPlugin and set autoaddoc to nsMemberOf
  240. 2. Restart the instance
  241. 3. Add a user without nsMemberOf attribute
  242. 4. Create a group and add the user to the group
  243. 5. Check that user has memberOf attribute
  244. 6. Check the error log for ".*oc_check_allowed_sv.*USER_DN.*memberOf.*not allowed.*"
  245. and ".*schema violation caught - repair operation.*" patterns
  246. :expectedresults:
  247. 1. Should be successful
  248. 2. Should be successful
  249. 3. Should be successful
  250. 4. Should be successful
  251. 5. User should have the attribute
  252. 6. Errors should be logged
  253. """
  254. inst = topo_m2.ms["master1"]
  255. memberof = MemberOfPlugin(inst)
  256. memberof.enable()
  257. memberof.set_autoaddoc('nsMemberOf')
  258. inst.restart()
  259. users = UserAccounts(inst, SUFFIX)
  260. user_props = TEST_USER_PROPERTIES.copy()
  261. user_props.update({'uid': USER_CN, 'cn': USER_CN, 'sn': USER_CN})
  262. testuser = users.create(properties=user_props)
  263. testuser.remove('objectclass', 'nsMemberOf')
  264. groups = Groups(inst, SUFFIX)
  265. testgroup = groups.create(properties={'cn': GROUP_CN})
  266. testgroup.add('member', testuser.dn)
  267. user_memberof_attr = testuser.get_attr_val_utf8('memberof')
  268. assert user_memberof_attr
  269. log.info('memberOf attr value - {}'.format(user_memberof_attr))
  270. pattern = ".*oc_check_allowed_sv.*{}.*memberOf.*not allowed.*".format(testuser.dn.lower())
  271. log.info("pattern = %s" % pattern)
  272. assert inst.ds_error_log.match(pattern)
  273. pattern = ".*schema violation caught - repair operation.*"
  274. assert inst.ds_error_log.match(pattern)
  275. @pytest.mark.bz1192099
  276. def test_memberof_with_changelog_reset(topo_m2):
  277. """Test that replication does not break, after DS stop-start, due to changelog reset
  278. :id: 60c11636-55a1-4704-9e09-2c6bcc828de4
  279. :setup: 2 Masters
  280. :steps:
  281. 1. On M1 and M2, Enable memberof
  282. 2. On M1, add 999 entries allowing memberof
  283. 3. On M1, add a group with these 999 entries as members
  284. 4. Stop M1 in between,
  285. when add the group memerof is called and before it is finished the
  286. add, so step 4 should be executed after memberof has started and
  287. before the add has finished
  288. 5. Check that replication is working fine
  289. :expectedresults:
  290. 1. memberof should be enabled
  291. 2. Entries should be added
  292. 3. Add operation should start
  293. 4. M1 should be stopped
  294. 5. Replication should be working fine
  295. """
  296. m1 = topo_m2.ms["master1"]
  297. m2 = topo_m2.ms["master2"]
  298. log.info("Configure memberof on M1 and M2")
  299. memberof = MemberOfPlugin(m1)
  300. memberof.enable()
  301. memberof.set_autoaddoc('nsMemberOf')
  302. m1.restart()
  303. memberof = MemberOfPlugin(m2)
  304. memberof.enable()
  305. memberof.set_autoaddoc('nsMemberOf')
  306. m2.restart()
  307. log.info("On M1, add 999 test entries allowing memberof")
  308. users_list = add_users(topo_m2, 999, DEFAULT_SUFFIX)
  309. log.info("On M1, add a group with these 999 entries as members")
  310. dic_of_attributes = {'cn': ensure_bytes('testgroup'),
  311. 'objectclass': ensure_list_bytes(['top', 'groupOfNames'])}
  312. for user in users_list:
  313. dic_of_attributes.setdefault('member', [])
  314. dic_of_attributes['member'].append(user.dn)
  315. log.info('Adding the test group using async function')
  316. groupdn = 'cn=testgroup,%s' % DEFAULT_SUFFIX
  317. m1.add(Entry((groupdn, dic_of_attributes)))
  318. #shutdown the server in-between adding the group
  319. m1.stop()
  320. #start the server
  321. m1.start()
  322. log.info("Check the log messages for error")
  323. error_msg = "ERR - NSMMReplicationPlugin - ruv_compare_ruv"
  324. assert not m1.ds_error_log.match(error_msg)
  325. log.info("Check that the replication is working fine both ways, M1 <-> M2")
  326. repl = ReplicationManager(DEFAULT_SUFFIX)
  327. repl.test_replication_topology(topo_m2)
  328. def add_container(inst, dn, name, sleep=False):
  329. """Creates container entry"""
  330. conts = nsContainers(inst, dn)
  331. cont = conts.create(properties={'cn': name})
  332. if sleep:
  333. time.sleep(1)
  334. return cont
  335. def add_member(server, cn, subtree):
  336. dn = subtree
  337. users = UserAccounts(server, dn, rdn=None)
  338. users.create(properties={'uid': 'test_%s' % cn,
  339. 'cn': "%s" % cn,
  340. 'sn': 'SN',
  341. 'description': 'member',
  342. 'uidNumber': '1000',
  343. 'gidNumber': '2000',
  344. 'homeDirectory': '/home/testuser'
  345. })
  346. def add_group(server, cn, subtree):
  347. group = Groups(server, subtree, rdn=None)
  348. group.create(properties={'cn': "%s" % cn,
  349. 'member': ['uid=test_m1,%s' % SUBTREE_1, 'uid=test_m2,%s' % SUBTREE_1],
  350. 'description': 'group'})
  351. def rename_entry(server, cn, from_subtree, to_subtree):
  352. dn = '%s,%s' % (cn, from_subtree)
  353. nrdn = '%s-new' % cn
  354. log.fatal('Renaming user (%s): new %s' % (dn, nrdn))
  355. server.rename_s(dn, nrdn, newsuperior=to_subtree, delold=0)
  356. def _find_memberof_ext(server, user_dn=None, group_dn=None, find_result=True):
  357. assert (server)
  358. assert (user_dn)
  359. assert (group_dn)
  360. ent = server.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  361. found = False
  362. if ent.hasAttr('memberof'):
  363. for val in ent.getValues('memberof'):
  364. server.log.info("!!!!!!! %s: memberof->%s" % (user_dn, val))
  365. if ensure_str(val) == group_dn:
  366. found = True
  367. break
  368. if find_result:
  369. assert found
  370. else:
  371. assert (not found)
  372. @pytest.mark.ds49161
  373. def test_memberof_group(topology_st):
  374. """Test memberof does not fail if group is moved into scope
  375. :id: d1d276ae-6375-4ad8-9437-6a0afcbee7d2
  376. :setup: Single instance
  377. :steps:
  378. 1. Enable memberof plugin and set memberofentryscope
  379. 2. Restart the server
  380. 3. Add test sub-suffixes
  381. 4. Add test users
  382. 5. Add test groups
  383. 6. Check for memberof attribute added to the test users
  384. 7. Rename the group entry
  385. 8. Check the new name is reflected in memberof attribute of user
  386. :expectedresults:
  387. 1. memberof plugin should be enabled and memberofentryscope should be set
  388. 2. Server should be restarted
  389. 3. Sub-suffixes should be added
  390. 4. Test users should be added
  391. 5. Test groups should be added
  392. 6. memberof attribute should be present in the test users
  393. 7. Group entry should be renamed
  394. 8. New group name should be present in memberof attribute of user
  395. """
  396. inst = topology_st.standalone
  397. log.info('Enable memberof plugin and set the scope as cn=sub1,dc=example,dc=com')
  398. memberof = MemberOfPlugin(inst)
  399. memberof.enable()
  400. memberof.replace('memberOfEntryScope', SUBTREE_1)
  401. inst.restart()
  402. add_container(inst, SUFFIX, 'sub1')
  403. add_container(inst, SUFFIX, 'sub2')
  404. add_member(inst, 'm1', SUBTREE_1)
  405. add_member(inst, 'm2', SUBTREE_1)
  406. add_group(inst, 'g1', SUBTREE_1)
  407. add_group(inst, 'g2', SUBTREE_2)
  408. # _check_memberof
  409. dn1 = '%s,%s' % ('uid=test_m1', SUBTREE_1)
  410. dn2 = '%s,%s' % ('uid=test_m2', SUBTREE_1)
  411. g1 = '%s,%s' % ('cn=g1', SUBTREE_1)
  412. g2 = '%s,%s' % ('cn=g2', SUBTREE_2)
  413. _find_memberof_ext(inst, dn1, g1, True)
  414. _find_memberof_ext(inst, dn2, g1, True)
  415. _find_memberof_ext(inst, dn1, g2, False)
  416. _find_memberof_ext(inst, dn2, g2, False)
  417. rename_entry(inst, 'cn=g2', SUBTREE_2, SUBTREE_1)
  418. g2n = '%s,%s' % ('cn=g2-new', SUBTREE_1)
  419. _find_memberof_ext(inst, dn1, g1, True)
  420. _find_memberof_ext(inst, dn2, g1, True)
  421. _find_memberof_ext(inst, dn1, g2n, True)
  422. _find_memberof_ext(inst, dn2, g2n, True)
  423. def _config_memberof_entrycache_on_modrdn_failure(server):
  424. server.plugins.enable(name=PLUGIN_MEMBER_OF)
  425. peoplebase = 'ou=people,%s' % SUFFIX
  426. MEMBEROF_PLUGIN_DN = ('cn=' + PLUGIN_MEMBER_OF + ',cn=plugins,cn=config')
  427. server.modify_s(MEMBEROF_PLUGIN_DN, [(ldap.MOD_REPLACE, 'memberOfAllBackends', b'on'),
  428. (ldap.MOD_REPLACE, 'memberOfEntryScope', peoplebase.encode()),
  429. (ldap.MOD_REPLACE, 'memberOfAutoAddOC', b'nsMemberOf')])
  430. def _disable_auto_oc_memberof(server):
  431. MEMBEROF_PLUGIN_DN = ('cn=' + PLUGIN_MEMBER_OF + ',cn=plugins,cn=config')
  432. server.modify_s(MEMBEROF_PLUGIN_DN,
  433. [(ldap.MOD_REPLACE, 'memberOfAutoAddOC', b'nsContainer')])
  434. @pytest.mark.ds49967
  435. def test_entrycache_on_modrdn_failure(topology_st):
  436. """This test checks that when a modrdn fails, the destination entry is not returned by a search
  437. This could happen in case the destination entry remains in the entry cache
  438. :id: a4d8ac0b-2448-406a-9dc2-5a72851e30b6
  439. :setup: Standalone Instance
  440. :steps:
  441. 1. configure memberof to only scope ou=people,SUFFIX
  442. 2. Creates 10 users
  443. 3. Create groups0 (in peoplebase) that contain user0 and user1
  444. 4. Check user0 and user1 have memberof=group0.dn
  445. 5. Create group1 (OUT peoplebase) that contain user0 and user1
  446. 6. Check user0 and user1 have NOT memberof=group1.dn
  447. 7. Move group1 IN peoplebase and check users0 and user1 HAVE memberof=group1.dn
  448. 8. Create group2 (OUT peoplebase) that contain user2 and user3. Group2 contains a specific description value
  449. 9. Check user2 and user3 have NOT memberof=group2.dn
  450. 10. configure memberof so that added objectclass does not allow 'memberof' attribute
  451. 11. Move group2 IN peoplebase and check move failed OPERATIONS_ERROR (because memberof failed)
  452. 12. Search all groups and check that the group, having the specific description value,
  453. has the original DN of group2.dn
  454. :expectedresults:
  455. 1. should succeed
  456. 2. should succeed
  457. 3. should succeed
  458. 4. should succeed
  459. 5. should succeed
  460. 6. should succeed
  461. 7. should succeed
  462. 8. should succeed
  463. 9. should succeed
  464. 10. should succeed
  465. 11. should fail OPERATION_ERROR because memberof plugin fails to add 'memberof' to members.
  466. 12. should succeed
  467. """
  468. # only scopes peoplebase
  469. _config_memberof_entrycache_on_modrdn_failure(topology_st.standalone)
  470. topology_st.standalone.restart(timeout=10)
  471. # create 10 users
  472. peoplebase = 'ou=people,%s' % SUFFIX
  473. for i in range(10):
  474. cn = 'user%d' % i
  475. dn = 'cn=%s,%s' % (cn, peoplebase)
  476. log.fatal('Adding user (%s): ' % dn)
  477. topology_st.standalone.add_s(Entry((dn, {'objectclass': ['top', 'person'],
  478. 'sn': 'user_%s' % cn,
  479. 'description': 'add on standalone'})))
  480. # Check that members of group0 (in the scope) have 'memberof
  481. group0_dn = 'cn=group_in0,%s' % peoplebase
  482. topology_st.standalone.add_s(Entry((group0_dn, {'objectclass': ['top', 'groupofnames'],
  483. 'member': [
  484. 'cn=user0,%s' % peoplebase,
  485. 'cn=user1,%s' % peoplebase,
  486. ],
  487. 'description': 'mygroup'})))
  488. # Check the those entries have memberof with group0
  489. for i in range(2):
  490. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  491. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  492. assert ent.hasAttr('memberof')
  493. found = False
  494. for val in ent.getValues('memberof'):
  495. topology_st.standalone.log.info("!!!!!!! %s: memberof->%s (vs %s)" % (user_dn, val, group0_dn.encode().lower()))
  496. if val.lower() == group0_dn.encode().lower():
  497. found = True
  498. break
  499. assert found
  500. # Create a group1 out of the scope
  501. group1_dn = 'cn=group_out1,%s' % SUFFIX
  502. topology_st.standalone.add_s(Entry((group1_dn, {'objectclass': ['top', 'groupofnames'],
  503. 'member': [
  504. 'cn=user0,%s' % peoplebase,
  505. 'cn=user1,%s' % peoplebase,
  506. ],
  507. 'description': 'mygroup'})))
  508. # Check the those entries have not memberof with group1
  509. for i in range(2):
  510. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  511. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  512. assert ent.hasAttr('memberof')
  513. found = False
  514. for val in ent.getValues('memberof'):
  515. topology_st.standalone.log.info("!!!!!!! %s: memberof->%s (vs %s)" % (user_dn, val, group1_dn.encode().lower()))
  516. if val.lower() == group1_dn.encode().lower():
  517. found = True
  518. break
  519. assert not found
  520. # move group1 into the scope and check user0 and user1 are memberof group1
  521. topology_st.standalone.rename_s(group1_dn, 'cn=group_in1', newsuperior=peoplebase, delold=0)
  522. new_group1_dn = 'cn=group_in1,%s' % peoplebase
  523. for i in range(2):
  524. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  525. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  526. assert ent.hasAttr('memberof')
  527. found = False
  528. for val in ent.getValues('memberof'):
  529. topology_st.standalone.log.info("!!!!!!! %s: memberof->%s (vs %s)" % (user_dn, val, new_group1_dn.encode().lower()))
  530. if val.lower() == new_group1_dn.encode().lower():
  531. found = True
  532. break
  533. assert found
  534. # Create a group2 out of the scope with a SPECIFIC description value
  535. entry_description = "this is to check that the entry having this description has the appropriate DN"
  536. group2_dn = 'cn=group_out2,%s' % SUFFIX
  537. topology_st.standalone.add_s(Entry((group2_dn, {'objectclass': ['top', 'groupofnames'],
  538. 'member': [
  539. 'cn=user2,%s' % peoplebase,
  540. 'cn=user3,%s' % peoplebase,
  541. ],
  542. 'description': entry_description})))
  543. # Check the those entries have not memberof with group2
  544. for i in (2, 3):
  545. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  546. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  547. assert not ent.hasAttr('memberof')
  548. # memberof will not add the missing objectclass
  549. _disable_auto_oc_memberof(topology_st.standalone)
  550. topology_st.standalone.restart(timeout=10)
  551. # move group2 into the scope and check it fails
  552. try:
  553. topology_st.standalone.rename_s(group2_dn, 'cn=group_in2', newsuperior=peoplebase, delold=0)
  554. topology_st.standalone.log.info("This is unexpected, modrdn should fail as the member entry have not the appropriate objectclass")
  555. assert False
  556. except ldap.OBJECT_CLASS_VIOLATION:
  557. pass
  558. # retrieve the entry having the specific description value
  559. # check that the entry DN is the original group2 DN
  560. ents = topology_st.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, '(cn=gr*)')
  561. found = False
  562. for ent in ents:
  563. topology_st.standalone.log.info("retrieve: %s with desc=%s" % (ent.dn, ent.getValue('description')))
  564. if ent.getValue('description') == entry_description.encode():
  565. found = True
  566. assert ent.dn == group2_dn
  567. assert found
  568. def _config_memberof_silent_memberof_failure(server):
  569. _config_memberof_entrycache_on_modrdn_failure(server)
  570. def test_silent_memberof_failure(topology_st):
  571. """This test checks that if during a MODRDN, the memberof plugin fails
  572. then MODRDN also fails
  573. :id: 095aee01-581c-43dd-a241-71f9631a18bb
  574. :setup: Standalone Instance
  575. :steps:
  576. 1. configure memberof to only scope ou=people,SUFFIX
  577. 2. Do some cleanup and Creates 10 users
  578. 3. Create groups0 (IN peoplebase) that contain user0 and user1
  579. 4. Check user0 and user1 have memberof=group0.dn
  580. 5. Create group1 (OUT peoplebase) that contain user0 and user1
  581. 6. Check user0 and user1 have NOT memberof=group1.dn
  582. 7. Move group1 IN peoplebase and check users0 and user1 HAVE memberof=group1.dn
  583. 8. Create group2 (OUT peoplebase) that contain user2 and user3.
  584. 9. Check user2 and user3 have NOT memberof=group2.dn
  585. 10. configure memberof so that added objectclass does not allow 'memberof' attribute
  586. 11. Move group2 IN peoplebase and check move failed OPERATIONS_ERROR (because memberof failed)
  587. 12. Check user2 and user3 have NOT memberof=group2.dn
  588. 13. ADD group3 (IN peoplebase) with user4 and user5 members and check add failed OPERATIONS_ERROR (because memberof failed)
  589. 14. Check user4 and user5 have NOT memberof=group2.dn
  590. :expectedresults:
  591. 1. should succeed
  592. 2. should succeed
  593. 3. should succeed
  594. 4. should succeed
  595. 5. should succeed
  596. 6. should succeed
  597. 7. should succeed
  598. 8. should succeed
  599. 9. should succeed
  600. 10. should succeed
  601. 11. should fail OPERATION_ERROR because memberof plugin fails to add 'memberof' to members.
  602. 12. should succeed
  603. 13. should fail OPERATION_ERROR because memberof plugin fails to add 'memberof' to members
  604. 14. should succeed
  605. """
  606. # only scopes peoplebase
  607. _config_memberof_silent_memberof_failure(topology_st.standalone)
  608. topology_st.standalone.restart(timeout=10)
  609. # first do some cleanup
  610. peoplebase = 'ou=people,%s' % SUFFIX
  611. for i in range(10):
  612. cn = 'user%d' % i
  613. dn = 'cn=%s,%s' % (cn, peoplebase)
  614. topology_st.standalone.delete_s(dn)
  615. topology_st.standalone.delete_s('cn=group_in0,%s' % peoplebase)
  616. topology_st.standalone.delete_s('cn=group_in1,%s' % peoplebase)
  617. topology_st.standalone.delete_s('cn=group_out2,%s' % SUFFIX)
  618. # create 10 users
  619. for i in range(10):
  620. cn = 'user%d' % i
  621. dn = 'cn=%s,%s' % (cn, peoplebase)
  622. log.fatal('Adding user (%s): ' % dn)
  623. topology_st.standalone.add_s(Entry((dn, {'objectclass': ['top', 'person'],
  624. 'sn': 'user_%s' % cn,
  625. 'description': 'add on standalone'})))
  626. # Check that members of group0 (in the scope) have 'memberof
  627. group0_dn = 'cn=group_in0,%s' % peoplebase
  628. topology_st.standalone.add_s(Entry((group0_dn, {'objectclass': ['top', 'groupofnames'],
  629. 'member': [
  630. 'cn=user0,%s' % peoplebase,
  631. 'cn=user1,%s' % peoplebase,
  632. ],
  633. 'description': 'mygroup'})))
  634. # Check the those entries have memberof with group0
  635. for i in range(2):
  636. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  637. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  638. assert ent.hasAttr('memberof')
  639. found = False
  640. for val in ent.getValues('memberof'):
  641. topology_st.standalone.log.info("!!!!!!! %s: memberof->%s (vs %s)" % (user_dn, val, group0_dn.encode().lower()))
  642. if val.lower() == group0_dn.encode().lower():
  643. found = True
  644. break
  645. assert found
  646. # Create a group1 out of the scope
  647. group1_dn = 'cn=group_out1,%s' % SUFFIX
  648. topology_st.standalone.add_s(Entry((group1_dn, {'objectclass': ['top', 'groupofnames'],
  649. 'member': [
  650. 'cn=user0,%s' % peoplebase,
  651. 'cn=user1,%s' % peoplebase,
  652. ],
  653. 'description': 'mygroup'})))
  654. # Check the those entries have not memberof with group1
  655. for i in range(2):
  656. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  657. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  658. assert ent.hasAttr('memberof')
  659. found = False
  660. for val in ent.getValues('memberof'):
  661. topology_st.standalone.log.info("!!!!!!! %s: memberof->%s (vs %s)" % (user_dn, val, group1_dn.encode().lower()))
  662. if val.lower() == group1_dn.encode().lower():
  663. found = True
  664. break
  665. assert not found
  666. # move group1 into the scope and check user0 and user1 are memberof group1
  667. topology_st.standalone.rename_s(group1_dn, 'cn=group_in1', newsuperior=peoplebase, delold=0)
  668. new_group1_dn = 'cn=group_in1,%s' % peoplebase
  669. for i in range(2):
  670. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  671. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  672. assert ent.hasAttr('memberof')
  673. found = False
  674. for val in ent.getValues('memberof'):
  675. topology_st.standalone.log.info("!!!!!!! %s: memberof->%s (vs %s)" % (user_dn, val, new_group1_dn.encode().lower()))
  676. if val.lower() == new_group1_dn.encode().lower():
  677. found = True
  678. break
  679. assert found
  680. # Create a group2 out of the scope
  681. group2_dn = 'cn=group_out2,%s' % SUFFIX
  682. topology_st.standalone.add_s(Entry((group2_dn, {'objectclass': ['top', 'groupofnames'],
  683. 'member': [
  684. 'cn=user2,%s' % peoplebase,
  685. 'cn=user3,%s' % peoplebase,
  686. ],
  687. 'description': 'mygroup'})))
  688. # Check the those entries have not memberof with group2
  689. for i in (2, 3):
  690. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  691. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  692. assert not ent.hasAttr('memberof')
  693. # memberof will not add the missing objectclass
  694. _disable_auto_oc_memberof(topology_st.standalone)
  695. topology_st.standalone.restart(timeout=10)
  696. # move group2 into the scope and check it fails
  697. try:
  698. topology_st.standalone.rename_s(group2_dn, 'cn=group_in2', newsuperior=peoplebase, delold=0)
  699. topology_st.standalone.log.info("This is unexpected, modrdn should fail as the member entry have not the appropriate objectclass")
  700. assert False
  701. except ldap.OBJECT_CLASS_VIOLATION:
  702. pass
  703. # Check the those entries have not memberof
  704. for i in (2, 3):
  705. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  706. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  707. topology_st.standalone.log.info("Should assert %s has memberof is %s" % (user_dn, ent.hasAttr('memberof')))
  708. assert not ent.hasAttr('memberof')
  709. # Create a group3 in the scope
  710. group3_dn = 'cn=group3_in,%s' % peoplebase
  711. try:
  712. topology_st.standalone.add_s(Entry((group3_dn, {'objectclass': ['top', 'groupofnames'],
  713. 'member': [
  714. 'cn=user4,%s' % peoplebase,
  715. 'cn=user5,%s' % peoplebase,
  716. ],
  717. 'description': 'mygroup'})))
  718. topology_st.standalone.log.info("This is unexpected, ADD should fail as the member entry have not the appropriate objectclass")
  719. assert False
  720. except ldap.OBJECT_CLASS_VIOLATION:
  721. pass
  722. except ldap.OPERATIONS_ERROR:
  723. pass
  724. # Check the those entries do not have memberof
  725. for i in (4, 5):
  726. user_dn = 'cn=user%d,%s' % (i, peoplebase)
  727. ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
  728. topology_st.standalone.log.info("Should assert %s has memberof is %s" % (user_dn, ent.hasAttr('memberof')))
  729. assert not ent.hasAttr('memberof')
  730. if __name__ == '__main__':
  731. # Run isolated
  732. # -s for DEBUG mode
  733. CURRENT_FILE = os.path.realpath(__file__)
  734. pytest.main("-s %s" % CURRENT_FILE)