[Twisted-Python] advice on asynchronous LDAP?
Hi folks, I'm a newbie writing a twisted server that needs to access an LDAP server. I started by using python-ldap, which worked fine and is well documented, but doesn't seem to have support for a callback mechanism that would make it appropriate for a twisted app. So I switched to ldaptor, which fits the twisted model, but doesn't seem to have much documentation. I'm looking for advice from people who have some familiarity with writing twisted apps that include an LDAP client. Ideally, I'd like to find either: (1) a way to use the standard python-ldap library in a multitasking twisted server (i.e. without busy wait; polling at timed intervals is a possibility but also seems bad), or (2) a hidden trove of ldaptor documentation, or a mailing list or IRC channel where I could ask questions of people who know ldaptor. Any hints in either of these directions would be most appreciated. And if you're not an expert but might be interested in forming a new venue to discuss twisted+LDAP, let me know -- maybe we can set something up. thanks, Shimon Rura
Shimon Rura wrote:
Hi folks,
Hello
I'm a newbie writing a twisted server that needs to access an LDAP server. I started by using python-ldap, which worked fine and is well documented, but doesn't seem to have support for a callback mechanism that would make it appropriate for a twisted app. So I switched to ldaptor, which fits the twisted model, but doesn't seem to have much documentation.
I tried to use it but it worked only with twisted 1.3
I'm looking for advice from people who have some familiarity with writing twisted apps that include an LDAP client. Ideally, I'd like to find either:
(1) a way to use the standard python-ldap library in a multitasking twisted server (i.e. without busy wait; polling at timed intervals is a possibility but also seems bad), or
The way I found was to use python ldap and deferToThread. This is not really in the "asynchronous spirit of twisted " but it works. Here an example I used to make a small sendmail X map lookup: from twisted.application import internet, service from twisted.internet import protocol,reactor, defer, threads from twisted.internet.protocol import Protocol from twisted.protocols import basic import ldap class MapProtocol(Protocol): def dataReceived(self, Mel): d = threads.deferToThread(self.factory._lire_annuaire_ldap,Mel) d.addCallback(self._cb) d.addErrback(self._eb) def _cb(self, result): self.transport.write(result) def _eb(self, error): print error self.transport.loseConnection() class MapFactory(protocol.ServerFactory): protocol = MapProtocol def __init__(self, servers,who, cred, mydomains, dictstatus): # directory self.ldapservers = ldapservers self.who = who self.cred = cred self.mydomains = mydomains self.NOTFOUND = dictstatus['NOTFOUND'] self.TEMP = dictstatus['PERM'] def _lire_annuaire_ldap(self,mel): """ lookup directory server retourne RHS """ def _bind2ldap(servers,who="",cred=""): """ Trouve une serveur ldap dispo dans la liste qui lui est passé """ status = False for server in servers: urildap = "ldap://" + server l = ldap.initialize(urildap) l.protocol_version=ldap.VERSION3 try: resultbind = l.simple_bind_s(who,cred) status = True break except ldap.LDAPError,e : continue return(status,l) uid = '' mailhost = '' aretourner = self.NOTFOUND statusldap = False # directory server est disponible ? # Nom de la map # si on en a plusieurs dans le futur nommap = mel.split()[0].split(':')[1] # map LHS mel = mel.split()[1][:-1] # our domain or not ? try: mydomain = mel.split('@')[1] except IndexError,e: mydomain = 'mydomain' if mydomain in self.mydomains: statusldap, maconn = _bind2ldap(self.ldapservers,self.who,self.cred) if statusldap: marequete = '(|(mail=' + mel + ')(mailalternateaddress=' + mel +')(mailequivalentaddress=' + mel + '))' result_data = maconn.search_s("dc=...", ldap.SCOPE_SUBTREE, marequete , ['uid', 'mailhost'] ) if len(result_data) > 0: try: uid = ''.join(result_data[0][1]['uid']) except KeyError: print 'error clef:%s' % mel uid = mel.split("@")[0] mailhost = ''.join(result_data[0][1]['mailhost']) status = 'OK ' reponse = status + '<' + uid + '@' + mailhost + '>' aretourner = str(len(reponse)) + ":" + reponse + ',' else: aretourner = self.NOTFOUND else: aretourner = self.PERM else: aretourner = self.NOTFOUND return (aretourner) # Status de lookup "fixe" dictstatus = {'NOTFOUND' : '8:NOTFOUND,', 'PERM' : '4:PERM,'} # servers/user/pass necessaire au bind # server = ["ldap1","ldap2"] binddn = "" passwd = "" mydomains = ["mydomain"] application = service.Application('mapsmx', uid=663, gid=663) factory = MapFactory(server,binddn,passwd,mydomains,dictstatus) internet.TCPServer(8090, factory).setServiceParent( service.IServiceCollection(application)) HTH jmp
On Nov 13, 2006, at 11:10 PM, jean-marc pouchoulon wrote:
Shimon Rura wrote:
Hi folks,
Hello
I'm a newbie writing a twisted server that needs to access an LDAP server. I started by using python-ldap, which worked fine and is well documented, but doesn't seem to have support for a callback mechanism that would make it appropriate for a twisted app. So I switched to ldaptor, which fits the twisted model, but doesn't seem to have much documentation.
I tried to use it but it worked only with twisted 1.3
ldaptor, at least version 0.0.43, works fine with Twisted 2.2. I've used it to add authentication to buildbot. Nothing fancy - bind, search, rebind. My code lives here: <http://sourceforge.net/tracker/ index.php?func=detail&aid=1469500&group_id=73177&atid=537003> Cheers, Scott -- Scott Lamb <http://www.slamb.org/>
participants (3)
-
jean-marc pouchoulon
-
Scott Lamb
-
Shimon Rura