| Log note : check LDAP group for membership and more |
changed: - - **From: Denis Shaposhnikov** **Date: Sat, 5 Jan 2008 21:37:56 +0300** I want to share my expirience with configuring Roundup to use LDAP for authentication. I've found that the LDAPLogin (see above) is not exactly what I need. It creates new Roundup user after successfull LDAP authentication but use empty password. And it checks local password first. So, after first LDAP authentication anyone can login with empty password. OK, I've done some modifications and you can find 'ldaplogin.py' below. Just configure it and put to 'extenstions' directory. This module can do local authentication too but it disabled by default, see above for the reason. My module do the next steps for authentication: 1. Try to bind with user's DN (without search). 2. Check that user is a member of configured group. This check is optional. 3. If no Roundup's user in the database, create it. It creates a user with password and with some fields from LDAP. Here the 'ldaplogin.py' module:: """Authentication an user via LDAP.""" import ldap from roundup import password as PW from roundup.cgi import exceptions from roundup.cgi.actions import LoginAction from roundup.i18n import _ class LDAPLoginAction(LoginAction): """Do LDAP authentication. Do LDAP (and may be local) authentication and create new roundup user if it is not exists. If property `ldap_req_group` have any value the user should be a memeber of that LDAP group. Set `use_local_auth` if you want to use local authentication and LDAP next. If not, it authenticates by LDAP only. """ ldap_attrs = ( ('address', 'mail'), ('organisation', 'o'), ('realname', 'cn'), ('phone', 'telephoneNumber'), ('username', 'uid')) ldap_dn = 'uid=%s,ou=people,dc=example,dc=com' ldap_group_attr = 'memberUid' ldap_req_group = 'cn=Roundup Users,ou=groups,dc=example,dc=com' ldap_server = 'ldap://127.0.0.1/' use_local_auth = False # LDAP only def local_login (self, password): """Try local authentication.""" # make sure the user exists try: self.client.userid = self.db.user.lookup(self.client.user) except KeyError: self.client.error_message.append( _('Unknown user "%s"') % self.client.user) return 0 # verify the password if not self.verifyPassword(self.client.userid, password): self.client.error_message.append(_('Invalid password')) return 0 # Determine whether the user has permission to log in. # Base behaviour is to check the user has "Web Access". if not self.hasPermission("Web Access"): raise exceptions.LoginError, self._( "You do not have permission to login") return 1 def ldap_login(self, password): """Try LDAP authentication.""" ldapconn = ldap.initialize(self.ldap_server) # verify the password try: ldapconn.bind_s(self.ldap_dn % self.client.user, password) except: self.client.error_message.append (_('Invalid password')) return 0 if self.ldap_req_group: # verify the group membership member = None try: member = ldapconn.compare_s( self.ldap_req_group, self.ldap_group_attr, self.client.user) except: member = None if not member: self.client.error_message.append ( _("You do not have permission to login")) return 0 return 1 def verifyLogin(self, username, password): # try to login throught LDAP or with local account ldap_ok = None if self.use_local_auth: if not self.local_login(password): ldap_ok = self.ldap_login(password) if not ldap_ok: raise exceptions.LoginError else: ldap_ok = self.ldap_login(password) if not ldap_ok: raise exceptions.LoginError self.client.error_message = [] # reload user profile, or create it automatically if missing try: self.client.userid = self.db.user.lookup(self.client.user) except: if ldap_ok: ldapconn = ldap.initialize(self.ldap_server) ldaps = ldapconn.search_s( self.ldap_dn % self.client.user, ldap.SCOPE_BASE) attrs = ldaps[0][1] props = {} for user_attr,ldap_attr in self.ldap_attrs: props[user_attr] = attrs.get(ldap_attr,('',))[0] props['password'] = PW.Password(password) self.journaltag = 'admin' cl = self.db.user props['roles'] = self.db.config.NEW_WEB_USER_ROLES self.userid = cl.create(**props) self.db.commit() self.client.userid = self.db.user.lookup(self.client.user) else: raise exceptions.LoginError, _( "No account created without LDAP account") def init(instance): instance.registerAction('login', LDAPLoginAction)