LDAP library for Rust

Hi,

Since google seems to can’t find answer to my question maybe someone here will be able to help.
I’m trying to find “position” for Rust in my company (“telco”) but critical requirement is to have LDAP library since almost any app written must be able to talk to authentication systems (either OpenLDAP/AD). I was browsing Internet for past few days but it seems that there is no crate for such popular and widely used protocol in any bigger organization.

Does anyone knows is there some running project for implementing this that is not on crates.io ?

I have bad luck when trying to introduce Rust :confused: Last time I tried there was similar issue with another very popular protocol without reasonable implementation - SNMP. There are libraries but they have only minimal functionality.

Regards,

There is some LDAP crates on https://crates.io/search?q=ldap.

Currently I’m using the openldap one but I may try the ldap one (since it’s pure Rust).

None of those supports anything except search, so hardly you can say they support LDAP.
I need modify/delete. No “fancy” TLS, simple bind and basic CRUD operations.
Currently writing such lib is beyond my time constrains and probably above my Rust knowledge :slight_smile:

On the server side, there was a talk at LCA about writing Rust plugins to 389 DS. (video)

edit: here’s the author’s blog post about it.

You can just use a C LDAP library (e.g. http://www.openldap.org/). You can make it even easier and create the bindings with bindgen.

e: Personally I’d prefer a Rust solution, but you seem to need a mature, feature-complete library.

1 Like

I’m currently working on an LDAP library, and I’m going to publish it as soon as it stabilizes a bit, which should happen in a week or two.

Some history:

As you can see on GH, it’s a fork of a rather old project which was developed on and off for the past two years, but never went beyond basic simple bind/search operations. The latest rewrite, from the start of this year, was based on the tokio stack. There was a steady stream of updates, and then again a lull.

I contributed a PR to this version which enabled LDAP over TLS (ldaps://, not StartTLS), added support for attribute lists in searches, and fixed a bug in search result handling. However, on further inspection, I saw that updating the code to handle everything I needed would be so intrusive that I might as well fork it and develop it independently. I got in contact with the author and told him about my plan to fork the driver, which he accepted amicably (as was the intention).

What’s the present situation?

The latest master has everything from my original PR, plus a completely rewritten filter parser, with full support for RFC 4515. However, it’s not usable even for medium-size result sets because of the way it’s using tokio-proto: it will blow up if there are more than 127 search result entries. Its handling of LDAP message ids is not according to spec (the OpenLDAP server, against which I’m testing the code, is fortunately tolerant of that; others might not be). Add/Modify/Delete are not supported. In summary: if you only need searches, and can live with small result sets, you may try to use it.

Development is happening on the msgid-plus branch, which has, so far, seen a total restructuring of the tokio-proto interface to support large result sets, addition of RFC-compliant message id handling, and the beginning of support for response controls and the full range of LDAP result values.

My priorities are:

  • Finishing basic support for LDAP results/response controls.
  • Returning search results in a usable form, while preparing the driver for custom deserialization via Serde.
  • Adapting the existing synchronous code for result streaming.
  • Publishing the first version of the crate.

I’ll post updates here, if there’s interest.

5 Likes

Great news !
Thanks for info. I can’t wait to test it and give some feedback. Please be so kind to update this thread when you make release.

After some last-minute refactorings and fighting with crates.io, I’ve finally published the crate: ldap3, version 0.4.0. The relatively high version number reflects, I hope accurately, the state of the driver: all LDAP protocol operations are implemented, and the synchronous interface should be quite usable.

The documentation is very sparse, and is the first thing I’ll proceed to flesh out, at a bit slower pace than the last two weeks of development. If you know LDAP, there shouldn’t be any surprises in the interface, although I hope it’s more pleasant to use than various other language bindings I’ve used/endured over the years.

The data subdirectory of the repository contains the setup for a toy OpenLDAP server which can be directly used by the examples (in the examples subdirectory.) The setup has been tested on Ubuntu 16.04 and CentOS 7, but any recent Debian/Fedora etc. should run it without changes.

Feedback is welcome here or on GitHub. Enjoy!

13 Likes

Version 0.5.0 has been released. A major enhancement is the introduction of timeouts, which can be specified for connection attempts and all protocol operations, both synchronous and asynchronous.

The crate has undergone extensive refactoring, resulting in more idiomatic error handling and simpler function signatures, but also a large number of breaking changes, which are documented in the changelog. From the records on crates.io, I have identified both users :wink: of the crate and created PRs to upgrade their LDAP code to 0.5.0. It wasn’t difficult, and I encourage you to upgrade if you have existing code which uses 0.4.x.

10 Likes

After a long hiatus—not the almost three years since the last announcement here, but still one and a half since the last published version of the library—I have ported the code to async/await and Tokio 0.2, and published an alpha of the next release.

From the start, ldap3 offered both synchronous and asynchronous versions of its API. This is unchanged in the new version. Moreover, the synchronous API is virtually identical to the previous version, aside from requiring use through a mutable handle and having a different error type (although with automatic conversion to the old one). In my necessarily limited testing, once the mutability is fixed, nothing else needs to change. The asynchronous API has the same function shapes, but usage is completely different and much more pleasant thanks to async/await.

Why did it take so long? There wasn't a single deciding factor, but if I had to choose the three most relevant, they would be that a) it worked well enough for me, as I knew the code and could work around the limitations, b) there wasn't a lot of outside pressure to update the library, LDAP being a pretty niche protocol in today's landscape, and c) the whole Rust's async ecosystem was going through major churn, what with async/await work, 2018 edition, and Tokio's shift away from the original tokio-core to the multithreaded executors and reators of Tokio 0.1.

That the library continued to work through all this is a testament to both Rust's and the Tokio team's commitment to stability and bacwards compatibility. Stable Rust is still a young language, and it's simply impossible to assess long-term code viability and stability, but what I saw in the limited time-frame available is extremely encouraging. Additionally, refactoring-friendliness of the type system let me use large parts of existing code in the new framework without wondering whether the result was going to work. It did, in manageable steps and without nasty surprises. It was impressive to see how, once the basic I/O machinery was operative, everything else fell into place and started working almost from the first successful compilation. I recognized Rust as an excellent choice for my work long ago, and this experience only strengthened that conviction.

13 Likes

Thank you @inejge, this is excellent news! LDAP support is key to the Rust apps I am working on and your continued development efforts are appreciated.

1 Like

In the almost two years since the last big change and announcement, which involved the port to the then-fresh Tokio 0.2 and async/await, the library has seen the routine maintenance work which has kept it up to date, but nothing really newsworthy in terms of functionality, until now.

The recent appearance of the cross-krb5 crate allowed me to add Kerberos/GSSAPI support in a way that doesn't fragment the authentication mechanisms across platforms. The huge installed base and the formidable backwards compatibility requirements make Windows authentication a veritable zoo, but Kerberos is clearly the preferred method (although NTLM will be with us for a while yet). At the same time, Kerberos is/was a popular choice for some large Unix LDAP installations, so a way to support it on both platforms would neatly supply perhaps the largest piece of missing functionality to the library.

GSSAPI is optional and must be required by the compile-time gssapi feature. Since there are no pure-Rust Kerberos libraries, the feature works through FFI to the underlying C code, which is old and has had its share of security vulnerabilities, something to keep in mind. The interface to GSSAPI binds is experimental and expected to undergo breaking changes.

If you need Kerberos authentication in LDAP, consider testing the library and reporting any issues on GitHub.

4 Likes