This is an automated email from the git hooks/post-receive script.
firstyear pushed a commit to branch master
in repository 389-ds-base.
commit 87609c0a150cbf5db404aa57e8e7ad63e4d222fa
Author: William Brown <firstyear(a)redhat.com>
Date: Wed Nov 29 15:55:12 2017 +0100
Ticket 49474 - Improve GSSAPI testing capability
Bug Description: GSSAPI is difficult to test correctly. Having
support for it as a topology in lib389 will mak ethis easier.
Note that these tests require specific dns and hosts settings.
Fix Description: Improve the ability to integrate accounts with
principles, bind them with GSSAPI, oru ability to return valid
uris with krb realms, our saslmap capabilities and create a
single master gssapi topology.
https://pagure.io/389-ds-base/issue/49474
Author: wibrown
Review by: spichugi (Thank you!)
---
dirsrvtests/tests/suites/gssapi/__init__.py | 0
.../tests/suites/gssapi/simple_gssapi_test.py | 147 +++++++++++++++++++++
src/lib389/lib389/__init__.py | 64 +++------
src/lib389/lib389/idm/account.py | 31 +++++
src/lib389/lib389/mit_krb5.py | 19 +--
src/lib389/lib389/properties.py | 1 -
src/lib389/lib389/saslmap.py | 54 ++++++++
src/lib389/lib389/tests/krb5_create_test.py | 147 ---------------------
src/lib389/lib389/tools.py | 2 +-
src/lib389/lib389/topologies.py | 76 ++++++++++-
10 files changed, 332 insertions(+), 209 deletions(-)
diff --git a/dirsrvtests/tests/suites/gssapi/__init__.py
b/dirsrvtests/tests/suites/gssapi/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/dirsrvtests/tests/suites/gssapi/simple_gssapi_test.py
b/dirsrvtests/tests/suites/gssapi/simple_gssapi_test.py
new file mode 100644
index 0000000..9a881cb
--- /dev/null
+++ b/dirsrvtests/tests/suites/gssapi/simple_gssapi_test.py
@@ -0,0 +1,147 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+
+from lib389.topologies import topology_st_gssapi, gssapi_ack
+from lib389.idm.user import UserAccounts
+
+from lib389.saslmap import SaslMappings
+
+from lib389._constants import DEFAULT_SUFFIX
+
+import ldap
+import subprocess
+import os
+import pytest
+
+
+
+(a)pytest.fixture(scope='module')
+def testuser(topology_st_gssapi):
+ # Create a user
+ users = UserAccounts(topology_st_gssapi.standalone, DEFAULT_SUFFIX)
+ user = users.create(properties={
+ 'uid': 'testuser',
+ 'cn' : 'testuser',
+ 'sn' : 'user',
+ 'uidNumber' : '1000',
+ 'gidNumber' : '2000',
+ 'homeDirectory' : '/home/testuser'
+ })
+ # Give them a krb princ
+ user.create_keytab()
+ return user
+
+@gssapi_ack
+def test_gssapi_bind(topology_st_gssapi, testuser):
+ """Test that we can bind with GSSAPI
+
+ :id: 894a4c27-3d4c-4ba3-aa33-2910032e3783
+
+ :setup: standalone gssapi instance
+
+ :steps:
+ 1. Bind with sasl/gssapi
+ :expectedresults:
+ 1. Bind succeeds
+
+ """
+ conn = testuser.bind_gssapi()
+ assert(conn.whoami_s() == "dn: %s" % testuser.dn.lower())
+
+@gssapi_ack
+def test_invalid_sasl_map(topology_st_gssapi, testuser):
+ """Test that auth fails when we can not map a user.
+
+ :id: dd4218eb-9237-4611-ba2f-1781391cadd1
+
+ :setup: standalone gssapi instance
+
+ :steps:
+ 1. Invalidate a sasl map
+ 2. Attempt to bind
+ :expectedresults:
+ 1. The sasl map is invalid.
+ 2. The bind fails.
+ """
+ saslmaps = SaslMappings(topology_st_gssapi.standalone)
+ saslmap = saslmaps.get('suffix map')
+ saslmap.set('nsSaslMapFilterTemplate', '(invalidattr=\\1)')
+
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ conn = testuser.bind_gssapi()
+
+ saslmap.set('nsSaslMapFilterTemplate', '(uid=\\1)')
+
+@gssapi_ack
+def test_missing_user(topology_st_gssapi):
+ """Test that binding with no user does not work.
+
+ :id: 109b5ab8-6556-4222-92d6-398476a50d30
+
+ :setup: standalone gssapi instance
+
+ :steps:
+ 1. Create a principal with a name that is not mappable
+ 2. Attempt to bind
+ :expectedresults:
+ 1. The principal is created
+ 2. The bind fails.
+ """
+ # Make a principal and bind with no user.
+ st = topology_st_gssapi.standalone
+ st.realm.create_principal("doesnotexist")
+ st.realm.create_keytab("doesnotexist",
"/tmp/doesnotexist.keytab")
+ # Now try to bind.
+ subprocess.call(['/usr/bin/kdestroy', '-A'])
+ os.environ["KRB5_CLIENT_KTNAME"] = "/tmp/doesnotexist.keytab"
+
+ conn = ldap.initialize(st.toLDAPURL())
+ sasltok = ldap.sasl.gssapi()
+
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ conn.sasl_interactive_bind_s('', sasltok)
+
+@gssapi_ack
+def test_support_mech(topology_st_gssapi, testuser):
+ """Test allowed sasl mechs works when GSSAPI is allowed
+
+ :id: 6ec80aca-00c4-4141-b96b-3ae8837fc751
+
+ :setup: standalone gssapi instance
+
+ :steps:
+ 1. Add GSSAPI to allowed sasl mechanisms.
+ 2. Attempt to bind
+ :expectedresults:
+ 1. The allowed mechs are changed.
+ 2. The bind succeeds.
+ """
+ topology_st_gssapi.standalone.config.set('nsslapd-allowed-sasl-mechanisms',
'GSSAPI EXTERNAL ANONYMOUS')
+ conn = testuser.bind_gssapi()
+ assert(conn.whoami_s() == "dn: %s" % testuser.dn.lower())
+
+@gssapi_ack
+def test_rejected_mech(topology_st_gssapi, testuser):
+ """Test allowed sasl mechs fail when GSSAPI is not allowed.
+
+ :id: 7896c756-6f65-4390-a844-12e2eec19675
+
+ :setup: standalone gssapi instance
+
+ :steps:
+ 1. Add GSSAPI to allowed sasl mechanisms.
+ 2. Attempt to bind
+ :expectedresults:
+ 1. The allowed mechs are changed.
+ 2. The bind fails.
+ """
+ topology_st_gssapi.standalone.config.set('nsslapd-allowed-sasl-mechanisms',
'EXTERNAL ANONYMOUS')
+ with pytest.raises(ldap.STRONG_AUTH_NOT_SUPPORTED):
+ conn = testuser.bind_gssapi()
+ topology_st_gssapi.standalone.config.set('nsslapd-allowed-sasl-mechanisms',
'GSSAPI EXTERNAL ANONYMOUS')
+
diff --git a/src/lib389/lib389/__init__.py b/src/lib389/lib389/__init__.py
index 6961d1f..fab1ed1 100644
--- a/src/lib389/lib389/__init__.py
+++ b/src/lib389/lib389/__init__.py
@@ -50,6 +50,8 @@ import subprocess
import collections
import signal
import errno
+import pwd
+import grp
from shutil import copy2
try:
# There are too many issues with this on EL7
@@ -390,7 +392,6 @@ class DirSrv(SimpleLDAPObject, object):
args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
args_instance[SER_USER_ID] = None
args_instance[SER_GROUP_ID] = None
- args_instance[SER_REALM] = None
args_instance[SER_INST_SCRIPTS_ENABLED] = None
# We allocate a "default" prefix here which allows an un-allocate or
@@ -522,7 +523,7 @@ class DirSrv(SimpleLDAPObject, object):
self.ldapuri = args.get(SER_LDAP_URL, None)
self.log.debug("Allocate %s with %s" % (self.__class__, self.ldapuri))
# Still needed in setup, even if ldapuri over writes.
- self.host = args.get(SER_HOST, LOCALHOST)
+ self.host = args.get(SER_HOST, socket.gethostname())
self.port = args.get(SER_PORT, DEFAULT_PORT)
self.sslport = args.get(SER_SECURE_PORT)
@@ -564,9 +565,8 @@ class DirSrv(SimpleLDAPObject, object):
# Allocate from the args, or use our env, or use /
if args.get(SER_DEPLOYED_DIR, self.prefix) is not None:
self.prefix = args.get(SER_DEPLOYED_DIR, self.prefix)
- self.realm = args.get(SER_REALM, None)
- if self.realm is not None:
- self.krb5_realm = MitKrb5(realm=self.realm, debug=self.verbose)
+ # This will be externally populated in topologies.
+ self.realm = None
# Those variables needs to be revisited (sroot for 64 bits)
# self.sroot = os.path.join(self.prefix, "lib/dirsrv")
@@ -596,6 +596,7 @@ class DirSrv(SimpleLDAPObject, object):
args_instance[SER_LDAP_URL] = self.ldapuri
args_instance[SER_HOST] = self.host
args_instance[SER_PORT] = self.port
+ args_instance[SER_LDAP_URL] = self.ldapuri
args_instance[SER_SECURE_PORT] = self.sslport
args_instance[SER_SERVERID_PROP] = self.serverid
args_standalone = args_instance.copy()
@@ -863,7 +864,6 @@ class DirSrv(SimpleLDAPObject, object):
SER_GROUP_ID (groupid)
SER_DEPLOYED_DIR (prefix)
SER_BACKUP_INST_DIR (backupdir)
- SER_REALM (krb5_realm)
@return None
@@ -901,17 +901,6 @@ class DirSrv(SimpleLDAPObject, object):
prefix=self.prefix)
if result != 0:
raise Exception('Failed to run setup-ds.pl')
- if self.realm is not None:
- # This may conflict in some tests, we may need to use /etc/host
- # aliases or we may need to use server id
- self.krb5_realm.create_principal(principal='ldap/%s' % self.host)
- ktab = '%s/ldap.keytab' % (self.ds_paths.config_dir)
- self.krb5_realm.create_keytab(principal='ldap/%s' % self.host,
keytab=ktab)
- with open('%s/dirsrv-%s' % (self.ds_paths.initconfig_dir,
self.serverid), 'a') as sfile:
- sfile.write("\nKRB5_KTNAME=%s/etc/dirsrv/slapd-%s/"
- "ldap.keytab\nexport KRB5_KTNAME\n" %
- (self.prefix, self.serverid))
- self.restart()
def _createPythonDirsrv(self, version):
"""
@@ -953,17 +942,7 @@ class DirSrv(SimpleLDAPObject, object):
# Go!
sds.create_from_args(general, slapd, backends, None)
- if self.realm is not None:
- # This may conflict in some tests, we may need to use /etc/host
- # aliases or we may need to use server id
- self.krb5_realm.create_principal(principal='ldap/%s' % self.host)
- ktab = '%s/ldap.keytab' % (self.ds_paths.config_dir)
- self.krb5_realm.create_keytab(principal='ldap/%s' % self.host,
keytab=ktab)
- with open('%s/dirsrv-%s' % (self.ds_paths.initconfig_dir,
self.serverid), 'a') as sfile:
- sfile.write("\nKRB5_KTNAME=%s/etc/dirsrv/slapd-%s/"
- "ldap.keytab\nexport KRB5_KTNAME\n" %
- (self.prefix, self.serverid))
- self.restart()
+
def create(self, pyinstall=False, version=INSTALL_LATEST_CONFIG):
"""
@@ -1144,28 +1123,20 @@ class DirSrv(SimpleLDAPObject, object):
if starttls and not uri.startswith('ldaps'):
self.start_tls_s()
- if saslmethod and saslmethod.lower() == 'gssapi':
+ if saslmethod and sasltoken is not None:
+ # Just pass the sasltoken in!
+ self.sasl_interactive_bind_s("", sasltoken)
+ elif saslmethod and saslmethod.lower() == 'gssapi':
"""
Perform kerberos/gssapi authentication
"""
- try:
- sasl_auth = ldap.sasl.gssapi("")
- self.sasl_interactive_bind_s("", sasl_auth)
- except ldap.LOCAL_ERROR as e:
- # No Ticket - ultimately invalid credentials
- self.log.debug("Error: No Ticket (%s)" % str(e))
- raise ldap.INVALID_CREDENTIALS
- except ldap.LDAPError as e:
- self.log.debug("SASL/GSSAPI Bind Failed: %s" % str(e))
- raise e
+ sasl_auth = ldap.sasl.gssapi("")
+ self.sasl_interactive_bind_s("", sasl_auth)
elif saslmethod == 'EXTERNAL':
# Do nothing.
sasl_auth = ldap.sasl.external()
self.sasl_interactive_bind_s("", sasl_auth)
- elif saslmethod and sasltoken is not None:
- # Just pass the sasltoken in!
- self.sasl_interactive_bind_s("", sasltoken)
elif saslmethod:
# Unknown or unsupported method
self.log.debug('Unsupported SASL method: %s' % saslmethod)
@@ -1651,7 +1622,8 @@ class DirSrv(SimpleLDAPObject, object):
return self.ldapuri
elif self.ldapi_enabled == 'on' and self.ldapi_socket is not None:
return "ldapi://%s" %
(ldapurl.ldapUrlEscape(ensure_str(ldapi_socket)))
- elif self.sslport:
+ elif self.sslport and not self.realm:
+ # Gssapi can't use SSL so we have to nuke it here.
return "ldaps://%s:%d/" % (ensure_str(self.host), self.sslport)
else:
return "ldap://%s:%d/" % (ensure_str(self.host), self.port)
@@ -1772,6 +1744,12 @@ class DirSrv(SimpleLDAPObject, object):
def get_ldapi_path(self):
return self.ds_paths.ldapi
+ def get_user_uid(self):
+ return pwd.getpwnam(self.ds_paths.user).pw_uid
+
+ def get_group_gid(self):
+ return grp.getgrnam(self.ds_paths.group).gr_gid
+
def has_asan(self):
return self.ds_paths.asan_enabled
diff --git a/src/lib389/lib389/idm/account.py b/src/lib389/lib389/idm/account.py
index 02c2954..92038bf 100644
--- a/src/lib389/lib389/idm/account.py
+++ b/src/lib389/lib389/idm/account.py
@@ -9,6 +9,8 @@
from lib389._mapped_object import DSLdapObject, DSLdapObjects, _gen_or, _gen_filter,
_term_gen
from lib389._constants import SER_ROOT_DN, SER_ROOT_PW
+import os
+import subprocess
class Account(DSLdapObject):
"""A single instance of Account entry
@@ -62,6 +64,35 @@ class Account(DSLdapObject):
inst_clone.open(*args, **kwargs)
return inst_clone
+ def create_keytab(self):
+ """
+ Create a keytab for this account valid to bind with.
+ """
+ assert self._instance.realm is not None
+
+ myuid = self.get_attr_val_utf8('uid')
+ self._instance.realm.create_principal(myuid)
+ self._instance.realm.create_keytab(myuid, "/tmp/%s.keytab" % myuid)
+
+ self._keytab = "/tmp/%s.keytab" % myuid
+
+ def bind_gssapi(self):
+ """
+ Bind this account with gssapi credntials (if available)
+ """
+ assert self._instance.realm is not None
+ # Kill any local ccache.
+ subprocess.call(['/usr/bin/kdestroy', '-A'])
+
+ # This uses an in memory once off ccache.
+ os.environ["KRB5_CLIENT_KTNAME"] = self._keytab
+
+ # Because of the way that GSSAPI works, we can't
+ # use the normal dirsrv open method.
+ inst_clone = self._instance.clone()
+ inst_clone.open(saslmethod='gssapi')
+ return inst_clone
+
class Accounts(DSLdapObjects):
"""DSLdapObjects that represents Account entry
diff --git a/src/lib389/lib389/mit_krb5.py b/src/lib389/lib389/mit_krb5.py
index 64ca24d..fe37387 100644
--- a/src/lib389/lib389/mit_krb5.py
+++ b/src/lib389/lib389/mit_krb5.py
@@ -108,6 +108,9 @@ class MitKrb5(object):
realm = self.realm
lrealm = self.realm.lower()
cfile.write("""
+[libdefaults]
+ default_realm = {REALM}
+
[realms]
{REALM} = {{
kdc = {HOST}
@@ -130,12 +133,11 @@ class MitKrb5(object):
[realms]
{REALM} = {{
- #master_key_type = aes256-cts
acl_file = {PREFIX}/var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = {PREFIX}/var/kerberos/krb5kdc/kadm5.keytab
# Just use strong enctypes
- supported_enctypes = aes256-cts:normal aes128-cts:normal
+ # supported_enctypes = aes256-cts:normal aes128-cts:normal
}}
""".format(REALM=self.realm, PREFIX=self.krb_prefix))
@@ -170,7 +172,7 @@ class MitKrb5(object):
p = Popen([self.kdb5_util, 'destroy', '-r', self.realm],
env=self.krb_env, stdin=PIPE)
- p.communicate("yes\n")
+ p.communicate(b"yes\n")
p.wait()
assert(p.returncode == 0)
# Should we clean up the configurations we made too?
@@ -213,14 +215,3 @@ class MitKrb5(object):
(keytab, principal, self.realm)])
assert(p.wait() == 0)
-
-class KrbClient(object):
- def __init__(self, principal, keytab, ccache=None):
- self.krb_prefix = ""
- self.kdestroy = "/usr/bin/kdestroy"
- if ccache is not None:
- os.environ["KRB5CCNAME"] = ccache
- # Destroy the previous cache if any.
- subprocess.call(self.kdestroy)
- # Gssapi has magic that automatically creates things by env vars
- os.environ["KRB5_CLIENT_KTNAME"] = keytab
diff --git a/src/lib389/lib389/properties.py b/src/lib389/lib389/properties.py
index 2a9e174..e986aea 100644
--- a/src/lib389/lib389/properties.py
+++ b/src/lib389/lib389/properties.py
@@ -44,7 +44,6 @@ SER_PROPNAME_TO_ATTRNAME = {SER_HOST: 'nsslapd-localhost',
#
# Those WITHOUT related attribute name
#
-SER_REALM = 'krb5_realm'
SER_SERVERID_PROP = 'server-id'
SER_GROUP_ID = 'group-id'
SER_DEPLOYED_DIR = 'deployed-dir'
diff --git a/src/lib389/lib389/saslmap.py b/src/lib389/lib389/saslmap.py
new file mode 100644
index 0000000..3105f2e
--- /dev/null
+++ b/src/lib389/lib389/saslmap.py
@@ -0,0 +1,54 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+
+from lib389._mapped_object import DSLdapObject, DSLdapObjects
+
+class SaslMapping(DSLdapObject):
+ """A sasl map providing a link from a sasl user and realm
+ to a valid directory server entry.
+
+ :param instance: An instance
+ :type instance: lib389.DirSrv
+ :param dn: Entry DN
+ :type dn: str
+ """
+
+ def __init__(self, instance, dn=None):
+ super(SaslMapping, self).__init__(instance, dn)
+ self._rdn_attribute = 'cn'
+ self._must_attributes = [
+ 'cn',
+ 'nsSaslMapRegexString',
+ 'nsSaslMapBaseDNTemplate',
+ 'nsSaslMapFilterTemplate',
+ ]
+ self._create_objectclasses = [
+ 'top',
+ 'nsSaslMapping',
+ ]
+ self._protected = False
+
+class SaslMappings(DSLdapObjects):
+ """DSLdapObjects that represents SaslMappings in the server.
+
+ :param instance: An instance
+ :type instance: lib389.DirSrv
+ :param basedn: Base DN for all group entries below
+ :type basedn: str
+ """
+
+ def __init__(self, instance):
+ super(SaslMappings, self).__init__(instance)
+ self._objectclasses = [
+ 'nsSaslMapping',
+ ]
+ self._filterattrs = ['cn']
+ self._childobject = SaslMapping
+ self._basedn = 'cn=mapping,cn=sasl,cn=config'
+
+
diff --git a/src/lib389/lib389/tests/krb5_create_test.py
b/src/lib389/lib389/tests/krb5_create_test.py
deleted file mode 100644
index 182d51f..0000000
--- a/src/lib389/lib389/tests/krb5_create_test.py
+++ /dev/null
@@ -1,147 +0,0 @@
-
-# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2015 Red Hat, Inc.
-# All rights reserved.
-#
-# License: GPL (version 3 or any later version).
-# See LICENSE for details.
-# --- END COPYRIGHT BLOCK ---
-#
-from lib389._constants import *
-from lib389.mit_krb5 import MitKrb5, KrbClient
-from lib389 import DirSrv, Entry
-import pytest
-import logging
-import socket
-import subprocess
-
-import ldap
-import ldap.sasl
-
-logging.getLogger(__name__).setLevel(logging.DEBUG)
-log = logging.getLogger(__name__)
-
-INSTANCE_PORT = 54321
-INSTANCE_SERVERID = 'standalone'
-REALM = "EXAMPLE.COM"
-TEST_USER = 'uid=test,%s' % DEFAULT_SUFFIX
-
-KEYTAB = "/tmp/test.keytab"
-CCACHE = "FILE:/tmp/test.ccache"
-
-
-class TopologyInstance(object):
- def __init__(self, instance):
- instance.open()
- self.instance = instance
-
-
-(a)pytest.fixture(scope="module")
-def topology(request):
- # Create the realm
- krb = MitKrb5(realm=REALM)
- instance = DirSrv(verbose=False)
- instance.log.debug("Instance allocated")
- # WARNING: If this test fails it's like a hostname issue!!!
- args = {SER_HOST: socket.gethostname(),
- SER_PORT: INSTANCE_PORT,
- SER_REALM: REALM,
- SER_SERVERID_PROP: INSTANCE_SERVERID}
- instance.allocate(args)
- if instance.exists():
- instance.delete()
- # Its likely our realm exists too
- # Remove the old keytab
- if os.path.exists(KEYTAB):
- os.remove(KEYTAB)
- if krb.check_realm():
- krb.destroy_realm()
- # This will automatically create the krb entries
- krb.create_realm()
- instance.create()
- instance.open()
-
- def fin():
- if instance.exists():
- instance.delete()
- if krb.check_realm():
- krb.destroy_realm()
- if os.path.exists(KEYTAB):
- os.remove(KEYTAB)
- if os.path.exists(CCACHE):
- os.remove(CCACHE)
- request.addfinalizer(fin)
-
- return TopologyInstance(instance)
-
-
-(a)pytest.fixture(scope="module")
-def add_user(topology):
- """
- Create a user entry
- """
-
- log.info('Create a user entry: %s' % TEST_USER)
- uentry = Entry(TEST_USER)
- uentry.setValues('objectclass', 'top', 'extensibleobject')
- uentry.setValues('uid', 'test')
- topology.instance.add_s(uentry)
- # This doesn't matter that we re-open the realm
- krb = MitKrb5(realm=REALM)
- krb.create_principal("test")
- # We extract the kt so we can kinit from it
- krb.create_keytab("test", "/tmp/test.keytab")
-
-
-def test_gssapi(topology, add_user):
- """
- Check that our bind completese with ldapwhoami correctly mapped from
- the principal to our test user object.
- """
- # Init our local ccache
- kclient = KrbClient("test@%s" % REALM, KEYTAB, CCACHE)
- # Probably need to change this to NOT be raw python ldap
- # conn = ldap.initialize("ldap://%s:%s" % (LOCALHOST, INSTANCE_PORT))
- conn = ldap.initialize("ldap://%s:%s" % (socket.gethostname(),
INSTANCE_PORT))
- sasl = ldap.sasl.gssapi("test@%s" % REALM)
- try:
- conn.sasl_interactive_bind_s('', sasl)
- except Exception as e:
- try:
- print("%s" % subprocess.check_output(['klist']))
- except Exception as ex:
- print("%s" % ex)
- print("%s" % os.environ)
- print("IF THIS TEST FAILS ITS LIKELY A HOSTNAME ISSUE")
- raise e
- assert(conn.whoami_s() == "dn: uid=test,dc=example,dc=com")
-
- print("Error case 1. Broken Kerberos uid mapping")
- uidmapping = 'cn=Kerberos uid mapping,cn=mapping,cn=sasl,cn=config'
- topology.instance.modify_s(uidmapping, [(ldap.MOD_REPLACE,
'nsSaslMapFilterTemplate', '(cn=\1)')])
- conn0 = ldap.initialize("ldap://%s:%s" % (socket.gethostname(),
INSTANCE_PORT))
- try:
- conn0.sasl_interactive_bind_s('', sasl)
- except Exception as e:
- print("Exception (expected): %s" % type(e).__name__)
- print('Desc ' + str(e['desc']))
- assert isinstance(e, ldap.INVALID_CREDENTIALS)
-
- # undo
- topology.instance.modify_s(uidmapping, [(ldap.MOD_REPLACE,
'nsSaslMapFilterTemplate', '(uid=\1)')])
-
- print("Error case 2. Delete %s from DS" % TEST_USER)
- topology.instance.delete_s(TEST_USER)
- try:
- conn0.sasl_interactive_bind_s('', sasl)
- except Exception as e:
- print("Exception (expected): %s" % type(e).__name__)
- print('Desc ' + str(e['desc']))
- assert isinstance(e, ldap.INVALID_CREDENTIALS)
-
- print("SUCCESS")
-
-
-if __name__ == "__main__":
- CURRENT_FILE = os.path.realpath(__file__)
- pytest.main("-s -v %s" % CURRENT_FILE)
diff --git a/src/lib389/lib389/tools.py b/src/lib389/lib389/tools.py
index edb95b1..f0f4b1c 100644
--- a/src/lib389/lib389/tools.py
+++ b/src/lib389/lib389/tools.py
@@ -857,7 +857,7 @@ class DirSrvTools(object):
for line in hostfp.readlines():
if ipPattern is None:
words = line.split()
- if words[1] == expectedHost:
+ if len(words) >= 2 and words[1] == expectedHost:
return True
else:
if line.find(ipPattern) >= 0:
diff --git a/src/lib389/lib389/topologies.py b/src/lib389/lib389/topologies.py
index 068a24a..ae64828 100644
--- a/src/lib389/lib389/topologies.py
+++ b/src/lib389/lib389/topologies.py
@@ -10,13 +10,19 @@ import os
import logging
import time
+# For hostname detection for GSSAPI tests
+import socket
+
import pytest
from lib389 import DirSrv
from lib389.nss_ssl import NssSsl
from lib389.utils import generate_ds_params
from lib389.replica import Replicas
-from lib389._constants import (args_instance, SER_HOST, SER_PORT, SER_SERVERID_PROP,
SER_CREATION_SUFFIX,
+from lib389.mit_krb5 import MitKrb5
+from lib389.saslmap import SaslMappings
+
+from lib389._constants import (SER_HOST, SER_PORT, SER_SERVERID_PROP,
SER_CREATION_SUFFIX,
SER_SECURE_PORT, ReplicaRole, DEFAULT_SUFFIX, REPLICA_ID,
SER_LDAP_URL)
@@ -61,7 +67,8 @@ def create_topology(topo_dict):
# Also, we need to keep in mind that the function returns
# SER_SECURE_PORT and REPLICA_ID that are not used in
# the instance creation here.
- args_instance[SER_HOST] = instance_data[SER_HOST]
+ # args_instance[SER_HOST] = instance_data[SER_HOST]
+ args_instance = {}
args_instance[SER_PORT] = instance_data[SER_PORT]
args_instance[SER_SECURE_PORT] = instance_data[SER_SECURE_PORT]
args_instance[SER_SERVERID_PROP] = instance_data[SER_SERVERID_PROP]
@@ -198,6 +205,68 @@ def topology_st(request):
return topology
+gssapi_ack = pytest.mark.skipif(not os.environ.get('GSSAPI_ACK', False),
reason="GSSAPI tests may damage system configuration.")
+
+(a)pytest.fixture(scope="module")
+def topology_st_gssapi(request):
+ """Create a DS standalone instance with GSSAPI enabled.
+
+ This will alter the instance to remove the secure port, to allow
+ GSSAPI to function.
+ """
+ hostname = socket.gethostname().split('.', 1)
+
+ # Assert we have a domain setup in some kind.
+ assert len(hostname) == 2
+
+ REALM = hostname[1].upper()
+
+ topology = create_topology({ReplicaRole.STANDALONE: 1})
+
+ # Fix the hostname.
+ topology.standalone.host = socket.gethostname()
+
+ krb = MitKrb5(realm=REALM, debug=DEBUGGING)
+
+ # Destroy existing realm.
+ if krb.check_realm():
+ krb.destroy_realm()
+ krb.create_realm()
+
+ # Now add krb to our instance.
+ krb.create_principal(principal='ldap/%s' % topology.standalone.host)
+ krb.create_keytab(principal='ldap/%s' % topology.standalone.host,
keytab='/etc/krb5.keytab')
+ os.chown('/etc/krb5.keytab', topology.standalone.get_user_uid(),
topology.standalone.get_group_gid())
+
+ # Add sasl mappings
+ saslmappings = SaslMappings(topology.standalone)
+ saslmappings.create(properties={
+ 'cn': 'suffix map',
+ # Don't add the realm due to a SASL bug
+ # 'nsSaslMapRegexString': '\\(.*\\)@%s' % self.realm,
+ 'nsSaslMapRegexString': '\\(.*\\)',
+ 'nsSaslMapBaseDNTemplate': topology.standalone.creation_suffix,
+ 'nsSaslMapFilterTemplate': '(uid=\\1)'
+ })
+ topology.standalone.realm = krb
+
+ topology.standalone.config.set('nsslapd-localhost',
topology.standalone.host)
+
+ topology.standalone.sslport = None
+
+ topology.standalone.restart()
+
+ def fin():
+ if DEBUGGING:
+ topology.standalone.stop()
+ else:
+ topology.standalone.delete()
+ krb.destroy_realm()
+
+ request.addfinalizer(fin)
+
+ return topology
+
@pytest.fixture(scope="module")
def topology_i2(request):
@@ -338,7 +407,8 @@ def topology_m1h1c1(request):
instance = DirSrv(verbose=True)
else:
instance = DirSrv(verbose=False)
- args_instance[SER_HOST] = instance_data[SER_HOST]
+ args_instance = {}
+ # args_instance[SER_HOST] = instance_data[SER_HOST]
args_instance[SER_PORT] = instance_data[SER_PORT]
args_instance[SER_SECURE_PORT] = instance_data[SER_SECURE_PORT]
args_instance[SER_SERVERID_PROP] = instance_data[SER_SERVERID_PROP]
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.