gssapi_repl_test.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import os
  2. import sys
  3. import time
  4. import ldap
  5. import logging
  6. import pytest
  7. from lib389 import DirSrv, Entry, tools, tasks
  8. from lib389.tools import DirSrvTools
  9. from lib389._constants import *
  10. from lib389.properties import *
  11. from lib389.tasks import *
  12. from lib389.utils import *
  13. from lib389.mit_krb5 import MitKrb5
  14. #########################################
  15. #
  16. # WARNING!!!!! If this test is failing, and your here to find out why, the
  17. # reason is very likely your hosts file!!!!
  18. #
  19. # IT MUST LOOK LIKE THIS BELOW: Note the unique IPS for each kdc name!
  20. #
  21. # 127.0.0.1 ldapkdc.example.com localhost
  22. # 127.0.1.1 ldapkdc1.example.com
  23. # 127.0.2.1 ldapkdc2.example.com
  24. #
  25. #########################################
  26. logging.getLogger(__name__).setLevel(logging.DEBUG)
  27. log = logging.getLogger(__name__)
  28. REALM = "EXAMPLE.COM"
  29. HOST_MASTER_1 = 'ldapkdc1.example.com'
  30. HOST_MASTER_2 = 'ldapkdc2.example.com'
  31. class TopologyReplication(object):
  32. def __init__(self, master1, master2):
  33. master1.open()
  34. self.master1 = master1
  35. master2.open()
  36. self.master2 = master2
  37. @pytest.fixture(scope="module")
  38. def topology(request):
  39. return
  40. # Create the realm first
  41. krb = MitKrb5(realm=REALM)
  42. if krb.check_realm():
  43. krb.destroy_realm()
  44. krb.create_realm()
  45. DEBUG = False
  46. # Creating master 1...
  47. master1 = DirSrv(verbose=DEBUG)
  48. args_instance[SER_HOST] = HOST_MASTER_1
  49. args_instance[SER_PORT] = PORT_MASTER_1
  50. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  51. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  52. args_instance[SER_REALM] = REALM
  53. args_instance[SER_STRICT_HOSTNAME_CHECKING] = False
  54. args_master = args_instance.copy()
  55. master1.allocate(args_master)
  56. instance_master1 = master1.exists()
  57. if instance_master1:
  58. master1.delete()
  59. master1.create() # There is some magic in .create that finds the realm, and adds the keytab for us.
  60. master1.open()
  61. master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  62. # Creating master 2...
  63. master2 = DirSrv(verbose=DEBUG)
  64. args_instance[SER_HOST] = HOST_MASTER_2
  65. args_instance[SER_PORT] = PORT_MASTER_2
  66. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
  67. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  68. args_instance[SER_REALM] = REALM
  69. args_instance[SER_STRICT_HOSTNAME_CHECKING] = False
  70. args_master = args_instance.copy()
  71. master2.allocate(args_master)
  72. instance_master2 = master2.exists()
  73. if instance_master2:
  74. master2.delete()
  75. master2.create()
  76. master2.open()
  77. master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
  78. # Delete each instance in the end
  79. def fin():
  80. master1.delete()
  81. master2.delete()
  82. if krb.check_realm():
  83. krb.destroy_realm()
  84. request.addfinalizer(fin)
  85. # Clear out the tmp dir
  86. master1.clearTmpDir(__file__)
  87. return TopologyReplication(master1, master2)
  88. def _create_machine_ou(inst):
  89. inst.add_s( Entry(( "ou=Machines,%s" % DEFAULT_SUFFIX, {
  90. 'objectClass' : 'top organizationalUnit'.split(),
  91. 'ou' : 'Machines'
  92. }
  93. ))
  94. )
  95. def _create_machine_account(inst, name):
  96. # Create the simple security objects for the servers to replicate to
  97. inst.add_s( Entry(( "uid=%s,ou=Machines,%s" % (name, DEFAULT_SUFFIX),
  98. {
  99. 'objectClass' : 'top account'.split(),
  100. 'uid' : name
  101. }
  102. )))
  103. def _check_machine_account(inst, name):
  104. r = inst.search_s( 'ou=Machines,%s' % DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, '(uid=%s)' % name)
  105. if len(r) > 0:
  106. return True
  107. return False
  108. def _allow_machine_account(inst, name):
  109. # First we need to get the mapping tree dn
  110. mt = inst.mappingtree.list(suffix=DEFAULT_SUFFIX)[0]
  111. inst.modify_s('cn=replica,%s' % mt.dn, [
  112. (ldap.MOD_REPLACE, 'nsDS5ReplicaBindDN', "uid=%s,ou=Machines,%s" % (name, DEFAULT_SUFFIX))
  113. ])
  114. def test_gssapi_repl(topology):
  115. """
  116. Create a kdc, then using that, provision two masters which have a gssapi
  117. authenticated replication agreement.
  118. """
  119. return
  120. master1 = topology.master1
  121. master2 = topology.master2
  122. # Create the locations on each master for the other to bind to.
  123. _create_machine_ou(master1)
  124. _create_machine_ou(master2)
  125. _create_machine_account(master1, 'ldap/%s' % HOST_MASTER_1)
  126. _create_machine_account(master1, 'ldap/%s' % HOST_MASTER_2)
  127. _create_machine_account(master2, 'ldap/%s' % HOST_MASTER_1)
  128. _create_machine_account(master2, 'ldap/%s' % HOST_MASTER_2)
  129. # Set on the cn=replica config to accept the other masters princ mapping under mapping tree
  130. _allow_machine_account(master1, 'ldap/%s' % HOST_MASTER_2)
  131. _allow_machine_account(master2, 'ldap/%s' % HOST_MASTER_1)
  132. #
  133. # Create all the agreements
  134. #
  135. # Creating agreement from master 1 to master 2
  136. # Set the replica bind method to sasl gssapi
  137. properties = {RA_NAME: r'meTo_$host:$port',
  138. RA_METHOD: 'SASL/GSSAPI',
  139. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  140. m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
  141. if not m1_m2_agmt:
  142. log.fatal("Fail to create a master -> master replica agreement")
  143. sys.exit(1)
  144. log.debug("%s created" % m1_m2_agmt)
  145. # Creating agreement from master 2 to master 1
  146. # Set the replica bind method to sasl gssapi
  147. properties = {RA_NAME: r'meTo_$host:$port',
  148. RA_METHOD: 'SASL/GSSAPI',
  149. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  150. m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
  151. if not m2_m1_agmt:
  152. log.fatal("Fail to create a master -> master replica agreement")
  153. sys.exit(1)
  154. log.debug("%s created" % m2_m1_agmt)
  155. # Allow the replicas to get situated with the new agreements...
  156. time.sleep(5)
  157. #
  158. # Initialize all the agreements
  159. #
  160. master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
  161. master1.waitForReplInit(m1_m2_agmt)
  162. # Check replication is working...
  163. if master1.testReplication(DEFAULT_SUFFIX, master2):
  164. log.info('Replication is working.')
  165. else:
  166. log.fatal('Replication is not working.')
  167. assert False
  168. # Add a user to master 1
  169. _create_machine_account(master1, 'http/one.example.com')
  170. # Check it's on 2
  171. time.sleep(5)
  172. assert(_check_machine_account(master2, 'http/one.example.com'))
  173. # Add a user to master 2
  174. _create_machine_account(master2, 'http/two.example.com')
  175. # Check it's on 1
  176. time.sleep(5)
  177. assert(_check_machine_account(master2, 'http/two.example.com'))
  178. log.info('Test complete')
  179. if __name__ == '__main__':
  180. # Run isolated
  181. # -s for DEBUG mode
  182. CURRENT_FILE = os.path.realpath(__file__)
  183. pytest.main("-s %s" % CURRENT_FILE)