ticket47823_test.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  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 re
  11. import shutil
  12. import subprocess
  13. import time
  14. import ldap
  15. import pytest
  16. from lib389 import Entry
  17. from lib389._constants import *
  18. from lib389.topologies import topology_st
  19. log = logging.getLogger(__name__)
  20. PROVISIONING_CN = "provisioning"
  21. PROVISIONING_DN = "cn=%s,%s" % (PROVISIONING_CN, SUFFIX)
  22. ACTIVE_CN = "accounts"
  23. STAGE_CN = "staged users"
  24. DELETE_CN = "deleted users"
  25. ACTIVE_DN = "cn=%s,%s" % (ACTIVE_CN, SUFFIX)
  26. STAGE_DN = "cn=%s,%s" % (STAGE_CN, PROVISIONING_DN)
  27. DELETE_DN = "cn=%s,%s" % (DELETE_CN, PROVISIONING_DN)
  28. STAGE_USER_CN = "stage guy"
  29. STAGE_USER_DN = "cn=%s,%s" % (STAGE_USER_CN, STAGE_DN)
  30. ACTIVE_USER_CN = "active guy"
  31. ACTIVE_USER_DN = "cn=%s,%s" % (ACTIVE_USER_CN, ACTIVE_DN)
  32. ACTIVE_USER_1_CN = "test_1"
  33. ACTIVE_USER_1_DN = "cn=%s,%s" % (ACTIVE_USER_1_CN, ACTIVE_DN)
  34. ACTIVE_USER_2_CN = "test_2"
  35. ACTIVE_USER_2_DN = "cn=%s,%s" % (ACTIVE_USER_2_CN, ACTIVE_DN)
  36. STAGE_USER_1_CN = ACTIVE_USER_1_CN
  37. STAGE_USER_1_DN = "cn=%s,%s" % (STAGE_USER_1_CN, STAGE_DN)
  38. STAGE_USER_2_CN = ACTIVE_USER_2_CN
  39. STAGE_USER_2_DN = "cn=%s,%s" % (STAGE_USER_2_CN, STAGE_DN)
  40. ALL_CONFIG_ATTRS = ['nsslapd-pluginarg0', 'nsslapd-pluginarg1', 'nsslapd-pluginarg2',
  41. 'uniqueness-attribute-name', 'uniqueness-subtrees', 'uniqueness-across-all-subtrees']
  42. def _header(topology_st, label):
  43. topology_st.standalone.log.info("\n\n###############################################")
  44. topology_st.standalone.log.info("#######")
  45. topology_st.standalone.log.info("####### %s" % label)
  46. topology_st.standalone.log.info("#######")
  47. topology_st.standalone.log.info("###############################################")
  48. def _uniqueness_config_entry(topology_st, name=None):
  49. if not name:
  50. return None
  51. ent = topology_st.standalone.getEntry("cn=%s,%s" % (PLUGIN_ATTR_UNIQUENESS, DN_PLUGIN), ldap.SCOPE_BASE,
  52. "(objectclass=nsSlapdPlugin)",
  53. ['objectClass', 'cn', 'nsslapd-pluginPath', 'nsslapd-pluginInitfunc',
  54. 'nsslapd-pluginType', 'nsslapd-pluginEnabled',
  55. 'nsslapd-plugin-depends-on-type',
  56. 'nsslapd-pluginId', 'nsslapd-pluginVersion', 'nsslapd-pluginVendor',
  57. 'nsslapd-pluginDescription'])
  58. ent.dn = "cn=%s uniqueness,%s" % (name, DN_PLUGIN)
  59. return ent
  60. def _build_config(topology_st, attr_name='cn', subtree_1=None, subtree_2=None, type_config='old',
  61. across_subtrees=False):
  62. assert topology_st
  63. assert attr_name
  64. assert subtree_1
  65. if type_config == 'old':
  66. # enable the 'cn' uniqueness on Active
  67. config = _uniqueness_config_entry(topology_st, attr_name)
  68. config.setValue('nsslapd-pluginarg0', attr_name)
  69. config.setValue('nsslapd-pluginarg1', subtree_1)
  70. if subtree_2:
  71. config.setValue('nsslapd-pluginarg2', subtree_2)
  72. else:
  73. # prepare the config entry
  74. config = _uniqueness_config_entry(topology_st, attr_name)
  75. config.setValue('uniqueness-attribute-name', attr_name)
  76. config.setValue('uniqueness-subtrees', subtree_1)
  77. if subtree_2:
  78. config.setValue('uniqueness-subtrees', subtree_2)
  79. if across_subtrees:
  80. config.setValue('uniqueness-across-all-subtrees', 'on')
  81. return config
  82. def _active_container_invalid_cfg_add(topology_st):
  83. '''
  84. Check uniqueness is not enforced with ADD (invalid config)
  85. '''
  86. topology_st.standalone.add_s(Entry((ACTIVE_USER_1_DN, {
  87. 'objectclass': "top person".split(),
  88. 'sn': ACTIVE_USER_1_CN,
  89. 'cn': ACTIVE_USER_1_CN})))
  90. topology_st.standalone.add_s(Entry((ACTIVE_USER_2_DN, {
  91. 'objectclass': "top person".split(),
  92. 'sn': ACTIVE_USER_2_CN,
  93. 'cn': [ACTIVE_USER_1_CN, ACTIVE_USER_2_CN]})))
  94. topology_st.standalone.delete_s(ACTIVE_USER_1_DN)
  95. topology_st.standalone.delete_s(ACTIVE_USER_2_DN)
  96. def _active_container_add(topology_st, type_config='old'):
  97. '''
  98. Check uniqueness in a single container (Active)
  99. Add an entry with a given 'cn', then check we can not add an entry with the same 'cn' value
  100. '''
  101. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config=type_config,
  102. across_subtrees=False)
  103. # remove the 'cn' uniqueness entry
  104. try:
  105. topology_st.standalone.delete_s(config.dn)
  106. except ldap.NO_SUCH_OBJECT:
  107. pass
  108. topology_st.standalone.restart(timeout=120)
  109. topology_st.standalone.log.info('Uniqueness not enforced: create the entries')
  110. topology_st.standalone.add_s(Entry((ACTIVE_USER_1_DN, {
  111. 'objectclass': "top person".split(),
  112. 'sn': ACTIVE_USER_1_CN,
  113. 'cn': ACTIVE_USER_1_CN})))
  114. topology_st.standalone.add_s(Entry((ACTIVE_USER_2_DN, {
  115. 'objectclass': "top person".split(),
  116. 'sn': ACTIVE_USER_2_CN,
  117. 'cn': [ACTIVE_USER_1_CN, ACTIVE_USER_2_CN]})))
  118. topology_st.standalone.delete_s(ACTIVE_USER_1_DN)
  119. topology_st.standalone.delete_s(ACTIVE_USER_2_DN)
  120. topology_st.standalone.log.info('Uniqueness enforced: checks second entry is rejected')
  121. # enable the 'cn' uniqueness on Active
  122. topology_st.standalone.add_s(config)
  123. topology_st.standalone.restart(timeout=120)
  124. topology_st.standalone.add_s(Entry((ACTIVE_USER_1_DN, {
  125. 'objectclass': "top person".split(),
  126. 'sn': ACTIVE_USER_1_CN,
  127. 'cn': ACTIVE_USER_1_CN})))
  128. try:
  129. topology_st.standalone.add_s(Entry((ACTIVE_USER_2_DN, {
  130. 'objectclass': "top person".split(),
  131. 'sn': ACTIVE_USER_2_CN,
  132. 'cn': [ACTIVE_USER_1_CN, ACTIVE_USER_2_CN]})))
  133. except ldap.CONSTRAINT_VIOLATION:
  134. # yes it is expected
  135. pass
  136. # cleanup the stuff now
  137. topology_st.standalone.delete_s(config.dn)
  138. topology_st.standalone.delete_s(ACTIVE_USER_1_DN)
  139. def _active_container_mod(topology_st, type_config='old'):
  140. '''
  141. Check uniqueness in a single container (active)
  142. Add and entry with a given 'cn', then check we can not modify an entry with the same 'cn' value
  143. '''
  144. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config=type_config,
  145. across_subtrees=False)
  146. # enable the 'cn' uniqueness on Active
  147. topology_st.standalone.add_s(config)
  148. topology_st.standalone.restart(timeout=120)
  149. topology_st.standalone.log.info('Uniqueness enforced: checks MOD ADD entry is rejected')
  150. topology_st.standalone.add_s(Entry((ACTIVE_USER_1_DN, {
  151. 'objectclass': "top person".split(),
  152. 'sn': ACTIVE_USER_1_CN,
  153. 'cn': ACTIVE_USER_1_CN})))
  154. topology_st.standalone.add_s(Entry((ACTIVE_USER_2_DN, {
  155. 'objectclass': "top person".split(),
  156. 'sn': ACTIVE_USER_2_CN,
  157. 'cn': ACTIVE_USER_2_CN})))
  158. try:
  159. topology_st.standalone.modify_s(ACTIVE_USER_2_DN, [(ldap.MOD_ADD, 'cn', ACTIVE_USER_1_CN)])
  160. except ldap.CONSTRAINT_VIOLATION:
  161. # yes it is expected
  162. pass
  163. topology_st.standalone.log.info('Uniqueness enforced: checks MOD REPLACE entry is rejected')
  164. try:
  165. topology_st.standalone.modify_s(ACTIVE_USER_2_DN,
  166. [(ldap.MOD_REPLACE, 'cn', [ACTIVE_USER_1_CN, ACTIVE_USER_2_CN])])
  167. except ldap.CONSTRAINT_VIOLATION:
  168. # yes it is expected
  169. pass
  170. # cleanup the stuff now
  171. topology_st.standalone.delete_s(config.dn)
  172. topology_st.standalone.delete_s(ACTIVE_USER_1_DN)
  173. topology_st.standalone.delete_s(ACTIVE_USER_2_DN)
  174. def _active_container_modrdn(topology_st, type_config='old'):
  175. '''
  176. Check uniqueness in a single container
  177. Add and entry with a given 'cn', then check we can not modrdn an entry with the same 'cn' value
  178. '''
  179. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config=type_config,
  180. across_subtrees=False)
  181. # enable the 'cn' uniqueness on Active
  182. topology_st.standalone.add_s(config)
  183. topology_st.standalone.restart(timeout=120)
  184. topology_st.standalone.log.info('Uniqueness enforced: checks MODRDN entry is rejected')
  185. topology_st.standalone.add_s(Entry((ACTIVE_USER_1_DN, {
  186. 'objectclass': "top person".split(),
  187. 'sn': ACTIVE_USER_1_CN,
  188. 'cn': [ACTIVE_USER_1_CN, 'dummy']})))
  189. topology_st.standalone.add_s(Entry((ACTIVE_USER_2_DN, {
  190. 'objectclass': "top person".split(),
  191. 'sn': ACTIVE_USER_2_CN,
  192. 'cn': ACTIVE_USER_2_CN})))
  193. try:
  194. topology_st.standalone.rename_s(ACTIVE_USER_2_DN, 'cn=dummy', delold=0)
  195. except ldap.CONSTRAINT_VIOLATION:
  196. # yes it is expected
  197. pass
  198. # cleanup the stuff now
  199. topology_st.standalone.delete_s(config.dn)
  200. topology_st.standalone.delete_s(ACTIVE_USER_1_DN)
  201. topology_st.standalone.delete_s(ACTIVE_USER_2_DN)
  202. def _active_stage_containers_add(topology_st, type_config='old', across_subtrees=False):
  203. '''
  204. Check uniqueness in several containers
  205. Add an entry on a container with a given 'cn'
  206. with across_subtrees=False check we CAN add an entry with the same 'cn' value on the other container
  207. with across_subtrees=True check we CAN NOT add an entry with the same 'cn' value on the other container
  208. '''
  209. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=STAGE_DN,
  210. type_config=type_config, across_subtrees=False)
  211. topology_st.standalone.add_s(config)
  212. topology_st.standalone.restart(timeout=120)
  213. topology_st.standalone.add_s(Entry((ACTIVE_USER_1_DN, {
  214. 'objectclass': "top person".split(),
  215. 'sn': ACTIVE_USER_1_CN,
  216. 'cn': ACTIVE_USER_1_CN})))
  217. try:
  218. # adding an entry on a separated contains with the same 'cn'
  219. topology_st.standalone.add_s(Entry((STAGE_USER_1_DN, {
  220. 'objectclass': "top person".split(),
  221. 'sn': STAGE_USER_1_CN,
  222. 'cn': ACTIVE_USER_1_CN})))
  223. except ldap.CONSTRAINT_VIOLATION:
  224. assert across_subtrees
  225. # cleanup the stuff now
  226. topology_st.standalone.delete_s(config.dn)
  227. topology_st.standalone.delete_s(ACTIVE_USER_1_DN)
  228. topology_st.standalone.delete_s(STAGE_USER_1_DN)
  229. def _active_stage_containers_mod(topology_st, type_config='old', across_subtrees=False):
  230. '''
  231. Check uniqueness in a several containers
  232. Add an entry on a container with a given 'cn', then check we CAN mod an entry with the same 'cn' value on the other container
  233. '''
  234. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=STAGE_DN,
  235. type_config=type_config, across_subtrees=False)
  236. topology_st.standalone.add_s(config)
  237. topology_st.standalone.restart(timeout=120)
  238. # adding an entry on active with a different 'cn'
  239. topology_st.standalone.add_s(Entry((ACTIVE_USER_1_DN, {
  240. 'objectclass': "top person".split(),
  241. 'sn': ACTIVE_USER_1_CN,
  242. 'cn': ACTIVE_USER_2_CN})))
  243. # adding an entry on a stage with a different 'cn'
  244. topology_st.standalone.add_s(Entry((STAGE_USER_1_DN, {
  245. 'objectclass': "top person".split(),
  246. 'sn': STAGE_USER_1_CN,
  247. 'cn': STAGE_USER_1_CN})))
  248. try:
  249. # modify add same value
  250. topology_st.standalone.modify_s(STAGE_USER_1_DN, [(ldap.MOD_ADD, 'cn', [ACTIVE_USER_2_CN])])
  251. except ldap.CONSTRAINT_VIOLATION:
  252. assert across_subtrees
  253. topology_st.standalone.delete_s(STAGE_USER_1_DN)
  254. topology_st.standalone.add_s(Entry((STAGE_USER_1_DN, {
  255. 'objectclass': "top person".split(),
  256. 'sn': STAGE_USER_1_CN,
  257. 'cn': STAGE_USER_2_CN})))
  258. try:
  259. # modify replace same value
  260. topology_st.standalone.modify_s(STAGE_USER_1_DN,
  261. [(ldap.MOD_REPLACE, 'cn', [STAGE_USER_2_CN, ACTIVE_USER_1_CN])])
  262. except ldap.CONSTRAINT_VIOLATION:
  263. assert across_subtrees
  264. # cleanup the stuff now
  265. topology_st.standalone.delete_s(config.dn)
  266. topology_st.standalone.delete_s(ACTIVE_USER_1_DN)
  267. topology_st.standalone.delete_s(STAGE_USER_1_DN)
  268. def _active_stage_containers_modrdn(topology_st, type_config='old', across_subtrees=False):
  269. '''
  270. Check uniqueness in a several containers
  271. Add and entry with a given 'cn', then check we CAN modrdn an entry with the same 'cn' value on the other container
  272. '''
  273. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=STAGE_DN,
  274. type_config=type_config, across_subtrees=False)
  275. # enable the 'cn' uniqueness on Active and Stage
  276. topology_st.standalone.add_s(config)
  277. topology_st.standalone.restart(timeout=120)
  278. topology_st.standalone.add_s(Entry((ACTIVE_USER_1_DN, {
  279. 'objectclass': "top person".split(),
  280. 'sn': ACTIVE_USER_1_CN,
  281. 'cn': [ACTIVE_USER_1_CN, 'dummy']})))
  282. topology_st.standalone.add_s(Entry((STAGE_USER_1_DN, {
  283. 'objectclass': "top person".split(),
  284. 'sn': STAGE_USER_1_CN,
  285. 'cn': STAGE_USER_1_CN})))
  286. try:
  287. topology_st.standalone.rename_s(STAGE_USER_1_DN, 'cn=dummy', delold=0)
  288. # check stage entry has 'cn=dummy'
  289. stage_ent = topology_st.standalone.getEntry("cn=dummy,%s" % (STAGE_DN), ldap.SCOPE_BASE, "objectclass=*",
  290. ['cn'])
  291. assert stage_ent.hasAttr('cn')
  292. found = False
  293. for value in stage_ent.getValues('cn'):
  294. if value == 'dummy':
  295. found = True
  296. assert found
  297. # check active entry has 'cn=dummy'
  298. active_ent = topology_st.standalone.getEntry(ACTIVE_USER_1_DN, ldap.SCOPE_BASE, "objectclass=*", ['cn'])
  299. assert active_ent.hasAttr('cn')
  300. found = False
  301. for value in stage_ent.getValues('cn'):
  302. if value == 'dummy':
  303. found = True
  304. assert found
  305. topology_st.standalone.delete_s("cn=dummy,%s" % (STAGE_DN))
  306. except ldap.CONSTRAINT_VIOLATION:
  307. assert across_subtrees
  308. topology_st.standalone.delete_s(STAGE_USER_1_DN)
  309. # cleanup the stuff now
  310. topology_st.standalone.delete_s(config.dn)
  311. topology_st.standalone.delete_s(ACTIVE_USER_1_DN)
  312. def _config_file(topology_st, action='save'):
  313. dse_ldif = topology_st.standalone.confdir + '/dse.ldif'
  314. sav_file = topology_st.standalone.confdir + '/dse.ldif.ticket47823'
  315. if action == 'save':
  316. shutil.copy(dse_ldif, sav_file)
  317. else:
  318. shutil.copy(sav_file, dse_ldif)
  319. time.sleep(1)
  320. def _pattern_errorlog(file, log_pattern):
  321. try:
  322. _pattern_errorlog.last_pos += 1
  323. except AttributeError:
  324. _pattern_errorlog.last_pos = 0
  325. found = None
  326. log.debug("_pattern_errorlog: start at offset %d" % _pattern_errorlog.last_pos)
  327. file.seek(_pattern_errorlog.last_pos)
  328. # Use a while true iteration because 'for line in file: hit a
  329. # python bug that break file.tell()
  330. while True:
  331. line = file.readline()
  332. log.debug("_pattern_errorlog: [%d] %s" % (file.tell(), line))
  333. found = log_pattern.search(line)
  334. if ((line == '') or (found)):
  335. break
  336. log.debug("_pattern_errorlog: end at offset %d" % file.tell())
  337. _pattern_errorlog.last_pos = file.tell()
  338. return found
  339. def test_ticket47823_init(topology_st):
  340. """
  341. """
  342. # Enabled the plugins
  343. topology_st.standalone.plugins.enable(name=PLUGIN_ATTR_UNIQUENESS)
  344. topology_st.standalone.restart(timeout=120)
  345. topology_st.standalone.add_s(Entry((PROVISIONING_DN, {'objectclass': "top nscontainer".split(),
  346. 'cn': PROVISIONING_CN})))
  347. topology_st.standalone.add_s(Entry((ACTIVE_DN, {'objectclass': "top nscontainer".split(),
  348. 'cn': ACTIVE_CN})))
  349. topology_st.standalone.add_s(Entry((STAGE_DN, {'objectclass': "top nscontainer".split(),
  350. 'cn': STAGE_CN})))
  351. topology_st.standalone.add_s(Entry((DELETE_DN, {'objectclass': "top nscontainer".split(),
  352. 'cn': DELETE_CN})))
  353. topology_st.standalone.errorlog_file = open(topology_st.standalone.errlog, "r")
  354. topology_st.standalone.stop(timeout=120)
  355. time.sleep(1)
  356. topology_st.standalone.start(timeout=120)
  357. time.sleep(3)
  358. def test_ticket47823_one_container_add(topology_st):
  359. '''
  360. Check uniqueness in a single container
  361. Add and entry with a given 'cn', then check we can not add an entry with the same 'cn' value
  362. '''
  363. _header(topology_st, "With former config (args), check attribute uniqueness with 'cn' (ADD) ")
  364. _active_container_add(topology_st, type_config='old')
  365. _header(topology_st, "With new config (args), check attribute uniqueness with 'cn' (ADD) ")
  366. _active_container_add(topology_st, type_config='new')
  367. def test_ticket47823_one_container_mod(topology_st):
  368. '''
  369. Check uniqueness in a single container
  370. Add and entry with a given 'cn', then check we can not modify an entry with the same 'cn' value
  371. '''
  372. _header(topology_st, "With former config (args), check attribute uniqueness with 'cn' (MOD)")
  373. _active_container_mod(topology_st, type_config='old')
  374. _header(topology_st, "With new config (args), check attribute uniqueness with 'cn' (MOD)")
  375. _active_container_mod(topology_st, type_config='new')
  376. def test_ticket47823_one_container_modrdn(topology_st):
  377. '''
  378. Check uniqueness in a single container
  379. Add and entry with a given 'cn', then check we can not modrdn an entry with the same 'cn' value
  380. '''
  381. _header(topology_st, "With former config (args), check attribute uniqueness with 'cn' (MODRDN)")
  382. _active_container_modrdn(topology_st, type_config='old')
  383. _header(topology_st, "With former config (args), check attribute uniqueness with 'cn' (MODRDN)")
  384. _active_container_modrdn(topology_st, type_config='new')
  385. def test_ticket47823_multi_containers_add(topology_st):
  386. '''
  387. Check uniqueness in a several containers
  388. Add and entry with a given 'cn', then check we can not add an entry with the same 'cn' value
  389. '''
  390. _header(topology_st, "With former config (args), check attribute uniqueness with 'cn' (ADD) ")
  391. _active_stage_containers_add(topology_st, type_config='old', across_subtrees=False)
  392. _header(topology_st, "With new config (args), check attribute uniqueness with 'cn' (ADD) ")
  393. _active_stage_containers_add(topology_st, type_config='new', across_subtrees=False)
  394. def test_ticket47823_multi_containers_mod(topology_st):
  395. '''
  396. Check uniqueness in a several containers
  397. Add an entry on a container with a given 'cn', then check we CAN mod an entry with the same 'cn' value on the other container
  398. '''
  399. _header(topology_st, "With former config (args), check attribute uniqueness with 'cn' (MOD) on separated container")
  400. topology_st.standalone.log.info(
  401. 'Uniqueness not enforced: if same \'cn\' modified (add/replace) on separated containers')
  402. _active_stage_containers_mod(topology_st, type_config='old', across_subtrees=False)
  403. _header(topology_st, "With new config (args), check attribute uniqueness with 'cn' (MOD) on separated container")
  404. topology_st.standalone.log.info(
  405. 'Uniqueness not enforced: if same \'cn\' modified (add/replace) on separated containers')
  406. _active_stage_containers_mod(topology_st, type_config='new', across_subtrees=False)
  407. def test_ticket47823_multi_containers_modrdn(topology_st):
  408. '''
  409. Check uniqueness in a several containers
  410. Add and entry with a given 'cn', then check we CAN modrdn an entry with the same 'cn' value on the other container
  411. '''
  412. _header(topology_st,
  413. "With former config (args), check attribute uniqueness with 'cn' (MODRDN) on separated containers")
  414. topology_st.standalone.log.info('Uniqueness not enforced: checks MODRDN entry is accepted on separated containers')
  415. _active_stage_containers_modrdn(topology_st, type_config='old', across_subtrees=False)
  416. topology_st.standalone.log.info('Uniqueness not enforced: checks MODRDN entry is accepted on separated containers')
  417. _active_stage_containers_modrdn(topology_st, type_config='old')
  418. def test_ticket47823_across_multi_containers_add(topology_st):
  419. '''
  420. Check uniqueness across several containers, uniquely with the new configuration
  421. Add and entry with a given 'cn', then check we can not add an entry with the same 'cn' value
  422. '''
  423. _header(topology_st, "With new config (args), check attribute uniqueness with 'cn' (ADD) across several containers")
  424. _active_stage_containers_add(topology_st, type_config='old', across_subtrees=True)
  425. def test_ticket47823_across_multi_containers_mod(topology_st):
  426. '''
  427. Check uniqueness across several containers, uniquely with the new configuration
  428. Add and entry with a given 'cn', then check we can not modifiy an entry with the same 'cn' value
  429. '''
  430. _header(topology_st, "With new config (args), check attribute uniqueness with 'cn' (MOD) across several containers")
  431. _active_stage_containers_mod(topology_st, type_config='old', across_subtrees=True)
  432. def test_ticket47823_across_multi_containers_modrdn(topology_st):
  433. '''
  434. Check uniqueness across several containers, uniquely with the new configuration
  435. Add and entry with a given 'cn', then check we can not modrdn an entry with the same 'cn' value
  436. '''
  437. _header(topology_st,
  438. "With new config (args), check attribute uniqueness with 'cn' (MODRDN) across several containers")
  439. _active_stage_containers_modrdn(topology_st, type_config='old', across_subtrees=True)
  440. def test_ticket47823_invalid_config_1(topology_st):
  441. '''
  442. Check that an invalid config is detected. No uniqueness enforced
  443. Using old config: arg0 is missing
  444. '''
  445. _header(topology_st, "Invalid config (old): arg0 is missing")
  446. _config_file(topology_st, action='save')
  447. # create an invalid config without arg0
  448. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='old',
  449. across_subtrees=False)
  450. del config.data['nsslapd-pluginarg0']
  451. # replace 'cn' uniqueness entry
  452. try:
  453. topology_st.standalone.delete_s(config.dn)
  454. except ldap.NO_SUCH_OBJECT:
  455. pass
  456. topology_st.standalone.add_s(config)
  457. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  458. # Check the server did not restart
  459. topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '65536')])
  460. try:
  461. topology_st.standalone.restart(timeout=5)
  462. ent = topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)",
  463. ALL_CONFIG_ATTRS)
  464. if ent:
  465. # be sure to restore a valid config before assert
  466. _config_file(topology_st, action='restore')
  467. assert not ent
  468. except subprocess.CalledProcessError:
  469. pass
  470. # Check the expected error message
  471. regex = re.compile("Unable to parse old style")
  472. res = _pattern_errorlog(topology_st.standalone.errorlog_file, regex)
  473. if not res:
  474. # be sure to restore a valid config before assert
  475. _config_file(topology_st, action='restore')
  476. assert res
  477. # Check we can restart the server
  478. _config_file(topology_st, action='restore')
  479. topology_st.standalone.start(timeout=5)
  480. try:
  481. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  482. except ldap.NO_SUCH_OBJECT:
  483. pass
  484. def test_ticket47823_invalid_config_2(topology_st):
  485. '''
  486. Check that an invalid config is detected. No uniqueness enforced
  487. Using old config: arg1 is missing
  488. '''
  489. _header(topology_st, "Invalid config (old): arg1 is missing")
  490. _config_file(topology_st, action='save')
  491. # create an invalid config without arg0
  492. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='old',
  493. across_subtrees=False)
  494. del config.data['nsslapd-pluginarg1']
  495. # replace 'cn' uniqueness entry
  496. try:
  497. topology_st.standalone.delete_s(config.dn)
  498. except ldap.NO_SUCH_OBJECT:
  499. pass
  500. topology_st.standalone.add_s(config)
  501. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  502. # Check the server did not restart
  503. try:
  504. topology_st.standalone.restart(timeout=5)
  505. ent = topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)",
  506. ALL_CONFIG_ATTRS)
  507. if ent:
  508. # be sure to restore a valid config before assert
  509. _config_file(topology_st, action='restore')
  510. assert not ent
  511. except subprocess.CalledProcessError:
  512. pass
  513. # Check the expected error message
  514. regex = re.compile("No valid subtree is defined")
  515. res = _pattern_errorlog(topology_st.standalone.errorlog_file, regex)
  516. if not res:
  517. # be sure to restore a valid config before assert
  518. _config_file(topology_st, action='restore')
  519. assert res
  520. # Check we can restart the server
  521. _config_file(topology_st, action='restore')
  522. topology_st.standalone.start(timeout=5)
  523. try:
  524. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  525. except ldap.NO_SUCH_OBJECT:
  526. pass
  527. def test_ticket47823_invalid_config_3(topology_st):
  528. '''
  529. Check that an invalid config is detected. No uniqueness enforced
  530. Using old config: arg0 is missing
  531. '''
  532. _header(topology_st, "Invalid config (old): arg0 is missing but new config attrname exists")
  533. _config_file(topology_st, action='save')
  534. # create an invalid config without arg0
  535. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='old',
  536. across_subtrees=False)
  537. del config.data['nsslapd-pluginarg0']
  538. config.data['uniqueness-attribute-name'] = 'cn'
  539. # replace 'cn' uniqueness entry
  540. try:
  541. topology_st.standalone.delete_s(config.dn)
  542. except ldap.NO_SUCH_OBJECT:
  543. pass
  544. topology_st.standalone.add_s(config)
  545. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  546. # Check the server did not restart
  547. topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '65536')])
  548. try:
  549. topology_st.standalone.restart(timeout=5)
  550. ent = topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)",
  551. ALL_CONFIG_ATTRS)
  552. if ent:
  553. # be sure to restore a valid config before assert
  554. _config_file(topology_st, action='restore')
  555. assert not ent
  556. except subprocess.CalledProcessError:
  557. pass
  558. # Check the expected error message
  559. regex = re.compile("Unable to parse old style")
  560. res = _pattern_errorlog(topology_st.standalone.errorlog_file, regex)
  561. if not res:
  562. # be sure to restore a valid config before assert
  563. _config_file(topology_st, action='restore')
  564. assert res
  565. # Check we can restart the server
  566. _config_file(topology_st, action='restore')
  567. topology_st.standalone.start(timeout=5)
  568. try:
  569. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  570. except ldap.NO_SUCH_OBJECT:
  571. pass
  572. def test_ticket47823_invalid_config_4(topology_st):
  573. '''
  574. Check that an invalid config is detected. No uniqueness enforced
  575. Using old config: arg1 is missing
  576. '''
  577. _header(topology_st, "Invalid config (old): arg1 is missing but new config exist")
  578. _config_file(topology_st, action='save')
  579. # create an invalid config without arg0
  580. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='old',
  581. across_subtrees=False)
  582. del config.data['nsslapd-pluginarg1']
  583. config.data['uniqueness-subtrees'] = ACTIVE_DN
  584. # replace 'cn' uniqueness entry
  585. try:
  586. topology_st.standalone.delete_s(config.dn)
  587. except ldap.NO_SUCH_OBJECT:
  588. pass
  589. topology_st.standalone.add_s(config)
  590. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  591. # Check the server did not restart
  592. try:
  593. topology_st.standalone.restart(timeout=5)
  594. ent = topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)",
  595. ALL_CONFIG_ATTRS)
  596. if ent:
  597. # be sure to restore a valid config before assert
  598. _config_file(topology_st, action='restore')
  599. assert not ent
  600. except subprocess.CalledProcessError:
  601. pass
  602. # Check the expected error message
  603. regex = re.compile("No valid subtree is defined")
  604. res = _pattern_errorlog(topology_st.standalone.errorlog_file, regex)
  605. if not res:
  606. # be sure to restore a valid config before assert
  607. _config_file(topology_st, action='restore')
  608. assert res
  609. # Check we can restart the server
  610. _config_file(topology_st, action='restore')
  611. topology_st.standalone.start(timeout=5)
  612. try:
  613. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  614. except ldap.NO_SUCH_OBJECT:
  615. pass
  616. def test_ticket47823_invalid_config_5(topology_st):
  617. '''
  618. Check that an invalid config is detected. No uniqueness enforced
  619. Using new config: uniqueness-attribute-name is missing
  620. '''
  621. _header(topology_st, "Invalid config (new): uniqueness-attribute-name is missing")
  622. _config_file(topology_st, action='save')
  623. # create an invalid config without arg0
  624. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='new',
  625. across_subtrees=False)
  626. del config.data['uniqueness-attribute-name']
  627. # replace 'cn' uniqueness entry
  628. try:
  629. topology_st.standalone.delete_s(config.dn)
  630. except ldap.NO_SUCH_OBJECT:
  631. pass
  632. topology_st.standalone.add_s(config)
  633. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  634. # Check the server did not restart
  635. try:
  636. topology_st.standalone.restart(timeout=5)
  637. ent = topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)",
  638. ALL_CONFIG_ATTRS)
  639. if ent:
  640. # be sure to restore a valid config before assert
  641. _config_file(topology_st, action='restore')
  642. assert not ent
  643. except subprocess.CalledProcessError:
  644. pass
  645. # Check the expected error message
  646. regex = re.compile("Attribute name not defined")
  647. res = _pattern_errorlog(topology_st.standalone.errorlog_file, regex)
  648. if not res:
  649. # be sure to restore a valid config before assert
  650. _config_file(topology_st, action='restore')
  651. assert res
  652. # Check we can restart the server
  653. _config_file(topology_st, action='restore')
  654. topology_st.standalone.start(timeout=5)
  655. try:
  656. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  657. except ldap.NO_SUCH_OBJECT:
  658. pass
  659. def test_ticket47823_invalid_config_6(topology_st):
  660. '''
  661. Check that an invalid config is detected. No uniqueness enforced
  662. Using new config: uniqueness-subtrees is missing
  663. '''
  664. _header(topology_st, "Invalid config (new): uniqueness-subtrees is missing")
  665. _config_file(topology_st, action='save')
  666. # create an invalid config without arg0
  667. config = _build_config(topology_st, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='new',
  668. across_subtrees=False)
  669. del config.data['uniqueness-subtrees']
  670. # replace 'cn' uniqueness entry
  671. try:
  672. topology_st.standalone.delete_s(config.dn)
  673. except ldap.NO_SUCH_OBJECT:
  674. pass
  675. topology_st.standalone.add_s(config)
  676. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  677. # Check the server did not restart
  678. try:
  679. topology_st.standalone.restart(timeout=5)
  680. ent = topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)",
  681. ALL_CONFIG_ATTRS)
  682. if ent:
  683. # be sure to restore a valid config before assert
  684. _config_file(topology_st, action='restore')
  685. assert not ent
  686. except subprocess.CalledProcessError:
  687. pass
  688. # Check the expected error message
  689. regex = re.compile("Objectclass for subtree entries is not defined")
  690. res = _pattern_errorlog(topology_st.standalone.errorlog_file, regex)
  691. if not res:
  692. # be sure to restore a valid config before assert
  693. _config_file(topology_st, action='restore')
  694. assert res
  695. # Check we can restart the server
  696. _config_file(topology_st, action='restore')
  697. topology_st.standalone.start(timeout=5)
  698. try:
  699. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  700. except ldap.NO_SUCH_OBJECT:
  701. pass
  702. def test_ticket47823_invalid_config_7(topology_st):
  703. '''
  704. Check that an invalid config is detected. No uniqueness enforced
  705. Using new config: uniqueness-subtrees is missing
  706. '''
  707. _header(topology_st, "Invalid config (new): uniqueness-subtrees are invalid")
  708. _config_file(topology_st, action='save')
  709. # create an invalid config without arg0
  710. config = _build_config(topology_st, attr_name='cn', subtree_1="this_is dummy DN", subtree_2="an other=dummy DN",
  711. type_config='new', across_subtrees=False)
  712. topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '65536')])
  713. # replace 'cn' uniqueness entry
  714. try:
  715. topology_st.standalone.delete_s(config.dn)
  716. except ldap.NO_SUCH_OBJECT:
  717. pass
  718. topology_st.standalone.add_s(config)
  719. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  720. # Check the server did not restart
  721. try:
  722. topology_st.standalone.restart(timeout=5)
  723. ent = topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)",
  724. ALL_CONFIG_ATTRS)
  725. if ent:
  726. # be sure to restore a valid config before assert
  727. _config_file(topology_st, action='restore')
  728. assert not ent
  729. except subprocess.CalledProcessError:
  730. pass
  731. # Check the expected error message
  732. regex = re.compile("No valid subtree is defined")
  733. res = _pattern_errorlog(topology_st.standalone.errorlog_file, regex)
  734. if not res:
  735. # be sure to restore a valid config before assert
  736. _config_file(topology_st, action='restore')
  737. assert res
  738. # Check we can restart the server
  739. _config_file(topology_st, action='restore')
  740. topology_st.standalone.start(timeout=5)
  741. try:
  742. topology_st.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  743. except ldap.NO_SUCH_OBJECT:
  744. pass
  745. if __name__ == '__main__':
  746. # Run isolated
  747. # -s for DEBUG mode
  748. CURRENT_FILE = os.path.realpath(__file__)
  749. pytest.main("-s %s" % CURRENT_FILE)