ticket47823_test.py 37 KB

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