From 8d7faa398ff2cec41001e7c3cc069ced8deb1d8a Mon Sep 17 00:00:00 2001 From: Nico von Geyso Date: Mon, 17 Sep 2012 11:06:08 +0200 Subject: added basic account service functionality To auth, register, update or delete an account you have to use the AccountService class. A basic usage could be the following: # Simple auth service = AccountService(LDAP_HOST, LDAP_BASE_DN, LDAP_ADMIN_USER, LDAP_ADMIN_PASS) acc = service.auth('test', 'secret') # Authenticate against some credentials print('Mail: %s' % acc.mail) # Account creation, updating and deletion a = Account('foo', 'foo@bar.de', password='foobar') service.register(a) # create a.mail = 'bar@foo.de' service.update(a) # update service.delete(a.uid) # deletete --- account.py | 227 ++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 148 insertions(+), 79 deletions(-) (limited to 'account.py') diff --git a/account.py b/account.py index 76e3bf8..46356d5 100644 --- a/account.py +++ b/account.py @@ -1,84 +1,153 @@ # -*- coding: utf-8 -*- import ldap -import sys -#LDAP_HOST = 'ldaps://bernd:6336' -LDAP_HOST = 'ldap://bernd:3889' -LDAP_BASE_DN = 'dc=nodomain' -USER = 'cn=admin,dc=nodomain' -PASS = 'blubb' - -class Account(object): - def __init__(self, ldap_host, base_dn, user, password): - - self.con = ldap.initialize(ldap_host) - - self.base_dn = base_dn - - self.con.version = ldap.VERSION3 - self.con.start_tls_s() - - self.con.simple_bind(user, password) - - - def list(self, *args, **kwargs): - return self.con.search_s( - self.base_dn, ldap.SCOPE_SUBTREE, *args, **kwargs - ) - - - def register(self, name, attr): - dn = 'uid=%s,%s' % (name, self.base_dn) - try: - self.con.add_s(dn, attr) - except: - return False - - return True - - - def modify(self, name, attr): - try: - dn = self.find(name)[0] - self.con.modify_s(dn, attr) - except: - return False - - return True - - - def find(self, name, *args, **kwargs): - try: - dn = 'uid=%s,%s' % (name, self.base_dn) - return self.con.search_s( - dn, ldap.SCOPE_SUBTREE, *args, **kwargs - )[0] - except: - pass - - return None - - - - def delete(self, name): - try: - dn = self.find(name)[0] - self.con.delete_s(dn) - except: - return False - return True - - -a = Account(LDAP_HOST, LDAP_BASE_DN, USER, PASS) -#print(a.register('test6', -# [('objectClass', 'account'),('uid','test6')] -#)) -#print(a.list()) -#a.delete('test3') -#print(a.find('test3')) -#print(a.list()) -#print("--") -a.modify('test2', [(ldap.MOD_ADD, 'description','ldap ist_scheisse')]) -print(a.list()) +LDAP_HOST = 'ldap://localhost' +LDAP_BASE_DN = 'dc=nodomain,dc=local' +LDAP_ADMIN_USER = 'root' +LDAP_ADMIN_PASS = 'root' + + + +class AccountService: + """ + To simplify account management through ldap this class can be used. + """ + def __init__(self, ldap_host, base_dn, admin_user, admin_pass): + self.ldap_host = ldap_host + self.base_dn = base_dn + self.admin_cn = 'cn=%s,%s' % (admin_user, self.base_dn) + self.admin_pass = admin_pass + self.binded = False + + self.connection = ldap.initialize(ldap_host) + self.connection.version = ldap.VERSION3 + + + def auth(self, username, password): + """ + Tries to authenticate a user with a given password. If the + authentication is successful an Account object will be returned. + """ + dn = 'uid=%s,%s' % (username, self.base_dn) + self._bind(dn, password) + dn, data = self.connection.search_s(dn, ldap.SCOPE_BASE)[0] + acc = Account(dn, data['cn'][0], data['sn'][0]) + self._unbind() + return acc + + + def register(self, account): + """ + Persists an account in the ldap backend + """ + self._bind(self.admin_cn, self.admin_pass) + dn = 'uid=%s,%s' % (account.uid, self.base_dn) + self.connection.add_s(dn, account.to_ldif()) + account.dn = dn + self._alter_passwords(account) + self._unbind() + + + def update(self, account): + """ + Updates account informations like passwords or email. + """ + self._bind(self.admin_cn, self.admin_pass) + attr = [(ldap.MOD_REPLACE, 'mail', account.mail)] + dn = 'uid=%s,%s' % (account.uid, self.base_dn) + self.connection.modify_s(dn, attr) + self._alter_passwords(account) + self._unbind() + + + def delete(self, uid): + """ + Deletes an account permanently. + """ + self._bind(self.admin_cn, self.admin_pass) + dn = 'uid=%s,%s' % (uid, self.base_dn) + self.connection.delete_s(dn) + self._unbind() + + + def _bind(self, dn, password): + if not self.binded: + self.connection.simple_bind_s(dn, password) + self.binded = True + + + def _unbind(self): + if self.binded: + self.connection.unbind_s() + self.binded = False + + + def _alter_passwords(self, account): + if self.binded and 'root' in account.passwords: + attr = [ + (ldap.MOD_REPLACE, 'userPassword', account.passwords['root']) + ] + dn = 'uid=%s,%s' % (account.uid, self.base_dn) + self.connection.modify_s(dn, attr) + + + +class Account: + """ + An Account represents a complex ldap tree entry for spline users. + For each service a spline user can have a different password. + """ + def __init__(self, uid, mail, services = [], dn = None, password = None): + self.uid = uid + self.mail = mail + self.services = services + self.dn = dn + self.passwords = {} + + if password: + self.change_password(password) + + + def __str__(self): + return "Account(uid=%s)" % self.uid + + + def change_password(self, new_password, service = None): + """ + Changes a password for a given service. You have to use the Ldap class + to make the changes permanent. If no service is given, the root + password will be changed. + """ + if not service: + service = 'root' + + self.passwords[service] = new_password + + + def change_email(self, new_mail): + """ + Changes the mail address of an account. You have to use the Ldap class + to make changes permanent. + """ + self.mail = new_mail + + + def to_ldif(self): + """ + Returns basic account data as a list of tuples (ldif format) + """ + return [ + ('objectClass', ['top','inetOrgPerson']), ('uid',self.uid), + ('sn', self.uid), ('cn', self.uid), ('mail', self.mail) + ] + + +service = AccountService(LDAP_HOST, LDAP_BASE_DN, LDAP_ADMIN_USER, LDAP_ADMIN_PASS) +#print(service.auth('testaccountt6', 'secret')) +#service.delete('testaccountt5') +#a = Account('testaccountt6', 'test@test.de', password='secret') +a = Account('testaccount4', 'mail@mail.de', password='secret') +service.update(a) +#print(service.register(a)) -- cgit v1.2.3-1-g7c22