mirror of
https://github.com/kakwa/ldapcherry
synced 2024-11-25 18:54:29 +01:00
adding methods add_user and del_user
* adding add_user * adding del_user * adding unit tests * adding configuration parameters for adding users
This commit is contained in:
parent
0f6e0c7cab
commit
a1c7a529d8
@ -68,7 +68,7 @@ roles.file = '/etc/ldapcherry/roles.yml'
|
|||||||
|
|
||||||
ldap.module = 'ldapcherry.backend.backendLdap'
|
ldap.module = 'ldapcherry.backend.backendLdap'
|
||||||
ldap.groupdn = 'ou=group,dc=example,dc=com'
|
ldap.groupdn = 'ou=group,dc=example,dc=com'
|
||||||
ldap.userdn = 'ou=group,dc=example,dc=com'
|
ldap.userdn = 'ou=people,dc=example,dc=com'
|
||||||
ldap.binddn = 'cn=ldapcherry,dc=example,dc=com'
|
ldap.binddn = 'cn=ldapcherry,dc=example,dc=com'
|
||||||
ldap.password = 'password'
|
ldap.password = 'password'
|
||||||
ldap.uri = 'ldaps://ldap.ldapcherry.org'
|
ldap.uri = 'ldaps://ldap.ldapcherry.org'
|
||||||
@ -79,6 +79,7 @@ ldap.user_filter_tmpl = '(uid=%(username)s)'
|
|||||||
ldap.group_filter_tmpl = '(member=%(username)s)'
|
ldap.group_filter_tmpl = '(member=%(username)s)'
|
||||||
ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))'
|
ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))'
|
||||||
ldap.objectclasses = 'top, person, organizationalPerson, user'
|
ldap.objectclasses = 'top, person, organizationalPerson, user'
|
||||||
|
ldap.dn_user_attr = 'uid'
|
||||||
ldap.timeout = 1
|
ldap.timeout = 1
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,8 +7,16 @@
|
|||||||
|
|
||||||
import cherrypy
|
import cherrypy
|
||||||
import ldap
|
import ldap
|
||||||
|
import ldap.modlist as modlist
|
||||||
import logging
|
import logging
|
||||||
import ldapcherry.backend
|
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):
|
class Backend(ldapcherry.backend.Backend):
|
||||||
|
|
||||||
@ -28,14 +36,20 @@ class Backend(ldapcherry.backend.Backend):
|
|||||||
self.user_filter_tmpl = self.get_param('user_filter_tmpl')
|
self.user_filter_tmpl = self.get_param('user_filter_tmpl')
|
||||||
self.group_filter_tmpl = self.get_param('group_filter_tmpl')
|
self.group_filter_tmpl = self.get_param('group_filter_tmpl')
|
||||||
self.search_filter_tmpl = self.get_param('search_filter_tmpl')
|
self.search_filter_tmpl = self.get_param('search_filter_tmpl')
|
||||||
self.objectclasses = self.get_param('objectclasses')
|
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 = []
|
self.attrlist = []
|
||||||
for a in attrslist:
|
for a in attrslist:
|
||||||
|
self.attrlist.append(self._str(a))
|
||||||
|
|
||||||
|
def _str(self, s):
|
||||||
try:
|
try:
|
||||||
self.attrlist.append(str(a))
|
return str(s)
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
tmp = unicode(a).encode('unicode_escape')
|
return unicode(s).encode('unicode_escape')
|
||||||
self.attrlist.append(tmp)
|
|
||||||
|
|
||||||
def auth(self, username, password):
|
def auth(self, username, password):
|
||||||
|
|
||||||
@ -61,11 +75,47 @@ class Backend(ldapcherry.backend.Backend):
|
|||||||
def rm_from_group(self,username):
|
def rm_from_group(self,username):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def add_user(self, username):
|
def add_user(self, attrs):
|
||||||
pass
|
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(
|
||||||
|
logging.ERROR,
|
||||||
|
"Configuration error, " + desc + ", " + info,
|
||||||
|
)
|
||||||
|
raise e
|
||||||
|
except ldap.INSUFFICIENT_ACCESS as e:
|
||||||
|
info = e[0]['info']
|
||||||
|
desc = e[0]['desc']
|
||||||
|
self._logger(
|
||||||
|
logging.ERROR,
|
||||||
|
"Access error, " + desc + ", " + info,
|
||||||
|
)
|
||||||
|
raise e
|
||||||
|
except ldap.ALREADY_EXISTS as e:
|
||||||
|
desc = e[0]['desc']
|
||||||
|
self._logger(
|
||||||
|
logging.ERROR,
|
||||||
|
"adding user failed, " + desc,
|
||||||
|
)
|
||||||
|
raise e
|
||||||
|
|
||||||
def del_user(self, username):
|
def del_user(self, username):
|
||||||
pass
|
ldap_client = self._bind()
|
||||||
|
dn = self.get_user(username, False)
|
||||||
|
if not dn is None:
|
||||||
|
ldap_client.delete_s(dn)
|
||||||
|
else:
|
||||||
|
raise DelUserDontExists(username)
|
||||||
|
|
||||||
def _bind(self):
|
def _bind(self):
|
||||||
ldap_client = self._connect()
|
ldap_client = self._connect()
|
||||||
|
@ -79,6 +79,7 @@ ldap.user_filter_tmpl = '(uid=%(username)s)'
|
|||||||
ldap.group_filter_tmpl = '(member=%(userdn)s)'
|
ldap.group_filter_tmpl = '(member=%(userdn)s)'
|
||||||
ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))'
|
ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))'
|
||||||
ldap.objectclasses = 'top, person, organizationalPerson, user'
|
ldap.objectclasses = 'top, person, organizationalPerson, user'
|
||||||
|
ldap.dn_user_attr = 'uid'
|
||||||
ldap.timeout = 1
|
ldap.timeout = 1
|
||||||
|
|
||||||
ad.module = 'ldapcherry.backend.backendSamba4'
|
ad.module = 'ldapcherry.backend.backendSamba4'
|
||||||
|
@ -8,10 +8,10 @@ import pytest
|
|||||||
import sys
|
import sys
|
||||||
from sets import Set
|
from sets import Set
|
||||||
from ldapcherry.backend.backendLdap import Backend
|
from ldapcherry.backend.backendLdap import Backend
|
||||||
from ldapcherry import syslog_error
|
|
||||||
from ldapcherry.exceptions import *
|
from ldapcherry.exceptions import *
|
||||||
import cherrypy
|
import cherrypy
|
||||||
from ldap import SERVER_DOWN
|
import logging
|
||||||
|
import ldap
|
||||||
|
|
||||||
cfg = {
|
cfg = {
|
||||||
'module' : 'ldapcherry.backend.ldap',
|
'module' : 'ldapcherry.backend.ldap',
|
||||||
@ -26,9 +26,14 @@ cfg = {
|
|||||||
'user_filter_tmpl' : '(uid=%(username)s)',
|
'user_filter_tmpl' : '(uid=%(username)s)',
|
||||||
'group_filter_tmpl' : '(member=%(userdn)s)',
|
'group_filter_tmpl' : '(member=%(userdn)s)',
|
||||||
'search_filter_tmpl' : '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))',
|
'search_filter_tmpl' : '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))',
|
||||||
'objectclasses' : 'top, person, organizationalPerson, user',
|
'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
|
cherrypy.log.error = syslog_error
|
||||||
attr = ['shéll', 'shell', 'cn', 'uid', 'uidNumber', 'gidNumber', 'home', 'userPassword', 'givenName', 'email', 'sn']
|
attr = ['shéll', 'shell', 'cn', 'uid', 'uidNumber', 'gidNumber', 'home', 'userPassword', 'givenName', 'email', 'sn']
|
||||||
|
|
||||||
@ -61,7 +66,7 @@ class TestError(object):
|
|||||||
ldapc = inv._connect()
|
ldapc = inv._connect()
|
||||||
try:
|
try:
|
||||||
ldapc.simple_bind_s(inv.binddn, inv.bindpassword)
|
ldapc.simple_bind_s(inv.binddn, inv.bindpassword)
|
||||||
except SERVER_DOWN as e:
|
except ldap.SERVER_DOWN as e:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise AssertionError("expected an exception")
|
raise AssertionError("expected an exception")
|
||||||
@ -75,7 +80,7 @@ class TestError(object):
|
|||||||
ldapc = inv._connect()
|
ldapc = inv._connect()
|
||||||
try:
|
try:
|
||||||
ldapc.simple_bind_s(inv.binddn, inv.bindpassword)
|
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'
|
assert e[0]['info'] == 'TLS: hostname does not match CN in peer certificate'
|
||||||
|
|
||||||
# def testConnectSSLNoCheck(self):
|
# def testConnectSSLNoCheck(self):
|
||||||
@ -116,8 +121,61 @@ class TestError(object):
|
|||||||
expected = ('cn=John Watson,ou=People,dc=example,dc=org', {'uid': ['jwatson'], 'cn': ['John Watson'], 'sn': ['watson']})
|
expected = ('cn=John Watson,ou=People,dc=example,dc=org', {'uid': ['jwatson'], 'cn': ['John Watson'], 'sn': ['watson']})
|
||||||
assert ret == expected
|
assert ret == expected
|
||||||
|
|
||||||
def testSearchtUser(self):
|
def testSearchUser(self):
|
||||||
inv = Backend(cfg, cherrypy.log, 'ldap', attr)
|
inv = Backend(cfg, cherrypy.log, 'ldap', attr)
|
||||||
ret = inv.search('smith')
|
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']})]
|
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
|
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")
|
||||||
|
@ -7,7 +7,7 @@ olcSuffix: dc=example,dc=org
|
|||||||
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou
|
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou
|
||||||
s auth by dn="cn=admin,dc=example,dc=org" write by * none
|
s auth by dn="cn=admin,dc=example,dc=org" write by * none
|
||||||
olcAccess: {1}to dn.base="" by * read
|
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
|
olcLastMod: TRUE
|
||||||
olcRootDN: cn=admin,dc=example,dc=org
|
olcRootDN: cn=admin,dc=example,dc=org
|
||||||
olcRootPW: {SSHA}Fp+rSxe5eFsj0DGITJts4DwdSDFDZG9P
|
olcRootPW: {SSHA}Fp+rSxe5eFsj0DGITJts4DwdSDFDZG9P
|
||||||
|
Loading…
Reference in New Issue
Block a user