Erlang :eldap timeout with a lot of results

I’ve been using Exldap to integrate my application with an Active Directory server. For some functions not supported by Exldap, I’ve been calling :eldap functions directly. I encountered a huge performance issue today and I’m trying to figure out what’s going on. In order to narrow the issue down, I bypassed Exldap and did everything directly using :eldap.

All I’m trying to do is list all the members of a largish group (~380 members). When I execute the search using the ldapsearch command line utility, I get all the results displayed in a fraction of a second:

$ time ldapsearch \
  -H ldaps:/ldap.example.edu:636 \
  -D 'CN=My Bind DN,OU=Service Accounts,DC=department,DC=example,DC=edu' \
  -w 'bind_password' \
  -b 'DC=department,DC=example,DC=edu' \
  -s sub \
  '(memberOf=CN=Staff,OU=Staff,DC=department,DC=example,DC=edu)'

# [379 responses / ~25000 lines of output omitted]
# numResponses: 379
# numEntries: 377
# numReferences: 1
0.05s user 0.05s system 25% cpu 0.407 total

When I execute the exact same search using the exact same parameters using :eldap:

{:ok, conn} = :eldap.open(['ldap.example.edu'], port: 636, timeout: 50000, ssl: true)

:eldap.simple_bind(
  conn, 
  'CN=My Bind DN,OU=Service Accounts,DC=department,DC=example,DC=edu',
  'bind_password'
)

base = 'DC=department,DC=example,DC=edu'
scope = :eldap.wholeSubtree()
filter = :eldap.equalityMatch('memberOf', 'CN=Staff,OU=Staff,DC=department,DC=example,DC=edu')

:eldap.search(conn, base: base, scope: scope, filter: filter)

# 50 seconds pass
{:error, {:gen_tcp_error, :timeout}}

I can’t spy on the whole conversation over the wire because it’s using SSL, but I can tell that the ldapsearch version results in about a 676k payload while the :eldap version only pulls down 323k before communication stops and the search (eventually) times out. I’m going to set up a local LDAP server in a Docker container without SSL and see how it fares.

Other searches are working fine; it’s just timing out on the one with a few hundred results. I’m not sure where to go from here. Any help or insight would be greatly appreciated.

Are you just doing read searches? Or do you need to write to LDAP too? If you just need to read I might recommend my library instead at:

It’s binary based, faster in a few ways, I’ve been using it for years without issues, etc…

As for this issue I’m really not sure… :-\

Most performance issues I’ve seen is just either bad queries (not hitting indexes on the server) or just the server itself being very poor on performance with certain things.

Are you just doing read searches? Or do you need to write to LDAP too?

Mostly reads, some writes, but I can do my writes directly using :eldap. I would have assumed my query was the problem, but it’s just a straight up “User memberOf Group” query. (I know that in this simplest case, I could just grab the group’s member attribute, but my actual use case is more complex. I’ve just boiled it down to this to investigate/debug the issue.)

I would also suspect the server-side indexing was an issue if I hadn’t successfully performed the same search using ldapsearch on the command line.

To make things even more complicated, I set up a 500-user test server on my dev machine and it works fine using both ldapsearch and :eldap.search(), so now I’m stuck suspecting some kind of weird compatibility issue in Active Directory or maybe the SSL layer.

Sigh.

Eh, depending on how the LDAP server is programmed this can be an annoyingly expensive query. A lot of LDAP servers are really bad… >.>

I’d say give mine a try, just to rule out some other potential costs (it’s not just hiding eldap under the hood)…

Ooo, this is Active Directory, good luck with that to be honest… ^.^;

1 Like

Just tried the same search with Ruby’s net-ldap library and it returned all the results nearly instantaneously. It’s looking more and more like :eldap is choking on something.

I’ll take a look at ldap_ex.

2 Likes

@OvermindDL1 Based on this line I’m guessing you don’t support SSL connections in ldap_ex? That’s another of my requirements, I’m afraid.

ETA: Oh wait. I didn’t notice the different atom (:gen_tcp vs :ssl). I might have a certificate issue. I’ll keep poking around. Never mind.

1 Like

know nothing about ldap - but just popped in my eyes that the elixir code is using single quotes and NOT normal double quotes

iex(1)> 'ok' == "ok"
false

but probably just a copy/paste forum issue, or the library accepts both, but just checking…

just popped in my eyes that the elixir code is using single quotes and NOT normal double quotes

I’m bypassing the Elixir wrapper and calling erlang’s :eldap library directly, which calls for charlists and not binary strings

2 Likes

@OvermindDL1 I figured out the SSL connection issue and submitted a minuscule pull request. :slight_smile:

1 Like

Lol, nice. Does it work for you? I hadn’t needed SSL as it’s done over a secure tunnel here. ^.^;

Merged and new release out as 0.2.6. :slight_smile:

1 Like

Super weird. I couldn’t get ldap_ex to work with the AD server but for different reasons, I think having to do with the Active Directory tree delegation model. The search response is

{:error,
 %LDAPEx.Client.LDAPException{
   message: {:searchResRef,
    ["ldaps://department.example.edu/CN=Configuration,DC=department,DC=example,DC=edu"]},
   type: :search_failure
 }}

So I did some more experimenting with Exldap and :eldap, and discovered that both of them give me the same timeout when I try to run a search with 500 results against a local test server running Samba LDAP, but only when using SSL. (If I connect without encryption, the search works fine.) However, using the same data and the same search on a local test server running OpenLDAP, it works fine, even with SSL.

So yeah, I’m stumped. Unfortunately, there seems to be no way to limit the number of search results using :eldap.

1 Like