dirsrvtests/tests/suites/gssapi_repl/gssapi_repl_test.py | 216 +++++++++++++++
1 file changed, 216 insertions(+)
New commits:
commit 2a32cab7ad3aa0aff1ab1a81a3a96334be0525f8
Author: William Brown <firstyear(a)redhat.com>
Date: Wed May 11 13:37:18 2016 +1000
Ticket 48829 - Add gssapi sasl replication bind test
Bug Description: We previously had no way to test if replication via a gssapi
agreement was working.
Fix Description: This adds a test case capable of creating a gssapi environment
and binding the accounts for replication.
https://fedorahosted.org/389/ticket/48829
Author: wibrown
Review by: spichugi (Thanks!)
diff --git a/dirsrvtests/tests/suites/gssapi_repl/gssapi_repl_test.py
b/dirsrvtests/tests/suites/gssapi_repl/gssapi_repl_test.py
new file mode 100644
index 0000000..57f670f
--- /dev/null
+++ b/dirsrvtests/tests/suites/gssapi_repl/gssapi_repl_test.py
@@ -0,0 +1,216 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from lib389.utils import *
+from lib389.mit_krb5 import MitKrb5
+
+
+#########################################
+#
+# WARNING!!!!! If this test is failing, and your here to find out why, the
+# reason is very likely your hosts file!!!!
+#
+# IT MUST LOOK LIKE THIS BELOW: Note the unique IPS for each kdc name!
+#
+# 127.0.0.1
ldapkdc.example.com localhost
+# 127.0.1.1
ldapkdc1.example.com
+# 127.0.2.1
ldapkdc2.example.com
+#
+#########################################
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+REALM = "EXAMPLE.COM"
+
+HOST_MASTER_1 = 'ldapkdc1.example.com'
+HOST_MASTER_2 = 'ldapkdc2.example.com'
+
+class TopologyReplication(object):
+ def __init__(self, master1, master2):
+ master1.open()
+ self.master1 = master1
+ master2.open()
+ self.master2 = master2
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ # Create the realm first
+ krb = MitKrb5(realm=REALM)
+ if krb.check_realm():
+ krb.destroy_realm()
+ krb.create_realm()
+ DEBUG = False
+
+ # Creating master 1...
+ master1 = DirSrv(verbose=DEBUG)
+ args_instance[SER_HOST] = HOST_MASTER_1
+ args_instance[SER_PORT] = PORT_MASTER_1
+ args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_instance[SER_REALM] = REALM
+ args_instance[SER_STRICT_HOSTNAME_CHECKING] = False
+ args_master = args_instance.copy()
+ master1.allocate(args_master)
+ instance_master1 = master1.exists()
+ if instance_master1:
+ master1.delete()
+ master1.create() # There is some magic in .create that finds the realm, and adds the
keytab for us.
+ master1.open()
+ master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER,
replicaId=REPLICAID_MASTER_1)
+
+ # Creating master 2...
+ master2 = DirSrv(verbose=DEBUG)
+ args_instance[SER_HOST] = HOST_MASTER_2
+ args_instance[SER_PORT] = PORT_MASTER_2
+ args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_instance[SER_REALM] = REALM
+ args_instance[SER_STRICT_HOSTNAME_CHECKING] = False
+ args_master = args_instance.copy()
+ master2.allocate(args_master)
+ instance_master2 = master2.exists()
+ if instance_master2:
+ master2.delete()
+ master2.create()
+ master2.open()
+ master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER,
replicaId=REPLICAID_MASTER_2)
+
+ # Delete each instance in the end
+ def fin():
+ master1.delete()
+ master2.delete()
+ if krb.check_realm():
+ krb.destroy_realm()
+ #request.addfinalizer(fin)
+
+ # Clear out the tmp dir
+ master1.clearTmpDir(__file__)
+
+ return TopologyReplication(master1, master2)
+
+def _create_machine_ou(inst):
+ inst.add_s( Entry(( "ou=Machines,%s" % DEFAULT_SUFFIX, {
+ 'objectClass' : 'top organizationalUnit'.split(),
+ 'ou' : 'Machines'
+ }
+ ))
+ )
+
+def _create_machine_account(inst, name):
+ # Create the simple security objects for the servers to replicate to
+ inst.add_s( Entry(( "uid=%s,ou=Machines,%s" % (name, DEFAULT_SUFFIX),
+ {
+ 'objectClass' : 'top account'.split(),
+ 'uid' : name
+ }
+ )))
+
+def _check_machine_account(inst, name):
+ r = inst.search_s( 'ou=Machines,%s' % DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE,
'(uid=%s)' % name)
+ if len(r) > 0:
+ return True
+ return False
+
+def _allow_machine_account(inst, name):
+ # First we need to get the mapping tree dn
+ mt = inst.mappingtree.list(suffix=DEFAULT_SUFFIX)[0]
+ inst.modify_s('cn=replica,%s' % mt.dn, [
+ (ldap.MOD_REPLACE, 'nsDS5ReplicaBindDN',
"uid=%s,ou=Machines,%s" % (name, DEFAULT_SUFFIX))
+ ])
+
+def test_gssapi_repl(topology):
+ """
+ Create a kdc, then using that, provision two masters which have a gssapi
+ authenticated replication agreement.
+ """
+
+ master1 = topology.master1
+ master2 = topology.master2
+
+
+ # Create the locations on each master for the other to bind to.
+ _create_machine_ou(master1)
+ _create_machine_ou(master2)
+
+ _create_machine_account(master1, 'ldap/%s' % HOST_MASTER_1)
+ _create_machine_account(master1, 'ldap/%s' % HOST_MASTER_2)
+ _create_machine_account(master2, 'ldap/%s' % HOST_MASTER_1)
+ _create_machine_account(master2, 'ldap/%s' % HOST_MASTER_2)
+
+ # Set on the cn=replica config to accept the other masters princ mapping under
mapping tree
+ _allow_machine_account(master1, 'ldap/%s' % HOST_MASTER_2)
+ _allow_machine_account(master2, 'ldap/%s' % HOST_MASTER_1)
+
+ #
+ # Create all the agreements
+ #
+ # Creating agreement from master 1 to master 2
+
+ # Set the replica bind method to sasl gssapi
+ properties = {RA_NAME: r'meTo_$host:$port',
+ RA_METHOD: 'SASL/GSSAPI',
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+ m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host,
port=master2.port, properties=properties)
+ if not m1_m2_agmt:
+ log.fatal("Fail to create a master -> master replica agreement")
+ sys.exit(1)
+ log.debug("%s created" % m1_m2_agmt)
+
+ # Creating agreement from master 2 to master 1
+
+ # Set the replica bind method to sasl gssapi
+ properties = {RA_NAME: r'meTo_$host:$port',
+ RA_METHOD: 'SASL/GSSAPI',
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+ m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host,
port=master1.port, properties=properties)
+ if not m2_m1_agmt:
+ log.fatal("Fail to create a master -> master replica agreement")
+ sys.exit(1)
+ log.debug("%s created" % m2_m1_agmt)
+
+ # Allow the replicas to get situated with the new agreements...
+ time.sleep(5)
+
+ #
+ # Initialize all the agreements
+ #
+ master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
+ master1.waitForReplInit(m1_m2_agmt)
+
+ # Check replication is working...
+ if master1.testReplication(DEFAULT_SUFFIX, master2):
+ log.info('Replication is working.')
+ else:
+ log.fatal('Replication is not working.')
+ assert False
+
+ # Add a user to master 1
+ _create_machine_account(master1, 'http/one.example.com')
+ # Check it's on 2
+ time.sleep(5)
+ assert(_check_machine_account(master2, 'http/one.example.com'))
+ # Add a user to master 2
+ _create_machine_account(master2, 'http/two.example.com')
+ # Check it's on 1
+ time.sleep(5)
+ assert(_check_machine_account(master2, 'http/two.example.com'))
+
+
+ log.info('Test complete')
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)