使用LDAP时出现不稳定的INSUFFICIENT_ACCESS错误

时间:2016-06-07 20:21:20

标签: python openldap

我们有一个使用LDAP进行身份验证的Pyramid应用程序。目前,我们不使用pyramid_ldap,而是使用基于python_ldap的自定义代码连接到LDAP服务器。

代码在Singleton类中:__init__方法(更准确地说是在实例创建期间调用的方法)调用ldap.initialize来创建LDAPObjectsimple_bind_s。这是代码(用户可以通过提供本地管理员帐户来传递LDAP服务器):

class Singleton(object):
    '''
    Implements the singleton pattern. A class deriving from ``Singleton`` can
    have only one instance. The first instanciation will create an object and
    other instanciations return the same object. Note that the :py:meth:`__init__`
    method (if any) is still called at each instanciation (on the same object).
    Therefore, :py:class:`Singleton` derived classes should define
    :py:meth:`__singleton_init__`
    instead of :py:meth:`__init__` because the former is only called once.
    '''
    @classmethod
    def get_instance(cls):
        try:
            return getattr(cls, '_singleton_instance')
        except AttributeError:
            msg = "Class %s has not been initialized" % cls.__name__
            raise ValueError(msg)

    def __new__(cls, *args, **kwargs):
        if '_singleton_instance' not in cls.__dict__:
            cls._singleton_instance = super(Singleton, cls).__new__(cls)
            singleton_init = getattr(cls._singleton_instance,
                                 '__singleton_init__', None)
            if singleton_init is not None:
                singleton_init(*args, **kwargs)
        return cls._singleton_instance

    def __init__(self, *args, **kwargs):
        '''
        The __init__ method of :py:class:`Singleton` derived class should do nothing.
        Derived classes must define :py:meth:`__singleton_init__` instead of __init__.
        '''

    def __singleton_init__(self, *args, **kwargs):
        super(Singleton, self).__init__(*args, **kwargs)

class UsersAndGroups(Singleton):
    """
    Class used to query the LDAP directory.
    """
    def __singleton_init__(self, admin_login, admin_password,
                           server, ldap_admin_dn, ldap_password, users_dn,
                           groups_dn):
        self.admin_login = admin_login
        self.admin_password = admin_password
        self.server = server
        self.ldap_admin_dn = ldap_admin_dn
        self.ldap_password = ldap_password
        self.users_dn = users_dn
        self.groups_dn = groups_dn

        # Check
        if admin_login and (not admin_password):
            raise ValueError('You must specify a password for the local admin')
        self.has_local_admin = (admin_login) and (admin_password)
        if (not self.server) and (not self.has_local_admin):
            raise ValueError(
                'You must specify an LDAP server or a local admin')

        # Connect to LDAP server
        if self.server:
            self.ldap_connection = ldap.initialize(self.server)
            self.ldap_connection.simple_bind_s(self.ldap_admin_dn,
                                               self.ldap_password)
        else:
           self.ldap_connection = None

Singleton是在服务器启动函数中创建的(因此在任何请求之前),后续请求只是检索实例。我们使用admin帐户登录:

def main(global_config, **settings):

    # Create routes and so on    
    # Get configuration for LDAP connection from app.registry.settings

    # Create the singleton to connect to LDAP
    app.users_groups = UsersAndGroups(admin_login, admin_password, ldap_server,
                                      ldap_admin_dn, ldap_password, users_dn,
                                      groups_dn)

    return app

这在大多数情况下都有效,但有时LDAP操作会因INSUFFICIENT_ACCESS错误而失败。当我们在执行本地开发时(例如我们使用pservereload选项)重新启动服务器时,错误发生在生产服务器上(服务通过{{1管理) }和circus - 我们通常会启动几个进程)。我们找到的唯一解决方案是关闭服务器并重新启动它。

我们正在寻找有关正在发生的事情以及如何解决问题的线索。

登录名和密码是正确的,因为它大部分时间都可以使用。 AFAIU中的一个问题应该在服务器启动期间引发异常。我想知道自动重载或多个进程是否可能触发此类问题(因为它通常在重新启动服务器时有效)。

某些版本信息:

  • 操作系统:Ubuntu 12.04或14.04
  • python:2.7
  • OpenLDAP:2.4.28
  • python_ldap:2.4.25

1 个答案:

答案 0 :(得分:0)

我意识到错误来自代码中的其他地方。