Posts Tagged LDAP

WSGI daemon mode solves python-ldap connection issues

I was porting a Django/python-ldap application to another server and getting sporadic ldap.SERVER_DOWN errors.  Some basic troubleshooting showed that the problem was occurring specifically when requests routed through mod_wsgi.  If I just ran the Python code — no problem; just the Django app via the dev server — fine; Apache straight to Django (proxying to dev server) — OK.  Now, while I had been planning to investigate mod_wsgi’s “daemon mode” for some time, I was still running all my apps in “embedded mode”.  But with this python-ldap problem, I had to dig deeper into the docs.  The mod_wsgi ApplicationIssues page discusses a number of problems related to C extension modules, and while not specifically mentioning python-ldap, it does make this generalization:

Because of the possibilty that extension module writers have not written their code to take into consideration it being used from multiple sub interpreters, the safest approach is to force all WSGI applications to run within the same application group, with that preferably being the first interpreter instance created by Python.

To force a specific WSGI application to be run within the very first Python sub interpreter created when Python is initialised, the WSGIApplicationGroup directive should be used and the group set to ‘%{GLOBAL}’.

WSGIApplicationGroup %{GLOBAL}

If it is not feasible to force all WSGI applications to run in the same interpreter, then daemon mode of mod_wsgi should be used to assign different WSGI applications to their own daemon processes. Each would then be made to run in the first Python sub interpreter instance within their respective processes.

I did try WSGIApplicationGroup %{GLOBAL} first, but (assuming I implemented it correctly), the problem remained. So I tried WSGI daemon mode and the process has proved stable.

Advertisements

, ,

Leave a comment

Apache LDAP authentication and Active Directory

I needed to authenticate users in Apache against Active Directory using mod_authnz_ldap.  Normally I would have set the URL and base DN like this:

ldaps://example.com
ou=CompanyPeople,dc=example,dc=com

In this case, however, the users spanned two different top-level containers or “domains”:

ou=CompanyPeople,dc=example,dc=com
ou=OtherPeople,dc=example,dc=com

So, I tried setting the base DN to the top level:

dc=example,dc=com

but authentication failed with this ugly error in the log:

[ldap_search_ext_s() for user failed][Operations error]

It took some hunting, but I finally found that if you want to query the Active Directory “Global Catalog” (GC) via LDAP, you have to use port 3268 or 3269 (LDAPS) instead of the usual default port 389 or 636. So, the working URL and base DN are:

ldaps://example.com:3269
dc=example,dc=com

,

2 Comments

Django and Web Services

Or, developing Django data applications without a database.

In recent months I have been working intensively on a user interface to a data store that lives behind a web services API.  While this might not be considered a natural fit for Django, the smart de-coupling of URLs, views, and templates from data models means that the former retain their value even without the latter.  And hey, it’s all just Python, right?  Django models are just one way to handle data in your application, albeit a very convenient and powerful one when dealing with an RDBMS.

Before working on this project, I had already developed two other Django apps based on data sources accessed via HTTP, both of which were read-only, which of course made things quite a bit simpler.  The first of these was an XML-RPC interface (built with django_xmlrpc, Python’s standard xmlrpclib module and python-ldap) to an LDAP directory.  I manage user and group information for a number of staff applications, including Django itself, for which it is very useful to draw upon a central source of personnel data.  The Django-based service provides convenient methods for common operations while hiding the complexities of LDAP connections and search queries.

The second app dealt with requests to web services of a library catalog which return content in a custom XML format.  Since only HTTP GET requests were required, I used Python’s standard urllib and urllib2 modules for the request/response handling, and lxml.etree for the XML parsing and XSLT application (see also my previous post on the virtues of lxml).

The current project, as opposed to the previous two, involves both read and write actions on the backend data store.  Also, because the web services API implements a REST architecture, the “client” code I was tasked with has to support a wider range of HTTP request methods (not just GET and POST) and responses.  Finally, the client code stack includes a full-blown user interface (the ultimate purpose of the app) for managing the backend data.  In my next post, I’ll talk about how I broke down the problem.

, , , , , , ,

Leave a comment