#!/usr/bin/env python import ldap import re from dm.common.utility.loggingManager import LoggingManager from dm.common.exceptions.configurationError import ConfigurationError from dm.common.exceptions.internalError import InternalError from dm.common.exceptions.objectNotFound import ObjectNotFound from dm.common.exceptions.authenticationError import AuthenticationError from dm.common.exceptions.communicationError import CommunicationError from dm.common.exceptions.dmException import DmException class LdapClient: LDAP_ERROR_REGEX_LIST = [ (re.compile('.*No such object.*'),ObjectNotFound), (re.compile('.*'),DmException) ] def __init__(self, serverUrl, adminDn, adminPasswordFile): self.serverUrl = serverUrl self.adminDn = adminDn self.adminPassword = open(adminPasswordFile, 'r').readline().strip() if not self.adminPassword: raise ConfigurationError('LDAP password could not be found in %s file' % adminPasswordFile) self.ldapClient = None # Decorator for all LDAP transactions @classmethod def executeLdapCall(cls, func): def ldapCall(*args, **kwargs): try: result = func(*args, **kwargs) return result except DmException, ex: raise except Exception, ex: error = str(ex) for (pattern,dmExClass) in LdapClient.LDAP_ERROR_REGEX_LIST: if pattern.match(error): raise dmExClass(exception=ex) raise DmException(exception=ex) return ldapCall @classmethod def getLogger(cls): logger = LoggingManager.getInstance().getLogger(cls.__name__) return logger def getLdapClient(self): if self.ldapClient is not None: try: self.ldapClient.simple_bind_s(self.adminDn, self.adminPassword) except Exception, ex: self.getLogger().error('Invalidating LDAP client due to error: %s' % ex) self.unbind(self.ldapClient) self.ldapClient = None if not self.ldapClient: self.ldapClient = self.bind(self.serverUrl, self.adminDn, self.adminPassword) return self.ldapClient @classmethod def bind(cls, serverUrl, adminDn, adminPassword): try: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) ldapClient = ldap.initialize(serverUrl) ldapClient.set_option(ldap.OPT_REFERRALS,0) ldapClient.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3) ldapClient.simple_bind_s(adminDn, adminPassword) cls.getLogger().debug('Successful binding with LDAP DN: %s' % adminDn) return ldapClient except ldap.INVALID_CREDENTIALS, ex: ldapClient.unbind() raise AuthenticationError('Invalid LDAP credentials for admin user %s' % adminDn) except ldap.SERVER_DOWN, ex: raise CommunicationError('Cannot reach LDAP server %s' % serverUrl) except Exception, ex: raise InternalError('Unrecognized exception while binding to LDAP server %s: %s' % (serverUrl, ex)) @classmethod def unbind(cls, ldapClient): try: ldapClient.unbind() except Exception, ex: cls.getLogger().error('Could not unbind LDAP client: %s' % ex) ####################################################################### # Testing. if __name__ == '__main__': pass