diff --git a/conf/ldapcherry.ini b/conf/ldapcherry.ini index b2a00f9..ebc1da7 100644 --- a/conf/ldapcherry.ini +++ b/conf/ldapcherry.ini @@ -67,8 +67,8 @@ roles.file = '/etc/ldapcherry/roles.yml' [backends] ldap.module = 'ldapcherry.backend.backendLdap' -ldap.groupdn = 'ou=group,dc=example,dc=com' -ldap.userdn = 'ou=group,dc=example,dc=com' +ldap.groupdn = 'ou=groups,dc=example,dc=com' +ldap.userdn = 'ou=people,dc=example,dc=com' ldap.binddn = 'cn=ldapcherry,dc=example,dc=com' ldap.password = 'password' ldap.uri = 'ldaps://ldap.ldapcherry.org' @@ -76,7 +76,10 @@ ldap.ca = '/etc/dnscherry/TEST-cacert.pem' ldap.starttls = 'on' ldap.checkcert = 'off' ldap.user_filter_tmpl = '(uid=%(username)s)' -ldap.group_filter_tmpl = '(member=%(userdn)s)' +ldap.group_filter_tmpl = '(member=%(username)s)' +ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))' +ldap.objectclasses = 'top, person, organizationalPerson, user' +ldap.dn_user_attr = 'uid' ldap.timeout = 1 diff --git a/ldapcherry/__init__.py b/ldapcherry/__init__.py index a263ec7..a104048 100644 --- a/ldapcherry/__init__.py +++ b/ldapcherry/__init__.py @@ -76,6 +76,21 @@ class LdapCherry(object): else: raise MissingParameter(section, key) + + def _get_groups(self, username): + ret = {} + for b in self.backends: + ret[b] = self.backends[b].get_groups(username) + return ret + + def _get_roles(self, username): + groups = self._get_groups(username) + return self.roles.get_roles(groups) + + def _is_admin(self, username): + roles = self._get_roles(username) + return self.roles.is_admin(roles['roles']) + def _check_backends(self): backends = self.backends_params.keys() for b in self.roles.get_backends(): @@ -114,6 +129,27 @@ class LdapCherry(object): except: raise BackendModuleInitFail(module) + + def _init_auth(self, config): + self.auth_mode = self._get_param('auth', 'auth.mode', config) + if self.auth_mode in ['and', 'or', 'none']: + pass + elif self.auth_mode == 'custom': + # load custom auth module + auth_module = self._get_param('auth', 'auth.module', config) + auth = __import__(auth_module, globals(), locals(), ['Auth'], -1) + self.auth = auth.Auth(config['auth'], cherrypy.log) + else: + raise WrongParamValue('auth.mode', 'auth', ['and', 'or', 'none', 'custom']) + + self.roles_file = self._get_param('roles', 'roles.file', config) + cherrypy.log.error( + msg = "loading roles file <%(file)s>" % { 'file': self.roles_file }, + severity = logging.DEBUG + ) + self.roles = Roles(self.roles_file) + + def _set_access_log(self, config, level): access_handler = self._get_param('global', 'log.access_handler', config, 'syslog') @@ -201,6 +237,27 @@ class LdapCherry(object): else: return logging.INFO + def _auth(self, user, password): + if self.auth_mode == 'none': + return {'connected': True, 'isadmin': True} + elif self.auth_mode == 'and': + ret1 = True + for b in self.backends: + ret1 = self.backends[b].auth(user, password) and ret1 + elif self.auth_mode == 'or': + ret1 = False + for b in self.backends: + ret1 = self.backends[b].auth(user, password) or ret1 + elif self.auth_mode == 'custom': + ret1 = self.auth.auth(user, password) + else: + raise Exception() + if not ret1: + return {'connected': False, 'isadmin': False} + else: + isadmin = self._is_admin(user) + return {'connected': True, 'isadmin': isadmin} + def reload(self, config = None): """ load/reload the configuration """ @@ -229,18 +286,14 @@ class LdapCherry(object): self.temp_login = self.temp_lookup.get_template('login.tmpl') - self.roles_file = self._get_param('roles', 'roles.file', config) - cherrypy.log.error( - msg = "loading roles file <%(file)s>" % { 'file': self.roles_file }, - severity = logging.DEBUG - ) - self.roles = Roles(self.roles_file) + self._init_auth(config) self.attributes_file = self._get_param('attributes', 'attributes.file', config) cherrypy.log.error( msg = "loading attributes file <%(file)s>" % { 'file': self.attributes_file }, severity = logging.DEBUG ) + self.attributes = Attributes(self.attributes_file) cherrypy.log.error( @@ -308,6 +361,21 @@ class LdapCherry(object): message = 'Example warning' return render_error(alert, message) + def _check_auth(self, must_admin): + if not 'connected' in cherrypy.session or not cherrypy.session['connected']: + raise cherrypy.HTTPRedirect("/signin") + if cherrypy.session['connected'] and \ + not cherrypy.session['isadmin']: + if must_admin: + raise cherrypy.HTTPError("403 Forbidden", "You are not allowed to access this resource.") + else: + return + if cherrypy.session['connected'] and \ + cherrypy.session['isadmin']: + return + else: + raise cherrypy.HTTPRedirect("/signin") + @cherrypy.expose def signin(self): """simple signin page @@ -318,7 +386,11 @@ class LdapCherry(object): def login(self, login, password): """login page """ - if self.auth.check_credentials(login, password): + auth = self._auth(login, password) + cherrypy.session['isadmin'] = auth['isadmin'] + cherrypy.session['connected'] = auth['connected'] + + if auth['connected']: message = "login success for user '%(user)s'" % { 'user': login } @@ -342,44 +414,54 @@ class LdapCherry(object): def logout(self): """ logout page """ - user = self.auth.end_session() + sess = cherrypy.session + username = sess.get(SESSION_KEY, None) + sess[SESSION_KEY] = None + if username: + cherrypy.request.login = None + message = "user '%(user)s' logout" % { - 'user': user + 'user': username } cherrypy.log.error( msg = message, severity = logging.INFO ) - raise cherrypy.HTTPRedirect("/signin") @cherrypy.expose def index(self, **params): """main page rendering """ + self._check_auth(must_admin=False) pass @cherrypy.expose def searchuser(self): """ search user page """ + self._check_auth(must_admin=True) pass @cherrypy.expose def adduser(self): """ add user page """ + self._check_auth(must_admin=True) pass @cherrypy.expose def removeuser(self): """ remove user page """ + self._check_auth(must_admin=True) pass @cherrypy.expose def modifyuser(self): """ modify user page """ + self._check_auth(must_admin=True) pass @cherrypy.expose def modifyself(self): """ self modify user page """ + self._check_auth(must_admin=False) pass diff --git a/ldapcherry/backend/backendLdap.py b/ldapcherry/backend/backendLdap.py index b7e411f..2dc9de2 100644 --- a/ldapcherry/backend/backendLdap.py +++ b/ldapcherry/backend/backendLdap.py @@ -7,8 +7,16 @@ import cherrypy import ldap +import ldap.modlist as modlist import logging import ldapcherry.backend +import re + +class DelUserDontExists(Exception): + def __init__(self, user): + self.user = user + self.log = "cannot remove user, user <%(user)s> does not exist" % { 'user' : user} + class Backend(ldapcherry.backend.Backend): @@ -26,17 +34,26 @@ class Backend(ldapcherry.backend.Backend): self.userdn = self.get_param('userdn') self.groupdn = self.get_param('groupdn') self.user_filter_tmpl = self.get_param('user_filter_tmpl') + self.group_filter_tmpl = self.get_param('group_filter_tmpl') + self.search_filter_tmpl = self.get_param('search_filter_tmpl') + self.dn_user_attr = self.get_param('dn_user_attr') + self.objectclasses = [] + for o in re.split('\W+', self.get_param('objectclasses')): + self.objectclasses.append(self._str(o)) + self.attrlist = [] for a in attrslist: + self.attrlist.append(self._str(a)) + + def _str(self, s): try: - self.attrlist.append(str(a)) + return str(s) except UnicodeEncodeError: - tmp = unicode(a).encode('unicode_escape') - self.attrlist.append(tmp) + return unicode(s).encode('unicode_escape') def auth(self, username, password): - binddn = self.get_user(username, False) + binddn = self._get_user(username, False) if not binddn is None: ldap_client = self._connect() try: @@ -55,51 +72,150 @@ class Backend(ldapcherry.backend.Backend): def set_attrs(self, attrs): pass - def rm_from_group(self,username): + def rm_from_group(self, username): pass - def add_user(self, username): - pass + def get_groups(self, username): + userdn = self._get_user(username, False) + + searchfilter = self.group_filter_tmpl % { + 'userdn': userdn, + 'username': username + } + + groups = self._search(searchfilter, None, self.groupdn) + ret = [] + for entry in groups: + ret.append(entry[0]) + return ret + + def add_user(self, attrs): + ldap_client = self._bind() + attrs_str = {} + for a in attrs: + attrs_str[self._str(a)] = self._str(attrs[a]) + attrs_str['objectClass'] = self.objectclasses + dn = self.dn_user_attr + '=' + attrs[self.dn_user_attr] + ',' + self.userdn + ldif = modlist.addModlist(attrs_str) + try: + ldap_client.add_s(dn,ldif) + except ldap.OBJECT_CLASS_VIOLATION as e: + info = e[0]['info'] + desc = e[0]['desc'] + self._logger( + severity = logging.ERROR, + msg = "Configuration error, " + desc + ", " + info, + ) + raise e + except ldap.INSUFFICIENT_ACCESS as e: + info = e[0]['info'] + desc = e[0]['desc'] + self._logger( + severity = logging.ERROR, + msg = "Access error, " + desc + ", " + info, + ) + raise e + except ldap.ALREADY_EXISTS as e: + desc = e[0]['desc'] + self._logger( + severity = logging.ERROR, + msg = "adding user failed, " + desc, + ) + raise e def del_user(self, username): - pass - - def get_user(self, username, attrs=True): - if attrs: - a = self.attrlist + ldap_client = self._bind() + dn = self._get_user(username, False) + if not dn is None: + ldap_client.delete_s(dn) else: - a = None + raise DelUserDontExists(username) + + def _bind(self): ldap_client = self._connect() try: ldap_client.simple_bind_s(self.binddn, self.bindpassword) except ldap.INVALID_CREDENTIALS as e: self._logger( - logging.ERROR, - "Configuration error, wrong credentials, unable to connect to ldap with '" + self.binddn + "'", + severity = logging.ERROR, + msg = "Configuration error, wrong credentials, unable to connect to ldap with '" + self.binddn + "'", ) - #raise cherrypy.HTTPError("500", "Configuration Error, contact administrator") + ldap_client.unbind_s() raise e except ldap.SERVER_DOWN as e: self._logger( - logging.ERROR, - "Unable to contact ldap server '" + self.uri + "', check 'auth.ldap.uri' and ssl/tls configuration", + severity = logging.ERROR, + msg = "Unable to contact ldap server '" + self.uri + "', check 'auth.ldap.uri' and ssl/tls configuration", ) + ldap_client.unbind_s() raise e + return ldap_client + + + def _search(self, searchfilter, attrs, basedn): + ldap_client = self._bind() + try: + r = ldap_client.search_s(basedn, + ldap.SCOPE_SUBTREE, + searchfilter, + attrlist=attrs + ) + except ldap.FILTER_ERROR as e: + self._logger( + severity = logging.ERROR, + msg = "Bad search filter, check '" + self.backend_name + ".*_filter_tmpl' params", + ) + ldap_client.unbind_s() + raise e + except ldap.NO_SUCH_OBJECT as e: + self._logger( + severity = logging.ERROR, + msg = "Search DN '" + basedn \ + + "' doesn't exist, check '" \ + + self.backend_name + ".userdn' or '" \ + + self.backend_name + ".groupdn'", + ) + ldap_client.unbind_s() + raise e + + ldap_client.unbind_s() + return r + + + def search(self, searchstring): + + searchfilter = self.search_filter_tmpl % { + 'searchstring': searchstring + } + + return self._search(searchfilter, None, self.userdn) + + def get_user(self, username): + ret = {} + attrs_tmp = self._get_user(username)[1] + for attr in attrs_tmp: + value_tmp = attrs_tmp[attr] + if len(value_tmp) == 1: + ret[attr] = value_tmp[0] + else: + ret[attr] = value_tmp + return ret + + def _get_user(self, username, attrs=True): + if attrs: + a = self.attrlist + else: + a = None user_filter = self.user_filter_tmpl % { 'username': username } - r = ldap_client.search_s(self.userdn, - ldap.SCOPE_SUBTREE, - user_filter, - attrlist=a - ) + r = self._search(user_filter, a, self.userdn) + if len(r) == 0: - ldap_client.unbind_s() return None - ldap_client.unbind_s() if attrs: dn_entry = r[0] else: @@ -127,8 +243,8 @@ class Backend(ldapcherry.backend.Backend): ldap_client.start_tls_s() except ldap.OPERATIONS_ERROR as e: self._logger( - logging.ERROR, - "cannot use starttls with ldaps:// uri (uri: " + self.uri + ")", + severity = logging.ERROR, + msg = "cannot use starttls with ldaps:// uri (uri: " + self.uri + ")", ) raise e #raise cherrypy.HTTPError("500", "Configuration Error, contact administrator") diff --git a/ldapcherry/exceptions.py b/ldapcherry/exceptions.py index bd612e6..27d62b4 100644 --- a/ldapcherry/exceptions.py +++ b/ldapcherry/exceptions.py @@ -5,6 +5,8 @@ # LdapCherry # Copyright (c) 2014 Carpentier Pierre-Francois +import string + class MissingParameter(Exception): def __init__(self, section, key): self.section = section @@ -69,6 +71,14 @@ class BackendModuleInitFail(Exception): self.module = module self.log = "fail to init module <%(module)s>" % {'module': module} +class WrongParamValue(Exception): + def __init__(self, param, section, possible_values): + self.possible_values = possible_values + self.section = section + self.param = param + possible_values_str = string.join(possible_values, ', ') + self.log = "wrong value for param <%(param)s> in section <%(section)s>, possible values are [%(values)s]" % {'param': param, 'section': section, 'values': possible_values_str} + class WrongAttributeType(Exception): def __init__(self, key, section, ymlfile): self.key = key diff --git a/misc/debug_ldapbackend.py b/misc/debug_ldapbackend.py index 047beea..5cc9f1a 100644 --- a/misc/debug_ldapbackend.py +++ b/misc/debug_ldapbackend.py @@ -11,24 +11,49 @@ from ldapcherry.backend.backendLdap import Backend from ldapcherry import syslog_error from ldapcherry.exceptions import * import cherrypy +import logging from ldap import SERVER_DOWN cfg = { -'module' : 'ldapcherry.backend.ldap', -'groupdn' : 'ou=group,dc=example,dc=org', -'userdn' : 'ou=People,dc=example,dc=org', -'binddn' : 'cn=dnscherry,dc=example,dc=org', -'password' : 'password', -'uri' : 'ldap://ldap.ldapcherry.org:390', -'ca' : './tests/test_env/etc/ldapcherry/TEST-cacert.pem', -'starttls' : 'off', -'checkcert' : 'off', -'user_filter_tmpl' : '(uid=%(username)s)', -'group_filter_tmpl' : '(member=%(userdn)s)', +'module' : 'ldapcherry.backend.ldap', +'groupdn' : 'ou=Groups,dc=example,dc=org', +'userdn' : 'ou=People,dc=example,dc=org', +'binddn' : 'cn=dnscherry,dc=example,dc=org', +'password' : 'password', +'uri' : 'ldap://ldap.ldapcherry.org:390', +'ca' : './tests/test_env/etc/ldapcherry/TEST-cacert.pem', +'starttls' : 'off', +'checkcert' : 'off', +'user_filter_tmpl' : '(uid=%(username)s)', +'group_filter_tmpl' : '(member=%(userdn)s)', +'search_filter_tmpl' : '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))', +'objectclasses' : 'top, person, organizationalPerson, simpleSecurityObject, posixAccount', +'dn_user_attr' : 'uid', } +def syslog_error(msg='', context='', + severity=logging.INFO, traceback=False): + pass + cherrypy.log.error = syslog_error attr = ['shéll', 'cn', 'uid', 'uidNumber', 'gidNumber', 'home', 'userPassword', 'givenName', 'email', 'sn'] +cherrypy.log.error = syslog_error + inv = Backend(cfg, cherrypy.log, 'ldap', attr) print inv.get_user('jwatson') +print inv.get_groups('jwatson') +print inv.search('smit') +user = { +'uid': 'test', +'sn': 'test', +'cn': 'test', +'userPassword': 'test', +'uidNumber': '42', +'gidNumber': '42', +'homeDirectory': '/home/test/' +} +inv.add_user(user) +print inv.get_user('test') +print inv.get_groups('test') +inv.del_user('test') diff --git a/setup.py b/setup.py index 296caf4..565b047 100755 --- a/setup.py +++ b/setup.py @@ -73,10 +73,13 @@ def get_list_files(basedir, targetdir): return_list.append((os.path.join(targetdir, subpath), files_list)) return return_list +# add static files and templates in the list of thing to deploy resources_files = get_list_files('resources', os.path.join(datarootdir, 'share', 'ldapcherry')) -resources_files.append(( +# add the configuration files if they don't exist +if not os.path.exists(os.path.join(sysconfdir, 'ldapcherry')): + resources_files.append(( os.path.join(sysconfdir, 'ldapcherry'), [ 'conf/ldapcherry.ini', 'conf/attributes.yml', 'conf/roles.yml'] )) @@ -87,7 +90,7 @@ setup( version = '0.0.1', author = 'Pierre-Francois Carpentier', author_email = 'carpentier.pf@gmail.com', - packages = ['ldapcherry'], + packages = ['ldapcherry', 'ldapcherry.backend'], data_files = resources_files, scripts = ['scripts/ldapcherryd'], url = 'https://github.com/kakwa/ldapcherry', diff --git a/tests/cfg/ldapcherry.ini b/tests/cfg/ldapcherry.ini index f157b26..5cc168c 100644 --- a/tests/cfg/ldapcherry.ini +++ b/tests/cfg/ldapcherry.ini @@ -67,8 +67,8 @@ roles.file = './tests/cfg/roles.yml' [backends] ldap.module = 'ldapcherry.backend.backendLdap' -ldap.groupdn = 'ou=group,dc=example,dc=com' -ldap.userdn = 'ou=group,dc=example,dc=com' +ldap.groupdn = 'ou=groups,dc=example,dc=com' +ldap.userdn = 'ou=people,dc=example,dc=com' ldap.binddn = 'cn=dnscherry,dc=example,dc=org' ldap.password = 'password' ldap.uri = 'ldaps://ldap.ldapcherry.org' @@ -77,6 +77,9 @@ ldap.starttls = 'on' ldap.checkcert = 'off' ldap.user_filter_tmpl = '(uid=%(username)s)' ldap.group_filter_tmpl = '(member=%(userdn)s)' +ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))' +ldap.objectclasses = 'top, person, organizationalPerson, user' +ldap.dn_user_attr = 'uid' ldap.timeout = 1 ad.module = 'ldapcherry.backend.backendSamba4' diff --git a/tests/test_BackendLdap.py b/tests/test_BackendLdap.py index f85c9e5..4543976 100644 --- a/tests/test_BackendLdap.py +++ b/tests/test_BackendLdap.py @@ -8,25 +8,32 @@ import pytest import sys from sets import Set from ldapcherry.backend.backendLdap import Backend -from ldapcherry import syslog_error from ldapcherry.exceptions import * import cherrypy -from ldap import SERVER_DOWN +import logging +import ldap cfg = { -'module' : 'ldapcherry.backend.ldap', -'groupdn' : 'ou=group,dc=example,dc=org', -'userdn' : 'ou=People,dc=example,dc=org', -'binddn' : 'cn=dnscherry,dc=example,dc=org', -'password' : 'password', -'uri' : 'ldap://ldap.ldapcherry.org:390', -'ca' : './tests/test_env/etc/ldapcherry/TEST-cacert.pem', -'starttls' : 'off', -'checkcert' : 'off', -'user_filter_tmpl' : '(uid=%(username)s)', -'group_filter_tmpl' : '(member=%(userdn)s)', +'module' : 'ldapcherry.backend.ldap', +'groupdn' : 'ou=groups,dc=example,dc=org', +'userdn' : 'ou=People,dc=example,dc=org', +'binddn' : 'cn=dnscherry,dc=example,dc=org', +'password' : 'password', +'uri' : 'ldap://ldap.ldapcherry.org:390', +'ca' : './tests/test_env/etc/ldapcherry/TEST-cacert.pem', +'starttls' : 'off', +'checkcert' : 'off', +'user_filter_tmpl' : '(uid=%(username)s)', +'group_filter_tmpl' : '(member=%(userdn)s)', +'search_filter_tmpl' : '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))', +'objectclasses' : 'top, person, organizationalPerson, simpleSecurityObject, posixAccount', +'dn_user_attr' : 'uid', } +def syslog_error(msg='', context='', + severity=logging.INFO, traceback=False): + pass + cherrypy.log.error = syslog_error attr = ['shéll', 'shell', 'cn', 'uid', 'uidNumber', 'gidNumber', 'home', 'userPassword', 'givenName', 'email', 'sn'] @@ -59,7 +66,7 @@ class TestError(object): ldapc = inv._connect() try: ldapc.simple_bind_s(inv.binddn, inv.bindpassword) - except SERVER_DOWN as e: + except ldap.SERVER_DOWN as e: return else: raise AssertionError("expected an exception") @@ -73,7 +80,7 @@ class TestError(object): ldapc = inv._connect() try: ldapc.simple_bind_s(inv.binddn, inv.bindpassword) - except SERVER_DOWN as e: + except ldap.SERVER_DOWN as e: assert e[0]['info'] == 'TLS: hostname does not match CN in peer certificate' # def testConnectSSLNoCheck(self): @@ -111,5 +118,70 @@ class TestError(object): def testGetUser(self): inv = Backend(cfg, cherrypy.log, 'ldap', attr) ret = inv.get_user('jwatson') - expected = ('cn=John Watson,ou=People,dc=example,dc=org', {'uid': ['jwatson'], 'cn': ['John Watson'], 'sn': ['watson']}) + expected = {'uid': 'jwatson', 'cn': 'John Watson', 'sn': 'watson'} assert ret == expected + + def testGetUser(self): + inv = Backend(cfg, cherrypy.log, 'ldap', attr) + ret = inv.get_groups('jwatson') + expected = ['cn=itpeople,ou=Groups,dc=example,dc=org'] + assert ret == expected + + def testSearchUser(self): + inv = Backend(cfg, cherrypy.log, 'ldap', attr) + ret = inv.search('smith') + expected = [('cn=Sheri Smith,ou=People,dc=example,dc=org', {'uid': ['ssmith'], 'objectClass': ['inetOrgPerson'], 'carLicense': ['HERCAR 125'], 'sn': ['smith'], 'mail': ['s.smith@example.com', 'ssmith@example.com', 'sheri.smith@example.com'], 'homePhone': ['555-111-2225'], 'cn': ['Sheri Smith']}), ('cn=John Smith,ou=People,dc=example,dc=org', {'uid': ['jsmith'], 'objectClass': ['inetOrgPerson'], 'carLicense': ['HISCAR 125'], 'sn': ['Smith'], 'mail': ['j.smith@example.com', 'jsmith@example.com', 'jsmith.smith@example.com'], 'homePhone': ['555-111-2225'], 'cn': ['John Smith']})] + assert ret == expected + + def testAddUser(self): + inv = Backend(cfg, cherrypy.log, 'ldap', attr) + user = { + 'uid': 'test', + 'sn': 'test', + 'cn': 'test', + 'userPassword': 'test', + 'uidNumber': '42', + 'gidNumber': '42', + 'homeDirectory': '/home/test/' + } + inv.add_user(user) + inv.del_user('test') + + def testAddUserDuplicate(self): + inv = Backend(cfg, cherrypy.log, 'ldap', attr) + user = { + 'uid': 'test', + 'sn': 'test', + 'cn': 'test', + 'uidNumber': '42', + 'userPassword': 'test', + 'gidNumber': '42', + 'homeDirectory': '/home/test/' + } + try: + inv.add_user(user) + inv.add_user(user) + except ldap.ALREADY_EXISTS: + inv.del_user('test') + return + else: + inv.del_user('test') + raise AssertionError("expected an exception") + + def testAddUserMissingMustAttribute(self): + inv = Backend(cfg, cherrypy.log, 'ldap', attr) + user = { + 'uid': 'test', + 'sn': 'test', + 'cn': 'test', + 'userPassword': 'test', + 'gidNumber': '42', + 'homeDirectory': '/home/test/' + } + try: + inv.add_user(user) + except ldap.OBJECT_CLASS_VIOLATION: + return + else: + inv.del_user('test') + raise AssertionError("expected an exception") diff --git a/tests/test_env/deploy.sh b/tests/test_env/deploy.sh index 40c0fd7..e859180 100755 --- a/tests/test_env/deploy.sh +++ b/tests/test_env/deploy.sh @@ -32,7 +32,7 @@ sudo sed -i "s%tools.staticdir.dir.*%tools.staticdir.dir = '`pwd`/resources/stat chown -R openldap:openldap /etc/ldap/ rm /etc/ldap/slapd.d/cn\=config/*mdb* /etc/init.d/slapd restart -ldapadd -H ldap://localhost:390 -x -D "cn=admin,dc=example,dc=org" -f /etc/ldap/content.ldif -w password +ldapadd -c -H ldap://localhost:390 -x -D "cn=admin,dc=example,dc=org" -f /etc/ldap/content.ldif -w password sed -i "s/\(127.0.0.1.*\)/\1 ldap.ldapcherry.org ad.ldapcherry.org/" /etc/hosts df -h diff --git a/tests/test_env/etc/ldap/content.ldif b/tests/test_env/etc/ldap/content.ldif index 5108ed1..98a0682 100644 --- a/tests/test_env/etc/ldap/content.ldif +++ b/tests/test_env/etc/ldap/content.ldif @@ -32,6 +32,18 @@ mail: s.smith@example.com mail: ssmith@example.com mail: sheri.smith@example.com +dn: cn=John Smith,ou=people,dc=example,dc=org +objectclass: inetOrgPerson +cn: John Smith +sn: Smith +uid: jsmith +userpassword: passwordsmith +carlicense: HISCAR 125 +homephone: 555-111-2225 +mail: j.smith@example.com +mail: jsmith@example.com +mail: jsmith.smith@example.com + dn: cn=John Watson,ou=people,dc=example,dc=org objectclass: inetOrgPerson cn: John Watson diff --git a/tests/test_env/etc/ldap/slapd.d/cn=config/olcDatabase={1}hdb.ldif b/tests/test_env/etc/ldap/slapd.d/cn=config/olcDatabase={1}hdb.ldif index e35ae5b..f767ece 100644 --- a/tests/test_env/etc/ldap/slapd.d/cn=config/olcDatabase={1}hdb.ldif +++ b/tests/test_env/etc/ldap/slapd.d/cn=config/olcDatabase={1}hdb.ldif @@ -7,7 +7,7 @@ olcSuffix: dc=example,dc=org olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou s auth by dn="cn=admin,dc=example,dc=org" write by * none olcAccess: {1}to dn.base="" by * read -olcAccess: {2}to * by self write by dn="cn=admin,dc=example,dc=org" write by * read +olcAccess: {2}to * by self write by dn="cn=dnscherry,dc=example,dc=org" write by * read olcLastMod: TRUE olcRootDN: cn=admin,dc=example,dc=org olcRootPW: {SSHA}Fp+rSxe5eFsj0DGITJts4DwdSDFDZG9P