Opened 15 years ago

Closed 5 years ago

Last modified 5 years ago

#39 closed task (fixed)

Enable trac email lookup in ldap

Reported by: warmerdam Owned by: strk
Priority: major Milestone:
Component: Trac Keywords:
Cc: hobu

Description

Please do something so that Trac will automatically lookup email addresses for authenticated users in LDAP if they haven't set one themselves via "settings".

Change History (16)

comment:1 by warmerdam, 15 years ago

Owner: changed from hobu to warmerdam

I'll take this one...

comment:2 by warmerdam, 15 years ago

Resolution: fixed
Status: newclosed

OK, I have modified /usr/lib/python2.3/site-packages/trac/notification.py by applying this diff:

[root@osgeo1 trac]# diff notification.py ~warmerdam/notification.py 29a30,53

def osgeo_ldap_email_lookup( uid ):

server = 'localhost' who = 'cn=Manager,dc=osgeo,dc=org' cred = '<manager_password>'

try:

import ldap

l = ldap.open(server) l.simple_bind_s(who,cred)

base = 'uid='+uid+',ou=people,dc=osgeo,dc=org' scope = ldap.SCOPE_BASE result = l.search_s( base, scope, attrlist = mail )

if len(result) != 1:

return None

dn, attrdict = result[0]

return attrdictmail[0]

except:

return None

246,254c270,288 < elif NotifyEmail.nodomaddr_re.match(address): < if self.config.getbool('notification', 'use_short_addr'): < return address < domain = self.config.get('notification', 'smtp_default_domain') < if domain: < address = "%s@%s" % (address, domain) < else: < self.env.log.info("Email address w/o domain: %s" % address) < return None ---

else:

ldap_addr = osgeo_ldap_email_lookup( address ) if ldap_addr is None:

self.env.log.debug("ldap lookup failed.")

if ldap_addr is not None:

self.env.log.debug("Using ldap email %s for uid %s" % (ldap_addr,address)) address = ldap_addr # it would be nice to push this association into # the session info, but a bit tricky...

elif NotifyEmail.nodomaddr_re.match(address):

if self.config.getbool('notification', 'use_short_addr'):

return address

domain = self.config.get('notification', 'smtp_default_domain') if domain:

address = "%s@%s" % (address, domain)

else:

self.env.log.info("Email address w/o domain: %s" % address) return None

This seems to do the trick, though at the cost of an ldap lookup for every email address something is sent to. A copy of the modified notification.py is in ~warmerdam.

Keep in mind this is yet another place with the ldap manager password hardcoded.

comment:3 by warmerdam, 15 years ago

Lets try that patch again with better wiki formatting:

[root@osgeo1 trac]# diff notification.py ~warmerdam/notification.py
29a30,53
> def osgeo_ldap_email_lookup( uid ):
> 
>     server = 'localhost'
>     who = 'cn=Manager,dc=osgeo,dc=org'
>     cred = 'testdap'
> 
>     try:
>         import ldap
> 
>         l = ldap.open(server)
>         l.simple_bind_s(who,cred)
> 
>         base = 'uid='+uid+',ou=people,dc=osgeo,dc=org'
>         scope = ldap.SCOPE_BASE
>         result = l.search_s( base, scope, attrlist = ['mail'] )
> 
>         if len(result) != 1:
>             return None
> 
>         dn, attrdict = result[0]
> 
>         return attrdict['mail'][0]
>     except:
>         return None
246,254c270,288
<             elif NotifyEmail.nodomaddr_re.match(address):
<                 if self.config.getbool('notification', 'use_short_addr'):
<                     return address
<                 domain = self.config.get('notification', 'smtp_default_domain')
<                 if domain:
<                     address = "%s@%s" % (address, domain)
<                 else:
<                     self.env.log.info("Email address w/o domain: %s" % address)
<                     return None
---
>             else:
>                 ldap_addr = osgeo_ldap_email_lookup( address )
>                 if ldap_addr is None:
>                     self.env.log.debug("ldap lookup failed.")
>                 if ldap_addr is not None:
>                     self.env.log.debug("Using ldap email %s for uid %s" % (ldap_addr
,address))
>                     address = ldap_addr
>                     # it would be nice to push this association into
>                     # the session info, but a bit tricky...
>                 elif NotifyEmail.nodomaddr_re.match(address):
>                     if self.config.getbool('notification', 'use_short_addr'):
>                         return address
>                     domain = self.config.get('notification', 'smtp_default_domain')
>                     if domain:
>                         address = "%s@%s" % (address, domain)
>                     else:
>                         self.env.log.info("Email address w/o domain: %s" % address)
>                         return None
>                     

comment:4 by warmerdam, 15 years ago

The script has been altered slightly to bind anonymously now, rather than as manager. Howard has changed the configuration of the ldap somewhat to allow this.

comment:5 by hobu, 15 years ago

Cc: hobu added

comment:6 by warmerdam, 7 years ago

Updated to Trac 1.0.5 and the following change was made to :/usr/local/lib/python2.6/dist-packages/Trac-1.0.5-py2.6.egg/trac/notification.py:

277,297d276
< def osgeo_ldap_email_lookup( uid ):
<     server = 'ldaps://ldap.osgeo.org'
< 
<     try:
<         import ldap
< 
<         l = ldap.initialize(server)
<         l.simple_bind_s('')
< 
<         base = 'uid='+uid+',ou=people,dc=osgeo,dc=org'
<         scope = ldap.SCOPE_BASE
<         result = l.search_s( base, scope, attrlist = ['mail'] )
< 
<         if len(result) != 1:
<             return None
< 
<         dn, attrdict = result[0]
< 
<         return attrdict['mail'][0]
<     except:
<         return None
435,453c414,422
<         else:
<             ldap_addr = osgeo_ldap_email_lookup( address )
<             if ldap_addr is None:
<                 self.env.log.debug("ldap lookup failed.")
<             if ldap_addr is not None:
<                 self.env.log.debug("Using ldap email %s for uid %s" % (ldap_addr
< ,address))
<                 address = ldap_addr
<                 # it would be nice to push this association into
<                 # the session info, but a bit tricky...
< 	    elif not is_email(address) and NotifyEmail.nodomaddr_re.match(address):
<                 if self.config.getbool('notification', 'use_short_addr'):
<                     return address
<                 domain = self.config.get('notification', 'smtp_default_domain')
<                 if domain:
<                     address = "%s@%s" % (address, domain)
<                 else:
<                     self.env.log.info("Email address w/o domain: %s", address)
<                     return None
---
>         elif not is_email(address) and NotifyEmail.nodomaddr_re.match(address):
>             if self.config.getbool('notification', 'use_short_addr'):
>                 return address
>             domain = self.config.get('notification', 'smtp_default_domain')
>             if domain:
>                 address = "%s@%s" % (address, domain)
>             else:
>                 self.env.log.info("Email address w/o domain: %s", address)
>                 return None

comment:7 by strk, 7 years ago

What does the Trac-1.0.5-py2.6.egg modification do exactly, why is it needed ? I'd like to update the corresponding section on the wiki: https://wiki.osgeo.org/wiki/Trac_Instances#Local_Customizations

Is there a SAC repository to put these changes in ?

comment:8 by strk, 6 years ago

NOTE: broken on upgrade to 1.0.x: #1671

comment:9 by strk, 6 years ago

For the record, the patch updated for 1.0.5 (and now in place):

tracsvn:/usr/local/lib/python2.6/dist-packages/Trac-1.0.5-py2.6.egg/trac# diff notification.py.000  notification.py
41a42,66
> def osgeo_ldap_email_lookup( uid ):
>
>     server = 'localhost'
>     who = 'cn=Manager,dc=osgeo,dc=org'
>     cred = 'testdap'
>
>     try:
>         import ldap
>
>         l = ldap.initialize('ldaps://ldap.osgeo.org')
>         l.simple_bind_s('')
>
>         base = 'uid='+uid+',ou=people,dc=osgeo,dc=org'
>         scope = ldap.SCOPE_BASE
>         result = l.search_s( base, scope, attrlist = ['mail'] )
>
>         if len(result) != 1:
>             return None
>
>         dn, attrdict = result[0]
>
>         return attrdict['mail'][0]
>     except:
>         return None
>
414,422c439,456
<         elif not is_email(address) and NotifyEmail.nodomaddr_re.match(address):
<             if self.config.getbool('notification', 'use_short_addr'):   
<                 return address
<             domain = self.config.get('notification', 'smtp_default_domain')
<             if domain:
<                 address = "%s@%s" % (address, domain)
<             else:
<                 self.env.log.info("Email address w/o domain: %s", address)
<                 return None
---
>         elif not is_email(address):
>                 ldap_addr = osgeo_ldap_email_lookup( address )
>                 if ldap_addr is None:
>                     self.env.log.debug("ldap lookup failed.")
>                 if ldap_addr is not None:
>                     self.env.log.debug("Using ldap email %s for uid %s" % (ldap_addr,address))
>                     address = ldap_addr
>                     # it would be nice to push this association into
>                     # the session info, but a bit tricky...
>                 elif NotifyEmail.nodomaddr_re.match(address):
>                     if self.config.getbool('notification', 'use_short_addr'):
>                         return address
>                     domain = self.config.get('notification', 'smtp_default_domain')
>                     if domain:
>                         address = "%s@%s" % (address, domain)
>                     else:
>                         self.env.log.info("Email address w/o domain: %s" % address)
>                         return None

comment:10 by strk, 5 years ago

I found an old Trac ticket requesting a solution to this same feature: https://trac.edgewall.org/ticket/3162 -- as we move toward another upgrade to 1.2 (#1816) it would be nice to finally drop local modifications

comment:11 by strk, 5 years ago

Trac 1.2 (to be updated to, see #1816) made it possible to resolve email via a plugin. See https://trac.edgewall.org/wiki/TracDev/PluginDevelopment/ExtensionPoints/trac.notification.api.IEmailAddressResolver -- we'll need to test such plugin before upgrade

comment:12 by strk, 5 years ago

Component: Systems AdminTrac
Resolution: fixed
Status: closedreopened

comment:13 by strk, 5 years ago

Owner: changed from warmerdam to strk
Status: reopenednew

I'm looking at implementing proper LDAP lookup for email. Some more info can be read in https://trac.edgewall.org/ticket/3162#comment:16

comment:15 by strk, 5 years ago

Resolution: fixed
Status: newclosed

Fix landed in Trac 1.2.1dev: https://trac.edgewall.org/changeset/15356 Closing as it will be resolved by upgrading to Trac 1.2.1dev (revision 15356 or later). Trac upgrade ticket is #1816, LDAP email lookup will be implemented by plugin https://git.osgeo.org/gogs/sac/TracLDAPEmailResolverPlugin

comment:16 by strk, 5 years ago

Ticket #1863 is about restoring the behavior previously obtained by patches included in this ticket, which was modified after upgrading Trac to 1.2 (#1816)

Note: See TracTickets for help on using tickets.