ticket47823_test.py 37 KB

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