[ 
https://issues.apache.org/jira/browse/KNOX-3406?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on KNOX-3406 started by David Han.
---------------------------------------
> 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)

Reply via email to