Wir haben eine Pyramid-Anwendung, die LDAP für die Authentifizierung verwendet. Derzeit verwenden wir nicht pyramid_ldap
, sondern benutzerdefinierten Code basierend auf python_ldap
, um eine Verbindung zum LDAP-Server herzustellen.Erratic INSUFFICIENT_ACCESS Fehler bei der Verwendung von LDAP
Der Code ist in einer Singleton-Klasse: die __init__
Methode (genauer: das Verfahren während der Exemplarerstellung genannt) ruft ldap.initialize
die LDAPObject
und simple_bind_s
zu erstellen. Hier ist der Code (der Benutzer kann durch die LDAP-Server übergibt durch ein lokales Administrator-Konto bereitstellt):
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
Die Singleton in der Server-Start-Funktion erstellt wird (so vor jeder Anfrage) und die nachfolgenden Anfragen abrufen nur der Beispiel. Wir verwenden das admin
Konto anmelden:
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
Das meiste Zeit funktioniert, aber manchmal LDAP-Operationen nicht mit INSUFFICIENT_ACCESS
Fehler. Der Fehler tritt auf, wenn wir den Server zum Beispiel bei lokaler Entwicklung neu starten (in diesem Fall verwenden wir pserve
mit der Option reload
), aber auch auf dem Produktionsserver (wo die Dienste verwaltet werden über circus
und chaussette
- wir starten normalerweise mehrere Prozesse) . Die einzige Lösung, die wir gefunden haben, besteht darin, den Server herunterzufahren und neu zu starten.
Wir suchen nach Hinweisen auf was passiert und wie man es löst.
Der Benutzername und das Passwort sind korrekt, da es die meiste Zeit funktioniert. AFAIU ein Problem in Bindung sollte eine Ausnahme beim Serverstart auslösen. Ich frage mich, ob das Autoreload oder die mehreren Prozesse solche Probleme auslösen könnten (da es normalerweise beim Neustart des Servers funktioniert).
Einige Versionsinformationen:
- OS: Ubuntu 12.04 oder 14.04
- Python: 2.7
- OpenLDAP: 2.4.28
- python_ldap: 2.4.25
Yeah. Sie müssen hier Code anzeigen. –
Sie haben wahrscheinlich recht. Denkst du, ich sollte auch die 'Zirkus'-Konfiguration hinzufügen? Das Problem tritt auch während der lokalen Entwicklung ohne Zirkus auf. –