ticket47553_single_aci_test.py 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
  1. '''
  2. Created on Nov 7, 2013
  3. @author: tbordaz
  4. '''
  5. import os
  6. import sys
  7. import time
  8. import ldap
  9. import logging
  10. import socket
  11. import time
  12. import logging
  13. import pytest
  14. import re
  15. from lib389 import DirSrv, Entry, tools
  16. from lib389.tools import DirSrvTools
  17. from lib389._constants import *
  18. from lib389.properties import *
  19. from constants import *
  20. from lib389._constants import REPLICAROLE_MASTER
  21. logging.getLogger(__name__).setLevel(logging.DEBUG)
  22. log = logging.getLogger(__name__)
  23. #
  24. # important part. We can deploy Master1 and Master2 on different versions
  25. #
  26. installation1_prefix = None
  27. installation2_prefix = None
  28. TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
  29. STAGING_CN = "staged user"
  30. PRODUCTION_CN = "accounts"
  31. EXCEPT_CN = "excepts"
  32. STAGING_DN = "cn=%s,%s" % (STAGING_CN, SUFFIX)
  33. PRODUCTION_DN = "cn=%s,%s" % (PRODUCTION_CN, SUFFIX)
  34. PROD_EXCEPT_DN = "cn=%s,%s" % (EXCEPT_CN, PRODUCTION_DN)
  35. STAGING_PATTERN = "cn=%s*,%s" % (STAGING_CN[:2], SUFFIX)
  36. PRODUCTION_PATTERN = "cn=%s*,%s" % (PRODUCTION_CN[:2], SUFFIX)
  37. BAD_STAGING_PATTERN = "cn=bad*,%s" % (SUFFIX)
  38. BAD_PRODUCTION_PATTERN = "cn=bad*,%s" % (SUFFIX)
  39. BIND_CN = "bind_entry"
  40. BIND_DN = "cn=%s,%s" % (BIND_CN, SUFFIX)
  41. BIND_PW = "password"
  42. NEW_ACCOUNT = "new_account"
  43. MAX_ACCOUNTS = 20
  44. CONFIG_MODDN_ACI_ATTR = "nsslapd-moddn-aci"
  45. class TopologyMaster1Master2(object):
  46. def __init__(self, master1, master2):
  47. master1.open()
  48. self.master1 = master1
  49. master2.open()
  50. self.master2 = master2
  51. @pytest.fixture(scope="module")
  52. def topology(request):
  53. '''
  54. This fixture is used to create a replicated topology for the 'module'.
  55. The replicated topology is MASTER1 <-> Master2.
  56. At the beginning, It may exists a master2 instance and/or a master2 instance.
  57. It may also exists a backup for the master1 and/or the master2.
  58. Principle:
  59. If master1 instance exists:
  60. restart it
  61. If master2 instance exists:
  62. restart it
  63. If backup of master1 AND backup of master2 exists:
  64. create or rebind to master1
  65. create or rebind to master2
  66. restore master1 from backup
  67. restore master2 from backup
  68. else:
  69. Cleanup everything
  70. remove instances
  71. remove backups
  72. Create instances
  73. Initialize replication
  74. Create backups
  75. '''
  76. global installation1_prefix
  77. global installation2_prefix
  78. # allocate master1 on a given deployement
  79. master1 = DirSrv(verbose=False)
  80. if installation1_prefix:
  81. args_instance[SER_DEPLOYED_DIR] = installation1_prefix
  82. # Args for the master1 instance
  83. args_instance[SER_HOST] = HOST_MASTER_1
  84. args_instance[SER_PORT] = PORT_MASTER_1
  85. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  86. args_master = args_instance.copy()
  87. master1.allocate(args_master)
  88. # allocate master1 on a given deployement
  89. master2 = DirSrv(verbose=False)
  90. if installation2_prefix:
  91. args_instance[SER_DEPLOYED_DIR] = installation2_prefix
  92. # Args for the consumer instance
  93. args_instance[SER_HOST] = HOST_MASTER_2
  94. args_instance[SER_PORT] = PORT_MASTER_2
  95. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
  96. args_master = args_instance.copy()
  97. master2.allocate(args_master)
  98. # Get the status of the backups
  99. backup_master1 = master1.checkBackupFS()
  100. backup_master2 = master2.checkBackupFS()
  101. # Get the status of the instance and restart it if it exists
  102. instance_master1 = master1.exists()
  103. if instance_master1:
  104. master1.stop(timeout=10)
  105. master1.start(timeout=10)
  106. instance_master2 = master2.exists()
  107. if instance_master2:
  108. master2.stop(timeout=10)
  109. master2.start(timeout=10)
  110. if backup_master1 and backup_master2:
  111. # The backups exist, assuming they are correct
  112. # we just re-init the instances with them
  113. if not instance_master1:
  114. master1.create()
  115. # Used to retrieve configuration information (dbdir, confdir...)
  116. master1.open()
  117. if not instance_master2:
  118. master2.create()
  119. # Used to retrieve configuration information (dbdir, confdir...)
  120. master2.open()
  121. # restore master1 from backup
  122. master1.stop(timeout=10)
  123. master1.restoreFS(backup_master1)
  124. master1.start(timeout=10)
  125. # restore master2 from backup
  126. master2.stop(timeout=10)
  127. master2.restoreFS(backup_master2)
  128. master2.start(timeout=10)
  129. else:
  130. # We should be here only in two conditions
  131. # - This is the first time a test involve master-consumer
  132. # so we need to create everything
  133. # - Something weird happened (instance/backup destroyed)
  134. # so we discard everything and recreate all
  135. # Remove all the backups. So even if we have a specific backup file
  136. # (e.g backup_master) we clear all backups that an instance my have created
  137. if backup_master1:
  138. master1.clearBackupFS()
  139. if backup_master2:
  140. master2.clearBackupFS()
  141. # Remove all the instances
  142. if instance_master1:
  143. master1.delete()
  144. if instance_master2:
  145. master2.delete()
  146. # Create the instances
  147. master1.create()
  148. master1.open()
  149. master2.create()
  150. master2.open()
  151. #
  152. # Now prepare the Master-Consumer topology
  153. #
  154. # First Enable replication
  155. master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  156. master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
  157. # Initialize the supplier->consumer
  158. properties = {RA_NAME: r'meTo_$host:$port',
  159. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  160. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  161. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  162. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  163. repl_agreement = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
  164. if not repl_agreement:
  165. log.fatal("Fail to create a replica agreement")
  166. sys.exit(1)
  167. log.debug("%s created" % repl_agreement)
  168. properties = {RA_NAME: r'meTo_$host:$port',
  169. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  170. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  171. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  172. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  173. master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
  174. master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
  175. master1.waitForReplInit(repl_agreement)
  176. # Check replication is working fine
  177. master1.add_s(Entry((TEST_REPL_DN, {
  178. 'objectclass': "top person".split(),
  179. 'sn': 'test_repl',
  180. 'cn': 'test_repl'})))
  181. loop = 0
  182. while loop <= 10:
  183. try:
  184. ent = master2.getEntry(TEST_REPL_DN, ldap.SCOPE_BASE, "(objectclass=*)")
  185. break
  186. except ldap.NO_SUCH_OBJECT:
  187. time.sleep(1)
  188. loop += 1
  189. # Time to create the backups
  190. master1.stop(timeout=10)
  191. master1.backupfile = master1.backupFS()
  192. master1.start(timeout=10)
  193. master2.stop(timeout=10)
  194. master2.backupfile = master2.backupFS()
  195. master2.start(timeout=10)
  196. # clear the tmp directory
  197. master1.clearTmpDir(__file__)
  198. #
  199. # Here we have two instances master and consumer
  200. # with replication working. Either coming from a backup recovery
  201. # or from a fresh (re)init
  202. # Time to return the topology
  203. return TopologyMaster1Master2(master1, master2)
  204. def _bind_manager(topology):
  205. topology.master1.log.info("Bind as %s " % DN_DM)
  206. topology.master1.simple_bind_s(DN_DM, PASSWORD)
  207. def _bind_normal(topology):
  208. # bind as bind_entry
  209. topology.master1.log.info("Bind as %s" % BIND_DN)
  210. topology.master1.simple_bind_s(BIND_DN, BIND_PW)
  211. def _moddn_aci_deny_tree(topology, mod_type=None, target_from=STAGING_DN, target_to=PROD_EXCEPT_DN):
  212. '''
  213. It denies the access moddn_to in cn=except,cn=accounts,SUFFIX
  214. '''
  215. assert mod_type != None
  216. ACI_TARGET_FROM = ""
  217. ACI_TARGET_TO = ""
  218. if target_from:
  219. ACI_TARGET_FROM = "(target_from = \"ldap:///%s\")" % (target_from)
  220. if target_to:
  221. ACI_TARGET_TO = "(target_to = \"ldap:///%s\")" % (target_to)
  222. ACI_ALLOW = "(version 3.0; acl \"Deny MODDN to prod_except\"; deny (moddn)"
  223. ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % BIND_DN
  224. ACI_BODY = ACI_TARGET_TO + ACI_TARGET_FROM + ACI_ALLOW + ACI_SUBJECT
  225. mod = [(mod_type, 'aci', ACI_BODY)]
  226. #topology.master1.modify_s(SUFFIX, mod)
  227. topology.master1.log.info("Add a DENY aci under %s " % PROD_EXCEPT_DN)
  228. topology.master1.modify_s(PROD_EXCEPT_DN, mod)
  229. def _moddn_aci_staging_to_production(topology, mod_type=None, target_from=STAGING_DN, target_to=PRODUCTION_DN):
  230. assert mod_type != None
  231. ACI_TARGET_FROM = ""
  232. ACI_TARGET_TO = ""
  233. if target_from:
  234. ACI_TARGET_FROM = "(target_from = \"ldap:///%s\")" % (target_from)
  235. if target_to:
  236. ACI_TARGET_TO = "(target_to = \"ldap:///%s\")" % (target_to)
  237. ACI_ALLOW = "(version 3.0; acl \"MODDN from staging to production\"; allow (moddn)"
  238. ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % BIND_DN
  239. ACI_BODY = ACI_TARGET_FROM + ACI_TARGET_TO + ACI_ALLOW + ACI_SUBJECT
  240. mod = [(mod_type, 'aci', ACI_BODY)]
  241. topology.master1.modify_s(SUFFIX, mod)
  242. def _moddn_aci_from_production_to_staging(topology, mod_type=None):
  243. assert mod_type != None
  244. ACI_TARGET = "(target_from = \"ldap:///%s\") (target_to = \"ldap:///%s\")" % (PRODUCTION_DN, STAGING_DN)
  245. ACI_ALLOW = "(version 3.0; acl \"MODDN from production to staging\"; allow (moddn)"
  246. ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % BIND_DN
  247. ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
  248. mod = [(mod_type, 'aci', ACI_BODY)]
  249. topology.master1.modify_s(SUFFIX, mod)
  250. def test_ticket47553_init(topology):
  251. """
  252. Creates
  253. - a staging DIT
  254. - a production DIT
  255. - add accounts in staging DIT
  256. - enable ACL logging (commented for performance reason)
  257. """
  258. topology.master1.log.info("\n\n######################### INITIALIZATION ######################\n")
  259. # entry used to bind with
  260. topology.master1.log.info("Add %s" % BIND_DN)
  261. topology.master1.add_s(Entry((BIND_DN, {
  262. 'objectclass': "top person".split(),
  263. 'sn': BIND_CN,
  264. 'cn': BIND_CN,
  265. 'userpassword': BIND_PW})))
  266. # DIT for staging
  267. topology.master1.log.info("Add %s" % STAGING_DN)
  268. topology.master1.add_s(Entry((STAGING_DN, {
  269. 'objectclass': "top organizationalRole".split(),
  270. 'cn': STAGING_CN,
  271. 'description': "staging DIT"})))
  272. # DIT for production
  273. topology.master1.log.info("Add %s" % PRODUCTION_DN)
  274. topology.master1.add_s(Entry((PRODUCTION_DN, {
  275. 'objectclass': "top organizationalRole".split(),
  276. 'cn': PRODUCTION_CN,
  277. 'description': "production DIT"})))
  278. # DIT for production/except
  279. topology.master1.log.info("Add %s" % PROD_EXCEPT_DN)
  280. topology.master1.add_s(Entry((PROD_EXCEPT_DN, {
  281. 'objectclass': "top organizationalRole".split(),
  282. 'cn': EXCEPT_CN,
  283. 'description': "production except DIT"})))
  284. # enable acl error logging
  285. #mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '128')]
  286. #topology.master1.modify_s(DN_CONFIG, mod)
  287. #topology.master2.modify_s(DN_CONFIG, mod)
  288. # add dummy entries in the staging DIT
  289. for cpt in range(MAX_ACCOUNTS):
  290. name = "%s%d" % (NEW_ACCOUNT, cpt)
  291. topology.master1.add_s(Entry(("cn=%s,%s" % (name, STAGING_DN), {
  292. 'objectclass': "top person".split(),
  293. 'sn': name,
  294. 'cn': name})))
  295. def test_ticket47553_add(topology):
  296. '''
  297. This test case checks that the ADD operation fails (no ADD aci on production)
  298. '''
  299. topology.master1.log.info("\n\n######################### ADD (should fail) ######################\n")
  300. _bind_normal(topology)
  301. #
  302. # First try to add an entry in production => INSUFFICIENT_ACCESS
  303. #
  304. try:
  305. topology.master1.log.info("Try to add %s" % PRODUCTION_DN)
  306. name = "%s%d" % (NEW_ACCOUNT, 0)
  307. topology.master1.add_s(Entry(("cn=%s,%s" % (name, PRODUCTION_DN), {
  308. 'objectclass': "top person".split(),
  309. 'sn': name,
  310. 'cn': name})))
  311. assert 0 # this is an error, we should not be allowed to add an entry in production
  312. except Exception as e:
  313. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  314. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  315. def test_ticket47553_delete(topology):
  316. '''
  317. This test case checks that the DEL operation fails (no 'delete' aci on production)
  318. '''
  319. topology.master1.log.info("\n\n######################### DELETE (should fail) ######################\n")
  320. _bind_normal(topology)
  321. #
  322. # Second try to delete an entry in staging => INSUFFICIENT_ACCESS
  323. #
  324. try:
  325. topology.master1.log.info("Try to delete %s" % STAGING_DN)
  326. name = "%s%d" % (NEW_ACCOUNT, 0)
  327. topology.master1.delete_s("cn=%s,%s" % (name, STAGING_DN))
  328. assert 0 # this is an error, we should not be allowed to add an entry in production
  329. except Exception as e:
  330. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  331. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  332. def test_ticket47553_moddn_staging_prod_0(topology):
  333. '''
  334. This test case MOVE entry NEW_ACCOUNT0 from staging to prod
  335. target_to/target_from: equality filter
  336. '''
  337. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (0) ######################\n")
  338. _bind_normal(topology)
  339. old_rdn = "cn=%s0" % NEW_ACCOUNT
  340. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  341. new_rdn = old_rdn
  342. new_superior = PRODUCTION_DN
  343. #
  344. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  345. #
  346. try:
  347. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  348. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  349. assert 0
  350. except AssertionError:
  351. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  352. except Exception as e:
  353. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  354. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  355. # successfull MOD with the ACI
  356. topology.master1.log.info("\n\n######################### MOVE to and from equality filter ######################\n")
  357. _bind_manager(topology)
  358. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  359. _bind_normal(topology)
  360. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  361. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  362. # successfull MOD with the both ACI
  363. _bind_manager(topology)
  364. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  365. _bind_normal(topology)
  366. def test_ticket47553_moddn_staging_prod_1(topology):
  367. '''
  368. This test case MOVE entry NEW_ACCOUNT1 from staging to prod
  369. target_to/target_from: substring/equality filter
  370. '''
  371. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (1) ######################\n")
  372. _bind_normal(topology)
  373. old_rdn = "cn=%s1" % NEW_ACCOUNT
  374. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  375. new_rdn = old_rdn
  376. new_superior = PRODUCTION_DN
  377. #
  378. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  379. #
  380. try:
  381. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  382. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  383. assert 0
  384. except AssertionError:
  385. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  386. except Exception as e:
  387. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  388. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  389. # successfull MOD with the ACI
  390. topology.master1.log.info("\n\n######################### MOVE to substring/ from equality filter ######################\n")
  391. _bind_manager(topology)
  392. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_DN, target_to=PRODUCTION_PATTERN)
  393. _bind_normal(topology)
  394. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  395. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  396. # successfull MOD with the both ACI
  397. _bind_manager(topology)
  398. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=PRODUCTION_PATTERN)
  399. _bind_normal(topology)
  400. def test_ticket47553_moddn_staging_prod_2(topology):
  401. '''
  402. This test case fails to MOVE entry NEW_ACCOUNT2 from staging to prod
  403. because of bad pattern
  404. '''
  405. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (2) ######################\n")
  406. _bind_normal(topology)
  407. old_rdn = "cn=%s2" % NEW_ACCOUNT
  408. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  409. new_rdn = old_rdn
  410. new_superior = PRODUCTION_DN
  411. #
  412. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  413. #
  414. try:
  415. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  416. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  417. assert 0
  418. except AssertionError:
  419. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  420. except Exception as e:
  421. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  422. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  423. # successfull MOD with the ACI
  424. topology.master1.log.info("\n\n######################### MOVE to substring (BAD)/ from equality filter ######################\n")
  425. _bind_manager(topology)
  426. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_DN, target_to=BAD_PRODUCTION_PATTERN)
  427. _bind_normal(topology)
  428. try:
  429. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  430. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  431. except AssertionError:
  432. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  433. except Exception as e:
  434. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  435. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  436. # successfull MOD with the both ACI
  437. _bind_manager(topology)
  438. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=BAD_PRODUCTION_PATTERN)
  439. _bind_normal(topology)
  440. def test_ticket47553_moddn_staging_prod_3(topology):
  441. '''
  442. This test case MOVE entry NEW_ACCOUNT3 from staging to prod
  443. target_to/target_from: equality/substring filter
  444. '''
  445. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (3) ######################\n")
  446. _bind_normal(topology)
  447. old_rdn = "cn=%s3" % NEW_ACCOUNT
  448. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  449. new_rdn = old_rdn
  450. new_superior = PRODUCTION_DN
  451. #
  452. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  453. #
  454. try:
  455. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  456. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  457. assert 0
  458. except AssertionError:
  459. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  460. except Exception as e:
  461. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  462. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  463. # successfull MOD with the ACI
  464. topology.master1.log.info("\n\n######################### MOVE to:equality filter / from substring filter ######################\n")
  465. _bind_manager(topology)
  466. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_PATTERN, target_to=PRODUCTION_DN)
  467. _bind_normal(topology)
  468. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  469. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  470. # successfull MOD with the both ACI
  471. _bind_manager(topology)
  472. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_PATTERN, target_to=PRODUCTION_DN)
  473. _bind_normal(topology)
  474. def test_ticket47553_moddn_staging_prod_4(topology):
  475. '''
  476. This test case fails to MOVE entry NEW_ACCOUNT4 from staging to prod
  477. because of bad pattern
  478. '''
  479. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (4) ######################\n")
  480. _bind_normal(topology)
  481. old_rdn = "cn=%s4" % NEW_ACCOUNT
  482. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  483. new_rdn = old_rdn
  484. new_superior = PRODUCTION_DN
  485. #
  486. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  487. #
  488. try:
  489. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  490. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  491. assert 0
  492. except AssertionError:
  493. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  494. except Exception as e:
  495. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  496. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  497. # successfull MOD with the ACI
  498. topology.master1.log.info("\n\n######################### MOVE to: equality filter/ from: substring (BAD) ######################\n")
  499. _bind_manager(topology)
  500. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=BAD_STAGING_PATTERN, target_to=PRODUCTION_DN)
  501. _bind_normal(topology)
  502. try:
  503. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  504. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  505. except AssertionError:
  506. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  507. except Exception as e:
  508. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  509. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  510. # successfull MOD with the both ACI
  511. _bind_manager(topology)
  512. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=BAD_STAGING_PATTERN, target_to=PRODUCTION_DN)
  513. _bind_normal(topology)
  514. def test_ticket47553_moddn_staging_prod_5(topology):
  515. '''
  516. This test case MOVE entry NEW_ACCOUNT5 from staging to prod
  517. target_to/target_from: substring/substring filter
  518. '''
  519. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (5) ######################\n")
  520. _bind_normal(topology)
  521. old_rdn = "cn=%s5" % NEW_ACCOUNT
  522. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  523. new_rdn = old_rdn
  524. new_superior = PRODUCTION_DN
  525. #
  526. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  527. #
  528. try:
  529. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  530. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  531. assert 0
  532. except AssertionError:
  533. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  534. except Exception as e:
  535. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  536. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  537. # successfull MOD with the ACI
  538. topology.master1.log.info("\n\n######################### MOVE to:substring filter / from: substring filter ######################\n")
  539. _bind_manager(topology)
  540. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_PATTERN, target_to=PRODUCTION_PATTERN)
  541. _bind_normal(topology)
  542. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  543. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  544. # successfull MOD with the both ACI
  545. _bind_manager(topology)
  546. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_PATTERN, target_to=PRODUCTION_PATTERN)
  547. _bind_normal(topology)
  548. def test_ticket47553_moddn_staging_prod_6(topology):
  549. '''
  550. This test case MOVE entry NEW_ACCOUNT6 from staging to prod
  551. target_to/target_from: substring/<enmpty> filter
  552. '''
  553. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (6) ######################\n")
  554. _bind_normal(topology)
  555. old_rdn = "cn=%s6" % NEW_ACCOUNT
  556. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  557. new_rdn = old_rdn
  558. new_superior = PRODUCTION_DN
  559. #
  560. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  561. #
  562. try:
  563. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  564. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  565. assert 0
  566. except AssertionError:
  567. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  568. except Exception as e:
  569. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  570. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  571. # successfull MOD with the ACI
  572. topology.master1.log.info("\n\n######################### MOVE to:substring filter / from: empty ######################\n")
  573. _bind_manager(topology)
  574. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=None, target_to=PRODUCTION_PATTERN)
  575. _bind_normal(topology)
  576. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  577. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  578. # successfull MOD with the both ACI
  579. _bind_manager(topology)
  580. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=None, target_to=PRODUCTION_PATTERN)
  581. _bind_normal(topology)
  582. def test_ticket47553_moddn_staging_prod_7(topology):
  583. '''
  584. This test case MOVE entry NEW_ACCOUNT7 from staging to prod
  585. target_to/target_from: <empty>/substring filter
  586. '''
  587. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (7) ######################\n")
  588. _bind_normal(topology)
  589. old_rdn = "cn=%s7" % NEW_ACCOUNT
  590. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  591. new_rdn = old_rdn
  592. new_superior = PRODUCTION_DN
  593. #
  594. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  595. #
  596. try:
  597. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  598. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  599. assert 0
  600. except AssertionError:
  601. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  602. except Exception as e:
  603. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  604. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  605. # successfull MOD with the ACI
  606. topology.master1.log.info("\n\n######################### MOVE to: empty/ from: substring filter ######################\n")
  607. _bind_manager(topology)
  608. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_PATTERN, target_to=None)
  609. _bind_normal(topology)
  610. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  611. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  612. # successfull MOD with the both ACI
  613. _bind_manager(topology)
  614. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_PATTERN, target_to=None)
  615. _bind_normal(topology)
  616. def test_ticket47553_moddn_staging_prod_8(topology):
  617. '''
  618. This test case MOVE entry NEW_ACCOUNT8 from staging to prod
  619. target_to/target_from: <empty>/<empty> filter
  620. '''
  621. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (8) ######################\n")
  622. _bind_normal(topology)
  623. old_rdn = "cn=%s8" % NEW_ACCOUNT
  624. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  625. new_rdn = old_rdn
  626. new_superior = PRODUCTION_DN
  627. #
  628. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  629. #
  630. try:
  631. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  632. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  633. assert 0
  634. except AssertionError:
  635. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  636. except Exception as e:
  637. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  638. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  639. # successfull MOD with the ACI
  640. topology.master1.log.info("\n\n######################### MOVE to: empty/ from: empty ######################\n")
  641. _bind_manager(topology)
  642. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=None, target_to=None)
  643. _bind_normal(topology)
  644. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  645. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  646. # successfull MOD with the both ACI
  647. _bind_manager(topology)
  648. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=None, target_to=None)
  649. _bind_normal(topology)
  650. def test_ticket47553_moddn_staging_prod_9(topology):
  651. '''
  652. This test case disable the 'moddn' right so a MODDN requires a 'add' right
  653. to be successfull.
  654. It fails to MOVE entry NEW_ACCOUNT9 from staging to prod.
  655. Add a 'add' right to prod.
  656. Then it succeeds to MOVE NEW_ACCOUNT9 from staging to prod.
  657. Then enable the 'moddn' right so a MODDN requires a 'moddn' right
  658. It fails to MOVE entry NEW_ACCOUNT10 from staging to prod.
  659. Add a 'moddn' right to prod.
  660. Then it succeeds to MOVE NEW_ACCOUNT10 from staging to prod.
  661. '''
  662. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (9) ######################\n")
  663. _bind_normal(topology)
  664. old_rdn = "cn=%s9" % NEW_ACCOUNT
  665. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  666. new_rdn = old_rdn
  667. new_superior = PRODUCTION_DN
  668. #
  669. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  670. #
  671. try:
  672. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  673. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  674. assert 0
  675. except AssertionError:
  676. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  677. except Exception as e:
  678. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  679. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  680. ############################################
  681. # Now do tests with no support of moddn aci
  682. ############################################
  683. topology.master1.log.info("Disable the moddn right" )
  684. _bind_manager(topology)
  685. mod = [(ldap.MOD_REPLACE, CONFIG_MODDN_ACI_ATTR, 'off')]
  686. topology.master1.modify_s(DN_CONFIG, mod)
  687. # Add the moddn aci that will not be evaluated because of the config flag
  688. topology.master1.log.info("\n\n######################### MOVE to and from equality filter ######################\n")
  689. _bind_manager(topology)
  690. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  691. _bind_normal(topology)
  692. # It will fail because it will test the ADD right
  693. try:
  694. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  695. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  696. assert 0
  697. except AssertionError:
  698. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  699. except Exception as e:
  700. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  701. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  702. # remove the moddn aci
  703. _bind_manager(topology)
  704. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  705. _bind_normal(topology)
  706. #
  707. # add the 'add' right to the production DN
  708. # Then do a successfull moddn
  709. #
  710. ACI_ALLOW = "(version 3.0; acl \"ADD rights to allow moddn\"; allow (add)"
  711. ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % BIND_DN
  712. ACI_BODY = ACI_ALLOW + ACI_SUBJECT
  713. _bind_manager(topology)
  714. mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
  715. topology.master1.modify_s(PRODUCTION_DN, mod)
  716. _bind_normal(topology)
  717. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  718. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  719. _bind_manager(topology)
  720. mod = [(ldap.MOD_DELETE, 'aci', ACI_BODY)]
  721. topology.master1.modify_s(PRODUCTION_DN, mod)
  722. _bind_normal(topology)
  723. ############################################
  724. # Now do tests with support of moddn aci
  725. ############################################
  726. topology.master1.log.info("Enable the moddn right" )
  727. _bind_manager(topology)
  728. mod = [(ldap.MOD_REPLACE, CONFIG_MODDN_ACI_ATTR, 'on')]
  729. topology.master1.modify_s(DN_CONFIG, mod)
  730. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (10) ######################\n")
  731. _bind_normal(topology)
  732. old_rdn = "cn=%s10" % NEW_ACCOUNT
  733. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  734. new_rdn = old_rdn
  735. new_superior = PRODUCTION_DN
  736. #
  737. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  738. #
  739. try:
  740. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  741. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  742. assert 0
  743. except AssertionError:
  744. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  745. except Exception as e:
  746. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  747. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  748. #
  749. # add the 'add' right to the production DN
  750. # Then do a failing moddn
  751. #
  752. ACI_ALLOW = "(version 3.0; acl \"ADD rights to allow moddn\"; allow (add)"
  753. ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % BIND_DN
  754. ACI_BODY = ACI_ALLOW + ACI_SUBJECT
  755. _bind_manager(topology)
  756. mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
  757. topology.master1.modify_s(PRODUCTION_DN, mod)
  758. _bind_normal(topology)
  759. try:
  760. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  761. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  762. assert 0
  763. except AssertionError:
  764. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  765. except Exception as e:
  766. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  767. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  768. _bind_manager(topology)
  769. mod = [(ldap.MOD_DELETE, 'aci', ACI_BODY)]
  770. topology.master1.modify_s(PRODUCTION_DN, mod)
  771. _bind_normal(topology)
  772. # Add the moddn aci that will be evaluated because of the config flag
  773. topology.master1.log.info("\n\n######################### MOVE to and from equality filter ######################\n")
  774. _bind_manager(topology)
  775. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  776. _bind_normal(topology)
  777. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  778. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  779. # remove the moddn aci
  780. _bind_manager(topology)
  781. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  782. _bind_normal(topology)
  783. def test_ticket47553_moddn_prod_staging(topology):
  784. '''
  785. This test checks that we can move ACCOUNT11 from staging to prod
  786. but not move back ACCOUNT11 from prod to staging
  787. '''
  788. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (11) ######################\n")
  789. _bind_normal(topology)
  790. old_rdn = "cn=%s11" % NEW_ACCOUNT
  791. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  792. new_rdn = old_rdn
  793. new_superior = PRODUCTION_DN
  794. #
  795. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  796. #
  797. try:
  798. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  799. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  800. assert 0
  801. except AssertionError:
  802. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  803. except Exception as e:
  804. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  805. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  806. # successfull MOD with the ACI
  807. topology.master1.log.info("\n\n######################### MOVE to and from equality filter ######################\n")
  808. _bind_manager(topology)
  809. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  810. _bind_normal(topology)
  811. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  812. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  813. #
  814. # Now check we can not move back the entry to staging
  815. old_rdn = "cn=%s11" % NEW_ACCOUNT
  816. old_dn = "%s,%s" % (old_rdn, PRODUCTION_DN)
  817. new_rdn = old_rdn
  818. new_superior = STAGING_DN
  819. try:
  820. topology.master1.log.info("Try to move back MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  821. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  822. assert 0
  823. except AssertionError:
  824. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  825. except Exception as e:
  826. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  827. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  828. # successfull MOD with the both ACI
  829. _bind_manager(topology)
  830. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  831. _bind_normal(topology)
  832. def test_ticket47553_check_repl_M2_to_M1(topology):
  833. '''
  834. Checks that replication is still working M2->M1, using ACCOUNT12
  835. '''
  836. topology.master1.log.info("Bind as %s (M2)" % DN_DM)
  837. topology.master2.simple_bind_s(DN_DM, PASSWORD)
  838. rdn = "cn=%s12" % NEW_ACCOUNT
  839. dn = "%s,%s" % (rdn, STAGING_DN)
  840. # First wait for the ACCOUNT19 entry being replicated on M2
  841. loop = 0
  842. while loop <= 10:
  843. try:
  844. ent = topology.master2.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)")
  845. break
  846. except ldap.NO_SUCH_OBJECT:
  847. time.sleep(1)
  848. loop += 1
  849. assert loop <= 10
  850. attribute = 'description'
  851. tested_value = 'Hello world'
  852. mod = [(ldap.MOD_ADD, attribute, tested_value)]
  853. topology.master1.log.info("Update (M2) %s (%s)" % (dn, attribute))
  854. topology.master2.modify_s(dn, mod)
  855. loop = 0
  856. while loop <= 10:
  857. ent = topology.master1.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)")
  858. assert ent != None
  859. if ent.hasAttr(attribute) and (ent.getValue(attribute) == tested_value):
  860. break
  861. time.sleep(1)
  862. loop += 1
  863. assert loop < 10
  864. topology.master1.log.info("Update %s (%s) replicated on M1" % (dn, attribute))
  865. def test_ticket47553_moddn_staging_prod_except(topology):
  866. '''
  867. This test case MOVE entry NEW_ACCOUNT13 from staging to prod
  868. but fails to move entry NEW_ACCOUNT14 from staging to prod_except
  869. '''
  870. topology.master1.log.info("\n\n######################### MOVE staging -> Prod (13) ######################\n")
  871. _bind_normal(topology)
  872. old_rdn = "cn=%s13" % NEW_ACCOUNT
  873. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  874. new_rdn = old_rdn
  875. new_superior = PRODUCTION_DN
  876. #
  877. # Try to rename without the apropriate ACI => INSUFFICIENT_ACCESS
  878. #
  879. try:
  880. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  881. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  882. assert 0
  883. except AssertionError:
  884. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  885. except Exception as e:
  886. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  887. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  888. # successfull MOD with the ACI
  889. topology.master1.log.info("\n\n######################### MOVE to and from equality filter ######################\n")
  890. _bind_manager(topology)
  891. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_ADD, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  892. _moddn_aci_deny_tree(topology, mod_type=ldap.MOD_ADD)
  893. _bind_normal(topology)
  894. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  895. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  896. #
  897. # Now try to move an entry under except
  898. #
  899. topology.master1.log.info("\n\n######################### MOVE staging -> Prod/Except (14) ######################\n")
  900. old_rdn = "cn=%s14" % NEW_ACCOUNT
  901. old_dn = "%s,%s" % (old_rdn, STAGING_DN)
  902. new_rdn = old_rdn
  903. new_superior = PROD_EXCEPT_DN
  904. try:
  905. topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
  906. topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
  907. assert 0
  908. except AssertionError:
  909. topology.master1.log.info("Exception (not really expected exception but that is fine as it fails to rename)")
  910. except Exception as e:
  911. topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
  912. assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
  913. # successfull MOD with the both ACI
  914. _bind_manager(topology)
  915. _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=PRODUCTION_DN)
  916. _moddn_aci_deny_tree(topology, mod_type=ldap.MOD_DELETE)
  917. _bind_normal(topology)
  918. def test_ticket47553_final(topology):
  919. topology.master1.stop(timeout=10)
  920. topology.master2.stop(timeout=10)
  921. def run_isolated():
  922. '''
  923. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  924. To run isolated without py.test, you need to
  925. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  926. - set the installation prefix
  927. - run this program
  928. '''
  929. global installation1_prefix
  930. global installation2_prefix
  931. installation1_prefix = None
  932. installation2_prefix = None
  933. topo = topology(True)
  934. topo.master1.log.info("\n\n######################### Ticket 47553 ######################\n")
  935. test_ticket47553_init(topo)
  936. # Check that without appropriate aci we are not allowed to add/delete
  937. test_ticket47553_add(topo)
  938. test_ticket47553_delete(topo)
  939. # tests the ACI as equality/substring filter
  940. test_ticket47553_moddn_staging_prod_0(topo)
  941. test_ticket47553_moddn_staging_prod_1(topo)
  942. test_ticket47553_moddn_staging_prod_2(topo)
  943. test_ticket47553_moddn_staging_prod_3(topo)
  944. test_ticket47553_moddn_staging_prod_4(topo)
  945. test_ticket47553_moddn_staging_prod_5(topo)
  946. # tests the ACI with undefined 'target_to'/'target_from'
  947. test_ticket47553_moddn_staging_prod_6(topo)
  948. test_ticket47553_moddn_staging_prod_7(topo)
  949. test_ticket47553_moddn_staging_prod_8(topo)
  950. # Check we can control the behavior with nsslapd-moddn-aci
  951. test_ticket47553_moddn_staging_prod_9(topo)
  952. # Check we can move entry 'from' -> 'to' but not 'to' -> 'from'
  953. test_ticket47553_moddn_prod_staging(topo)
  954. # check replication is still working
  955. test_ticket47553_check_repl_M2_to_M1(topo)
  956. # check DENY rule is working
  957. test_ticket47553_moddn_staging_prod_except(topo)
  958. test_ticket47553_final(topo)
  959. if __name__ == '__main__':
  960. run_isolated()