ticket47823_test.py 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  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. def _pattern_errorlog(file, log_pattern):
  345. try:
  346. _pattern_errorlog.last_pos += 1
  347. except AttributeError:
  348. _pattern_errorlog.last_pos = 0
  349. found = None
  350. log.debug("_pattern_errorlog: start at offset %d" % _pattern_errorlog.last_pos)
  351. file.seek(_pattern_errorlog.last_pos)
  352. # Use a while true iteration because 'for line in file: hit a
  353. # python bug that break file.tell()
  354. while True:
  355. line = file.readline()
  356. log.debug("_pattern_errorlog: [%d] %s" % (file.tell(), line))
  357. found = log_pattern.search(line)
  358. if ((line == '') or (found)):
  359. break
  360. log.debug("_pattern_errorlog: end at offset %d" % file.tell())
  361. _pattern_errorlog.last_pos = file.tell()
  362. return found
  363. def test_ticket47823_init(topology):
  364. """
  365. """
  366. # Enabled the plugins
  367. topology.standalone.plugins.enable(name=PLUGIN_ATTR_UNIQUENESS)
  368. topology.standalone.restart(timeout=120)
  369. topology.standalone.add_s(Entry((PROVISIONING_DN, {'objectclass': "top nscontainer".split(),
  370. 'cn': PROVISIONING_CN})))
  371. topology.standalone.add_s(Entry((ACTIVE_DN, {'objectclass': "top nscontainer".split(),
  372. 'cn': ACTIVE_CN})))
  373. topology.standalone.add_s(Entry((STAGE_DN, {'objectclass': "top nscontainer".split(),
  374. 'cn': STAGE_CN})))
  375. topology.standalone.add_s(Entry((DELETE_DN, {'objectclass': "top nscontainer".split(),
  376. 'cn': DELETE_CN})))
  377. topology.standalone.errorlog_file = open(topology.standalone.errlog, "r")
  378. topology.standalone.stop(timeout=120)
  379. time.sleep(1)
  380. topology.standalone.start(timeout=120)
  381. time.sleep(3)
  382. def test_ticket47823_one_container_add(topology):
  383. '''
  384. Check uniqueness in a single container
  385. Add and entry with a given 'cn', then check we can not add an entry with the same 'cn' value
  386. '''
  387. _header(topology, "With former config (args), check attribute uniqueness with 'cn' (ADD) ")
  388. _active_container_add(topology, type_config='old')
  389. _header(topology, "With new config (args), check attribute uniqueness with 'cn' (ADD) ")
  390. _active_container_add(topology, type_config='new')
  391. def test_ticket47823_one_container_mod(topology):
  392. '''
  393. Check uniqueness in a single container
  394. Add and entry with a given 'cn', then check we can not modify an entry with the same 'cn' value
  395. '''
  396. _header(topology, "With former config (args), check attribute uniqueness with 'cn' (MOD)")
  397. _active_container_mod(topology, type_config='old')
  398. _header(topology, "With new config (args), check attribute uniqueness with 'cn' (MOD)")
  399. _active_container_mod(topology, type_config='new')
  400. def test_ticket47823_one_container_modrdn(topology):
  401. '''
  402. Check uniqueness in a single container
  403. Add and entry with a given 'cn', then check we can not modrdn an entry with the same 'cn' value
  404. '''
  405. _header(topology, "With former config (args), check attribute uniqueness with 'cn' (MODRDN)")
  406. _active_container_modrdn(topology, type_config='old')
  407. _header(topology, "With former config (args), check attribute uniqueness with 'cn' (MODRDN)")
  408. _active_container_modrdn(topology, type_config='new')
  409. def test_ticket47823_multi_containers_add(topology):
  410. '''
  411. Check uniqueness in a several containers
  412. Add and entry with a given 'cn', then check we can not add an entry with the same 'cn' value
  413. '''
  414. _header(topology, "With former config (args), check attribute uniqueness with 'cn' (ADD) ")
  415. _active_stage_containers_add(topology, type_config='old', across_subtrees=False)
  416. _header(topology, "With new config (args), check attribute uniqueness with 'cn' (ADD) ")
  417. _active_stage_containers_add(topology, type_config='new', across_subtrees=False)
  418. def test_ticket47823_multi_containers_mod(topology):
  419. '''
  420. Check uniqueness in a several containers
  421. 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
  422. '''
  423. _header(topology, "With former 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='old', across_subtrees=False)
  426. _header(topology, "With new config (args), check attribute uniqueness with 'cn' (MOD) on separated container")
  427. topology.standalone.log.info('Uniqueness not enforced: if same \'cn\' modified (add/replace) on separated containers')
  428. _active_stage_containers_mod(topology, type_config='new', across_subtrees=False)
  429. def test_ticket47823_multi_containers_modrdn(topology):
  430. '''
  431. Check uniqueness in a several containers
  432. Add and entry with a given 'cn', then check we CAN modrdn an entry with the same 'cn' value on the other container
  433. '''
  434. _header(topology, "With former config (args), check attribute uniqueness with 'cn' (MODRDN) on separated containers")
  435. topology.standalone.log.info('Uniqueness not enforced: checks MODRDN entry is accepted on separated containers')
  436. _active_stage_containers_modrdn(topology, type_config='old', across_subtrees=False)
  437. topology.standalone.log.info('Uniqueness not enforced: checks MODRDN entry is accepted on separated containers')
  438. _active_stage_containers_modrdn(topology, type_config='old')
  439. def test_ticket47823_across_multi_containers_add(topology):
  440. '''
  441. Check uniqueness across several containers, uniquely with the new configuration
  442. Add and entry with a given 'cn', then check we can not add an entry with the same 'cn' value
  443. '''
  444. _header(topology, "With new config (args), check attribute uniqueness with 'cn' (ADD) across several containers")
  445. _active_stage_containers_add(topology, type_config='old', across_subtrees=True)
  446. def test_ticket47823_across_multi_containers_mod(topology):
  447. '''
  448. Check uniqueness across several containers, uniquely with the new configuration
  449. Add and entry with a given 'cn', then check we can not modifiy an entry with the same 'cn' value
  450. '''
  451. _header(topology, "With new config (args), check attribute uniqueness with 'cn' (MOD) across several containers")
  452. _active_stage_containers_mod(topology, type_config='old', across_subtrees=True)
  453. def test_ticket47823_across_multi_containers_modrdn(topology):
  454. '''
  455. Check uniqueness across several containers, uniquely with the new configuration
  456. Add and entry with a given 'cn', then check we can not modrdn an entry with the same 'cn' value
  457. '''
  458. _header(topology, "With new config (args), check attribute uniqueness with 'cn' (MODRDN) across several containers")
  459. _active_stage_containers_modrdn(topology, type_config='old', across_subtrees=True)
  460. def test_ticket47823_invalid_config_1(topology):
  461. '''
  462. Check that an invalid config is detected. No uniqueness enforced
  463. Using old config: arg0 is missing
  464. '''
  465. _header(topology, "Invalid config (old): arg0 is missing")
  466. _config_file(topology, action='save')
  467. # create an invalid config without arg0
  468. config = _build_config(topology, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='old', across_subtrees=False)
  469. del config.data['nsslapd-pluginarg0']
  470. # replace 'cn' uniqueness entry
  471. try:
  472. topology.standalone.delete_s(config.dn)
  473. except ldap.NO_SUCH_OBJECT:
  474. pass
  475. topology.standalone.add_s(config)
  476. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  477. # Check the server did not restart
  478. topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '65536')])
  479. try:
  480. topology.standalone.restart(timeout=5)
  481. ent = topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  482. if ent:
  483. # be sure to restore a valid config before assert
  484. _config_file(topology, action='restore')
  485. assert not ent
  486. except ldap.SERVER_DOWN:
  487. pass
  488. # Check the expected error message
  489. regex = re.compile("Config fail: unable to parse old style")
  490. res = _pattern_errorlog(topology.standalone.errorlog_file, regex)
  491. if not res:
  492. # be sure to restore a valid config before assert
  493. _config_file(topology, action='restore')
  494. assert res
  495. # Check we can restart the server
  496. _config_file(topology, action='restore')
  497. topology.standalone.start(timeout=5)
  498. try:
  499. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  500. except ldap.NO_SUCH_OBJECT:
  501. pass
  502. def test_ticket47823_invalid_config_2(topology):
  503. '''
  504. Check that an invalid config is detected. No uniqueness enforced
  505. Using old config: arg1 is missing
  506. '''
  507. _header(topology, "Invalid config (old): arg1 is missing")
  508. _config_file(topology, action='save')
  509. # create an invalid config without arg0
  510. config = _build_config(topology, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='old', across_subtrees=False)
  511. del config.data['nsslapd-pluginarg1']
  512. # replace 'cn' uniqueness entry
  513. try:
  514. topology.standalone.delete_s(config.dn)
  515. except ldap.NO_SUCH_OBJECT:
  516. pass
  517. topology.standalone.add_s(config)
  518. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  519. # Check the server did not restart
  520. try:
  521. topology.standalone.restart(timeout=5)
  522. ent = topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  523. if ent:
  524. # be sure to restore a valid config before assert
  525. _config_file(topology, action='restore')
  526. assert not ent
  527. except ldap.SERVER_DOWN:
  528. pass
  529. # Check the expected error message
  530. regex = re.compile("Config info: No valid subtree is defined")
  531. res = _pattern_errorlog(topology.standalone.errorlog_file, regex)
  532. if not res:
  533. # be sure to restore a valid config before assert
  534. _config_file(topology, action='restore')
  535. assert res
  536. # Check we can restart the server
  537. _config_file(topology, action='restore')
  538. topology.standalone.start(timeout=5)
  539. try:
  540. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  541. except ldap.NO_SUCH_OBJECT:
  542. pass
  543. def test_ticket47823_invalid_config_3(topology):
  544. '''
  545. Check that an invalid config is detected. No uniqueness enforced
  546. Using old config: arg0 is missing
  547. '''
  548. _header(topology, "Invalid config (old): arg0 is missing but new config attrname exists")
  549. _config_file(topology, action='save')
  550. # create an invalid config without arg0
  551. config = _build_config(topology, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='old', across_subtrees=False)
  552. del config.data['nsslapd-pluginarg0']
  553. config.data['uniqueness-attribute-name'] = 'cn'
  554. # replace 'cn' uniqueness entry
  555. try:
  556. topology.standalone.delete_s(config.dn)
  557. except ldap.NO_SUCH_OBJECT:
  558. pass
  559. topology.standalone.add_s(config)
  560. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  561. # Check the server did not restart
  562. topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '65536')])
  563. try:
  564. topology.standalone.restart(timeout=5)
  565. ent = topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  566. if ent:
  567. # be sure to restore a valid config before assert
  568. _config_file(topology, action='restore')
  569. assert not ent
  570. except ldap.SERVER_DOWN:
  571. pass
  572. # Check the expected error message
  573. regex = re.compile("Config fail: unable to parse old style")
  574. res = _pattern_errorlog(topology.standalone.errorlog_file, regex)
  575. if not res:
  576. # be sure to restore a valid config before assert
  577. _config_file(topology, action='restore')
  578. assert res
  579. # Check we can restart the server
  580. _config_file(topology, action='restore')
  581. topology.standalone.start(timeout=5)
  582. try:
  583. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  584. except ldap.NO_SUCH_OBJECT:
  585. pass
  586. def test_ticket47823_invalid_config_4(topology):
  587. '''
  588. Check that an invalid config is detected. No uniqueness enforced
  589. Using old config: arg1 is missing
  590. '''
  591. _header(topology, "Invalid config (old): arg1 is missing but new config exist")
  592. _config_file(topology, action='save')
  593. # create an invalid config without arg0
  594. config = _build_config(topology, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='old', across_subtrees=False)
  595. del config.data['nsslapd-pluginarg1']
  596. config.data['uniqueness-subtrees'] = ACTIVE_DN
  597. # replace 'cn' uniqueness entry
  598. try:
  599. topology.standalone.delete_s(config.dn)
  600. except ldap.NO_SUCH_OBJECT:
  601. pass
  602. topology.standalone.add_s(config)
  603. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  604. # Check the server did not restart
  605. try:
  606. topology.standalone.restart(timeout=5)
  607. ent = topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  608. if ent:
  609. # be sure to restore a valid config before assert
  610. _config_file(topology, action='restore')
  611. assert not ent
  612. except ldap.SERVER_DOWN:
  613. pass
  614. # Check the expected error message
  615. regex = re.compile("Config info: No valid subtree is defined")
  616. res = _pattern_errorlog(topology.standalone.errorlog_file, regex)
  617. if not res:
  618. # be sure to restore a valid config before assert
  619. _config_file(topology, action='restore')
  620. assert res
  621. # Check we can restart the server
  622. _config_file(topology, action='restore')
  623. topology.standalone.start(timeout=5)
  624. try:
  625. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  626. except ldap.NO_SUCH_OBJECT:
  627. pass
  628. def test_ticket47823_invalid_config_5(topology):
  629. '''
  630. Check that an invalid config is detected. No uniqueness enforced
  631. Using new config: uniqueness-attribute-name is missing
  632. '''
  633. _header(topology, "Invalid config (new): uniqueness-attribute-name is missing")
  634. _config_file(topology, action='save')
  635. # create an invalid config without arg0
  636. config = _build_config(topology, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='new', across_subtrees=False)
  637. del config.data['uniqueness-attribute-name']
  638. # replace 'cn' uniqueness entry
  639. try:
  640. topology.standalone.delete_s(config.dn)
  641. except ldap.NO_SUCH_OBJECT:
  642. pass
  643. topology.standalone.add_s(config)
  644. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  645. # Check the server did not restart
  646. try:
  647. topology.standalone.restart(timeout=5)
  648. ent = topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  649. if ent:
  650. # be sure to restore a valid config before assert
  651. _config_file(topology, action='restore')
  652. assert not ent
  653. except ldap.SERVER_DOWN:
  654. pass
  655. # Check the expected error message
  656. regex = re.compile("Config info: attribute name not defined")
  657. res = _pattern_errorlog(topology.standalone.errorlog_file, regex)
  658. if not res:
  659. # be sure to restore a valid config before assert
  660. _config_file(topology, action='restore')
  661. assert res
  662. # Check we can restart the server
  663. _config_file(topology, action='restore')
  664. topology.standalone.start(timeout=5)
  665. try:
  666. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  667. except ldap.NO_SUCH_OBJECT:
  668. pass
  669. def test_ticket47823_invalid_config_6(topology):
  670. '''
  671. Check that an invalid config is detected. No uniqueness enforced
  672. Using new config: uniqueness-subtrees is missing
  673. '''
  674. _header(topology, "Invalid config (new): uniqueness-subtrees is missing")
  675. _config_file(topology, action='save')
  676. # create an invalid config without arg0
  677. config = _build_config(topology, attr_name='cn', subtree_1=ACTIVE_DN, subtree_2=None, type_config='new', across_subtrees=False)
  678. del config.data['uniqueness-subtrees']
  679. # replace 'cn' uniqueness entry
  680. try:
  681. topology.standalone.delete_s(config.dn)
  682. except ldap.NO_SUCH_OBJECT:
  683. pass
  684. topology.standalone.add_s(config)
  685. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  686. # Check the server did not restart
  687. try:
  688. topology.standalone.restart(timeout=5)
  689. ent = topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  690. if ent:
  691. # be sure to restore a valid config before assert
  692. _config_file(topology, action='restore')
  693. assert not ent
  694. except ldap.SERVER_DOWN:
  695. pass
  696. # Check the expected error message
  697. regex = re.compile("Config info: objectclass for subtree entries is not defined")
  698. res = _pattern_errorlog(topology.standalone.errorlog_file, regex)
  699. if not res:
  700. # be sure to restore a valid config before assert
  701. _config_file(topology, action='restore')
  702. assert res
  703. # Check we can restart the server
  704. _config_file(topology, action='restore')
  705. topology.standalone.start(timeout=5)
  706. try:
  707. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  708. except ldap.NO_SUCH_OBJECT:
  709. pass
  710. def test_ticket47823_invalid_config_7(topology):
  711. '''
  712. Check that an invalid config is detected. No uniqueness enforced
  713. Using new config: uniqueness-subtrees is missing
  714. '''
  715. _header(topology, "Invalid config (new): uniqueness-subtrees are invalid")
  716. _config_file(topology, action='save')
  717. # create an invalid config without arg0
  718. 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)
  719. topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '65536')])
  720. # replace 'cn' uniqueness entry
  721. try:
  722. topology.standalone.delete_s(config.dn)
  723. except ldap.NO_SUCH_OBJECT:
  724. pass
  725. topology.standalone.add_s(config)
  726. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  727. # Check the server did not restart
  728. try:
  729. topology.standalone.restart(timeout=5)
  730. ent = topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  731. if ent:
  732. # be sure to restore a valid config before assert
  733. _config_file(topology, action='restore')
  734. assert not ent
  735. except ldap.SERVER_DOWN:
  736. pass
  737. # Check the expected error message
  738. regex = re.compile("Config info: No valid subtree is defined")
  739. res = _pattern_errorlog(topology.standalone.errorlog_file, regex)
  740. if not res:
  741. # be sure to restore a valid config before assert
  742. _config_file(topology, action='restore')
  743. assert res
  744. # Check we can restart the server
  745. _config_file(topology, action='restore')
  746. topology.standalone.start(timeout=5)
  747. try:
  748. topology.standalone.getEntry(config.dn, ldap.SCOPE_BASE, "(objectclass=nsSlapdPlugin)", ALL_CONFIG_ATTRS)
  749. except ldap.NO_SUCH_OBJECT:
  750. pass
  751. if __name__ == '__main__':
  752. # Run isolated
  753. # -s for DEBUG mode
  754. CURRENT_FILE = os.path.realpath(__file__)
  755. pytest.main("-s %s" % CURRENT_FILE)