[
https://issues.apache.org/jira/browse/KNOX-3406?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Tamás Marcinkovics updated KNOX-3406:
-------------------------------------
Issue Type: Bug (was: Task)
> Fix intermittent LDAP proxy search truncation
> ---------------------------------------------
>
> Key: KNOX-3406
> URL: https://issues.apache.org/jira/browse/KNOX-3406
> Project: Apache Knox
> Issue Type: Bug
> Components: Server
> Affects Versions: 3.0.0
> Reporter: Tamás Marcinkovics
> Assignee: David Han
> Priority: Minor
>
> Problem: CI intermittently fails test_search_all_groups_by_objectclass — an
> LDAP
> subtree search for (objectClass=groupOfNames) returns only ['level1']
> instead of all 6 groups.
> [https://github.com/apache/knox/actions/runs/30453311904/attempts/1]
> test_knox_ldap_proxy_search.py::TestKnoxLdapProxySearch::test_search_all_groups_by_objectclass
> ests-1 | =================================== FAILURES
> ===================================
> tests-1 | ________
> TestKnoxLdapProxySearch.test_search_all_groups_by_objectclass _________
> tests-1 |
> tests-1 | self = <test_knox_ldap_proxy_search.TestKnoxLdapProxySearch
> testMethod=test_search_all_groups_by_objectclass>
> tests-1 |
> tests-1 | def test_search_all_groups_by_objectclass(self) -> None:
> tests-1 | """All groupOfNames entries under ou=groups are returned."""
> tests-1 | groups = self.rdn_values(GROUPS_BASE, "(objectClass=groupOfNames)")
> tests-1 | for expected in ("analyst", "scientist", "admin", "level1",
> "level2", "level3"):
> tests-1 | > self.assertIn(expected, groups)
> tests-1 | E AssertionError: 'analyst' not found in ['level1']
> tests-1 |
> tests-1 | test_knox_ldap_proxy_search.py:97: AssertionError
>
> I could reproduce this on an ubuntu vm.
>
> Root cause:
> LdapProxyBackend.search() opens an EntryCursor
> over the outer search, then inside the while (cursor.next()) loop calls
> addGroupMemberships(entry, connection, ...) which, when
> useMemberOf=false, calls getUserGroupsInternal(connection, ...)
> , opening a second EntryCursor on the same LdapConnection.
> The Apache Directory LDAP client is not designed for two concurrent
> SearchRequests on one connection: the SearchResultDone PDU from the inner
> search is consumed
> by the outer cursor, which interprets it as "no more entries" and
> terminates early after only 1 result.
> This is a nested/concurrent cursor problem. It is intermittent because the
> inner search's response must race ahead of the outer cursor's next() call —
> which is CPU/network-scheduling dependent and more likely in CI's
> faster-burst containers.
> Fix:
> Drain the outer cursor first, then enrich.
> In search(), collect all raw entries into a list before calling
> addGroupMemberships on any of them. This ensures the outer EntryCursor is
> fully consumed and closed before any secondary LDAP operation is issued on
> the connection.
> Three methods need fixing:
> 1. searchUsers — outer while (cursor.next()) loop calls addGroupMemberships
> on each iteration. Fix: collect all sourceEntry objects into a list inside
> the cursor block, then iterate that list after the cursor closes.
> 2. search — same pattern as searchUsers. Same fix.
> 3. getUser — outer cursor does cursor.next() then calls addGroupMemberships
> before the cursor is closed. Since it only reads one entry though, this is
> lower risk: the inner search fires after cursor.next() returns, while the
> outer cursor is still open. The fix: copy the entry out, close the cursor
> (let the try-with-resources do it naturally by moving addGroupMemberships
> after the try block), then call addGroupMemberships.
> getUserGroupsEntries also open cursors, but those are called from
> addGroupMemberships — they are the inner cursors, not the outer ones. This
> does not need to be changed.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)