#7406 Improving LDAP registration methods

sf-2 (994)

Originally created by: ifreeman

The use case I had in mind when using ldap auth was for an enterprise environment where there is already an existing ldap server containing existing user accounts. Users would register by providing their ldap credentials and Allura would authenticate them against ldap and then automatically provision their account. Even better if all this would happen simply by logging in (bypassing registration altogether).

But it seems the ldap plugin author had a different use case in mind: a local ldap server that is only managing accounts for this Allura instance. When registering an account on Allura, an admin account on the ldap server is used to create a new ldap object for the username in the domain. It is not possible to register an account without the ldap's admin account.

I believe the existing functionality to be contrary to the wishes of most enterprise installations.

I propose the attached patch to ./Allura/allura/lib/plugin.py to accomplish the following:
- Add a new registration.method = ldap to repurpose the existing behavior (creating a new ldap account upon allura registration, error if exists in ldap)
- Repurpose the existing registration.method = local configuration to be used in conjunction with auth.method = ldap as follows:
1. authenticate against ldap with an existing user
2. create local account in allura with the provided and ldap-authenticated username
3. use ldap to authenticate future logins

This being my first experience with python and this project I have not yet found the best way I should extend widgets/auth_widgets.py to be able to display errors to the user on the registration page. There are a great number of error conditions that should not be throwing exceptions (for such common occurances as an invalid password). Can any of you point me in the right direction/take it from here?

1 Attachments


  • Dave Brondsema

    Dave Brondsema - 2014-05-23

    I agree the current LDAP provider doesn't work the way most people would want it to, and adding the functionality as you describe sounds good. I won't be able to look at this right away, but wanted to say thanks for getting this started -- especially for contributing an initial patch.

  • Dave Brondsema

    Dave Brondsema - 2014-06-10
    • status: open --> in-progress
    • assigned_to: Dave Brondsema
    • Milestone: limbo --> forge-jun-13
  • Dave Brondsema

    Dave Brondsema - 2014-06-13
    • status: in-progress --> code-review
    • Size: --> 2
  • Dave Brondsema

    Dave Brondsema - 2014-06-13

    Branch db/7406 has support for

    • auto-registration of LDAP users (just login)
    • disabling regular user registration
    • using LDAP to get the display name for users
    • performance & timing enhancements for LDAP

    Also SF-internal forge-classic branch db/7406 has some semi-related changes.

  • Igor Bondarenko - 2014-06-19
    • status: code-review --> in-progress
  • Igor Bondarenko - 2014-06-19

    Looks good. Found an issue, though:

    If user_prefs_storage.ldap.fields.display_name = cn is set exeption is raised, when:

    • changing Display Name from /auth/preferences
    • registering new user

    Perhaps, related to LDAP configuration on sandboxes?

    URL: http://sf-fortytwo-1030.sb.sf.net/auth/preferences/update
    File '/var/local/env-allura/lib/python2.7/site-packages/weberror/evalexception.py', line 438 in respond
      return_iter = list(app_iter)
    File '/var/local/env-allura/lib/python2.7/site-packages/Paste-', line 409 in streaming_iter
      for item in self.application(environ, start_response):
    File '/var/local/env-allura/lib/python2.7/site-packages/ming/odm/middleware.py', line 20 in __call__
      result = self.app(environ, start_response)
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/lib/custom_middleware.py', line 60 in __call__
      return self.app(environ, start_response)
    File '/var/local/env-allura/lib/python2.7/site-packages/EasyWidgets-0.2dev_20130716-py2.7.egg/ew/middleware.py', line 65 in __call__
      result = self.app(environ, start_response)
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/config/middleware.py', line 202 in AlluraGlobalsMiddleware
      return app(environ, start_response)
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/lib/custom_middleware.py', line 147 in __call__
      return self._app(environ, session_start_response)
    File '/var/local/env-allura/lib/python2.7/site-packages/TimerMiddleware-0.4.4-py2.7.egg/timermiddleware/__init__.py', line 202 in __call__
      resp = req.get_response(self.app)
    File '/var/local/env-allura/lib/python2.7/site-packages/WebOb-1.0.8-py2.7.egg/webob/request.py', line 1053 in get_response
      application, catch_exc_info=False)
    File '/var/local/env-allura/lib/python2.7/site-packages/WebOb-1.0.8-py2.7.egg/webob/request.py', line 1022 in call_application
      app_iter = application(self.environ, start_response)
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/lib/custom_middleware.py', line 99 in __call__
      self.app, environ, catch_exc_info=True)
    File '/var/local/env-allura/lib/python2.7/site-packages/Pylons-1.0-py2.7.egg/pylons/util.py', line 48 in call_wsgi_application
      app_iter = application(environ, start_response)
    File '/var/local/env-allura/lib/python2.7/site-packages/Beaker-1.5.4-py2.7.egg/beaker/middleware.py', line 152 in __call__
      return self.wrap_app(environ, session_start_response)
    File '/var/local/env-allura/lib/python2.7/site-packages/Routes-1.12.3-py2.7.egg/routes/middleware.py', line 131 in __call__
      response = self.app(environ, start_response)
    File '/home/fortytwo/fortytwo-1034/forge-classic/ForgeSF/forgesf/middleware.py', line 79 in __call__
      resp = request.get_response(self.app)
    File '/var/local/env-allura/lib/python2.7/site-packages/WebOb-1.0.8-py2.7.egg/webob/request.py', line 1053 in get_response
      application, catch_exc_info=False)
    File '/var/local/env-allura/lib/python2.7/site-packages/WebOb-1.0.8-py2.7.egg/webob/request.py', line 1022 in call_application
      app_iter = application(self.environ, start_response)
    File '/home/fortytwo/fortytwo-1034/forge-classic/ForgeSF/forgesf/middleware.py', line 49 in __call__
      return self.app(env, start_response)
    File '/var/local/env-allura/lib/python2.7/site-packages/Pylons-1.0-py2.7.egg/pylons/wsgiapp.py', line 107 in __call__
      response = self.dispatch(controller, environ, start_response)
    File '/var/local/env-allura/lib/python2.7/site-packages/Pylons-1.0-py2.7.egg/pylons/wsgiapp.py', line 312 in dispatch
      return controller(environ, start_response)
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/lib/base.py', line 49 in __call__
      environ, start_response)
    File '/var/local/env-allura/lib/python2.7/site-packages/Pylons-1.0-py2.7.egg/pylons/controllers/core.py', line 211 in __call__
      response = self._dispatch_call()
    File '/var/local/env-allura/lib/python2.7/site-packages/Pylons-1.0-py2.7.egg/pylons/controllers/core.py', line 162 in _dispatch_call
      response = self._inspect_call(func)
    File '/var/local/env-allura/lib/python2.7/site-packages/Pylons-1.0-py2.7.egg/pylons/controllers/core.py', line 105 in _inspect_call
      result = self._perform_call(func, args)
    File '/var/local/env-allura/lib/python2.7/site-packages/TurboGears2-2.1.5-py2.7.egg/tg/controllers/dispatcher.py', line 258 in _perform_call
      r = self._call(func, params, remainder=remainder)
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/lib/patches.py', line 118 in _call
      return old_controller_call(self, controller, *args, **kwargs)
    File '/var/local/env-allura/lib/python2.7/site-packages/TurboGears2-2.1.5-py2.7.egg/tg/controllers/decoratedcontroller.py', line 120 in _call
      output = controller_callable(*remainder, **dict(params))
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/controllers/auth.py', line 370 in update
      c.user.set_pref('display_name', preferences['display_name'])
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/model/auth.py', line 350 in set_pref
      return plugin.UserPreferencesProvider.get().set_pref(self, pref_name, pref_value)
    File '/home/fortytwo/fortytwo-1034/forge/Allura/allura/lib/plugin.py', line 1154 in set_pref
      [(ldap.MOD_REPLACE, ldap_attr, pref_value.encode('utf-8'))])
    File '/var/local/env-allura/lib/python2.7/site-packages/TimerMiddleware-0.4.4-py2.7.egg/timermiddleware/__init__.py', line 117 in wrapper
      return self.run_and_log(func, inst, *args, **kwargs)
    File '/var/local/env-allura/lib/python2.7/site-packages/TimerMiddleware-0.4.4-py2.7.egg/timermiddleware/__init__.py', line 126 in run_and_log
      return func(*args, **kwargs)
    File '/var/local/env-allura/lib/python2.7/site-packages/ldap/ldapobject.py', line 357 in modify_s
      return self.result(msgid,all=1,timeout=self.timeout)
    File '/var/local/env-allura/lib/python2.7/site-packages/ldap/ldapobject.py', line 458 in result
      resp_type, resp_data, resp_msgid = self.result2(msgid,all,timeout)
    File '/var/local/env-allura/lib/python2.7/site-packages/ldap/ldapobject.py', line 462 in result2
      resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all,timeout)
    File '/var/local/env-allura/lib/python2.7/site-packages/ldap/ldapobject.py', line 469 in result3
    File '/var/local/env-allura/lib/python2.7/site-packages/ldap/ldapobject.py', line 476 in result4
      ldap_result = self._ldap_call(self._l.result4,msgid,all,timeout,add_ctrls,add_intermediates,add_extop)
    File '/var/local/env-allura/lib/python2.7/site-packages/ldap/ldapobject.py', line 99 in _ldap_call
      result = func(*args,**kwargs)
    INSUFFICIENT_ACCESS: {'info': "Insufficient 'write' privilege to the 'cn' attribute of entry 'uid=admin1,ou=users,dc=sf,dc=net'.\n", 'desc': 'Insufficient access'}
  • Dave Brondsema

    Dave Brondsema - 2014-06-19
    • status: in-progress --> closed
  • Dave Brondsema

    Dave Brondsema - 2015-01-05
    • Milestone: unreleased --> asf_release_1.2.0

Log in to post a comment.