Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to get multiple entries by dn using a single ldap call? #168

Open
gredwhite opened this issue Aug 22, 2024 · 2 comments
Open

Comments

@gredwhite
Copy link

I have a code like this:

List<String> dns = ...
List<Entry> entries = new ArrayList<>()
for(dn: dns)
  entries.add(connection.getEntry())

I don't like this code because it makes n ldap calls.

Is there a way to rewrite it to make a single Ldap call ?

@dirmgr
Copy link
Collaborator

dirmgr commented Aug 23, 2024

Sorry for the terse response, but I'm on vacation and on my phone. I may also not be able to follow up immediately if you have additional questions, but I'll do my best).

The only standard LDAP operation that can retrieve entries is a search request, and a single search request can be used to retrieve multiple entries if they all match the search criteria.

Normally, if you want to retrieve a single entry by DN, you issue a search request with a base DN that is the DN of the target entry, a baseObject scope and a filter that will match any entry, like "(objectClass=*)" or "(&)" (if the server supports LDAP true filters). That's what the LDAPConnection.getEntry method does. Unfortunately, you can't include multiple base DNs in a single search request, so that approach can't be used to retrieve multiple entries.

As such, the only way you can get exactly the set of entries you want from a single request is to come up with a filter that matches all of those entries and no others. Fortunately, RFC 5020 defines an operational attribute named entryDN whose value is the DN of the entry that contains it (so the "dc=example,dc=com" entry would have an entryDN value of "dc=example,dc=com"). Not all LDAP servers support this operational attribute, but in those that do, you could use it to search with an OR filter with components for each of the entries you want to retrieve, like "(|(entryDN=dn1)(entryDN=dn3)(entryDN=dn4)...- [ ] (entryDN=dnN))".

Note that if there are a lot of entries you want to get (I'd say at least in the hundreds), then you probably don't want to do this in a single search with a huge filter, but you could at least do it with multiple searches that each use different OR filters targeting different sets of entries and get all of them with a lot fewer requests.

If the server you're using doesn't support entryDN, then you're probably out of luck. It would be possible to define an extended operation to retrieve multiple entries with a single request, but there is no standard for that, and I'm not aware of any servers that have a proprietary extended operation to do it (it's something I've thought of adding to the Ping Identity Directory Server but it's always been way down on the to-do list because there are lots of other higher priorities).

The only other option that you really have would be to use the approach you're currently taking to get entries one at a time, but to parallelize the requests so that you can get them in less time than issuing a request and waiting for the response before issuing the next request. There are a couple of ways to do this:

  • Use multiple threads to issue several requests concurrently.
  • Use a single thread but issue several asynchronous search requests on it. If you use asynchronous requests, the LDAP SDK will return immediately from the call used to issue it, and will return an object that you can use to see if the result is available (e.g., using the Java Future API).

Neither of these approaches would be any gentler on the server, since it would still need to process each individual request, but it could let the client get all the entries faster because it could wait for the responses to multiple requests at the same time instead of doing it one by one.

@gredwhite
Copy link
Author

dirmgr Hope you have a good vacation) Don't expect immediate answer from your side.

Couple of comments:

As such, the only way you can get exactly the set of entries you want from a single request is to come up with a filter that matches all of those entries and no others. Fortunately, RFC 5020 defines an operational attribute named entryDN whose value is the DN of the entry that contains it (so the "dc=example,dc=com" entry would have an entryDN value of "dc=example,dc=com"). Not all LDAP servers support this operational attribute, but in those that do, you could use it to search with an OR filter with components for each of the entries you want to retrieve, like "(|(entryDN=dn1)(entryDN=dn3)(entryDN=dn4)...- [ ] (entryDN=dnN))".

Have you heard that AD supports it ?

Note that if there are a lot of entries you want to get (I'd say at least in the hundreds), then you probably don't want to do this in a single search with a huge filter

Why not ? what wrong with a huge filter ? I think it is better than a lot of ldap requests

If the server you're using doesn't support entryDN, then you're probably out of luck. It would be possible to define an extended operation to retrieve multiple entries with a single request, but there is no standard for that, and I'm not aware of any servers that have a proprietary extended operation to do it (it's something I've thought of adding to the Ping Identity Directory Server but it's always been way down on the to-do list because there are lots of other higher priorities).

Looks like I am out of luck herer with samba/AD

The only other option that you really have would be to use the approach you're currently taking to get entries one at a time, but to parallelize the requests so that you can get them in less time than issuing a request and waiting for the response before issuing the next request. There are a couple of ways to do this:

Use multiple threads to issue several requests concurrently.
Use a single thread but issue several asynchronous search requests on it. If you use asynchronous requests, the LDAP SDK will return immediately from the call used to issue it, and will return an object that you can use to see if the result is available (e.g., using the Java Future API).
Neither of these approaches would be any gentler on the server, since it would still need to process each individual request, but it could let the client get all the entries faster because it could wait for the responses to multiple requests at the same time instead of doing it one by one.

Yes, currently we consider those options. It looks quite simple. But look like having a single request is the preferred option here.
What about comparing
"multiple threads to issue several requests concurrently" vs "asynchronous ldap requests". Is there preferred option here ? Or should we measure on our side ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants