Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.
If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!
V5: Active Directory vs V4 - Delays
-
Hi,
We are experiencing periodic latency issues after migrating from V4 to V5 of the Active Directory user directory implementation.
Summary of the issue:
We observe intermittent delays of ~15 seconds or more
The delays appear to occur when the cache expires (Web.PrivilegeCacheExpiration)
Due to this, we have reverted to V4: Active Directory, which does not exhibit the same behaviorEnvironment characteristics:
Large Active Directory environment
Users have significant group memberships (including nested groups)Behavior differences:
V4 works reliably, especially with recursive lookups disabled
V5 does not expose an option to disable recursive group resolution
The issue only appears in V5Testing performed:
We attempted to reproduce the delay using PowerShellMeasure-Command { Get-ADUser <myusername> } Measure-Command { Get-ADUser <myusername> -Properties memberOf } Measure-Command { Get-ADPrincipalGroupMembership <myusername> }All of these return quickly in our environment.
However, we understand these cmdlets may not reflect the same LDAP query patterns used internally by V5 (e.g., DirectorySearcher, recursive group enumeration, or per-group lookups).
Questions:
Does V5 perform recursive group resolution via individual LDAP queries rather than using tokenGroups or equivalent server-side expansion?
Is there a way to disable or limit recursive group resolution in V5 (similar to V4)?
Does V5 perform additional lookups per group (e.g., resolving each memberOf DN individually)?Given that the delays correlate with cache expiration, it seems likely that group resolution or permission evaluation is triggering a large number of LDAP queries.
Any guidance or recommendations would be appreciated.
-
Let me start with a little background in V5 vs V4. With V5, our goal was to only support Active Directory because we have since created an OpenLDAP/Generic LDAP specific user directory. This allowed us to strip out the extra LDAP querying we had to do in V4 to support both. This significantly reduces the amount of LDAP queries to look up a user. It also allowed us to lean into specific Active Directory LDAP features that we could not do when supporting both.
One of those features we can now use is the built in LDAP query for a user's groups and a group's members. When we look up groups we use the following LDAP query:
(&(objectCategory=group)(member:1.2.840.113556.1.4.1941:=«USER_DISTINGUISHED_NAME»))This means that we will return all groups (including nested groups) just like how Active Directory would on Windows without having to make a circular walk of the groups tree in a single LDAP request.
Could you answer a few questions for me?
- Is your ProGet instance running on Windows or Docker?
- When you say significant group memberships, approximately how many are there? (~10, ~20, ~50, etc...)
- Is your domain part of a multi-directory forest?
- In your V4 user directory, can you change the recursive group search to "Recursive Search (Active Directory Only)" and see if you see the same slow downs?
Thanks,
Rich
-
1: Windows
2: On my user, 101 direct groups using Get-ADPrincipalGroupMembership, 217 groups using your query
3: No multi-directory forest.
4: I can try later22 GC servers, 37K users.
We have managed to reproduce the delay from powershell$dn = (Get-ADUser REDACTEDUSERNAME).DistinguishedName $searcher = New-Object DirectoryServices.DirectorySearcher $searcher.Filter = "(&(objectCategory=group)(member:1.2.840.113556.1.4.1941:=$dn))" Measure-Command { $searcher.FindAll() }TotalSeconds : 19,9523562
I have tried this on all 22 GC servers
$dn = (Get-ADUser REDACTEDUSERNAME).DistinguishedName $dcs = (Resolve-DnsName -Type SRV _ldap._tcp.dc._msdcs.$env:USERDNSDOMAIN).NameTarget foreach ($dc in $dcs) { $time = Measure-Command { $searcher = New-Object DirectoryServices.DirectorySearcher $searcher.SearchRoot = "LDAP://$dc" $searcher.Filter = "(&(objectCategory=group)(member:1.2.840.113556.1.4.1941:=$dn))" $searcher.FindAll() | Out-Null } [PSCustomObject]@{ DC = $dc TimeMs = $time.TotalMilliseconds } }It ranges between 19 -> 25 seconds
I think I need an option to either disable recursion or defining a search scope unless there exist some other way to query AD. :)
-
We can add back support to not do the recursive search. If you would like to use a search scope, we would recommend using the OpenLDAP/Generic LDAP user directory and specifying your own LDAP queries. With that said, I think that is overkill for this situation and adding a way to disable recursive groups will be the easiest. I will get that added on the April 3rd release of ProGet 2025.25.
Thanks,
Rich