[ 
https://issues.apache.org/jira/browse/KNOX-3487?focusedWorklogId=1048383&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1048383
 ]

ASF GitHub Bot logged work on KNOX-3487:
----------------------------------------

                Author: ASF GitHub Bot
            Created on: 20/Oct/26 07:23
            Start Date: 20/Oct/26 07:23
    Worklog Time Spent: 10m 
      Work Description: handavid commented on code in PR #1454:
URL: https://github.com/apache/knox/pull/1454#discussion_r4322448345


##########
gateway-spi/src/main/java/org/apache/knox/gateway/services/ldap/RoleAssignment.java:
##########
@@ -20,6 +20,18 @@
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class RoleAssignment {
+    public static RoleAssignment createFromDisplayValue(String displayValue) {
+        String[] tokens = displayValue.split(":");

Review Comment:
   done



##########
gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/interceptor/LDAPRolesLookupInterceptor.java:
##########
@@ -86,6 +96,90 @@ public EntryFilteringCursor search(SearchOperationContext 
ctx) throws LdapExcept
             }
         }
 
+        if (isAllGroupsSearch(ctx)) {
+            return handleAllGroupsSearch(ctx);
+        } else {
+            return handleSearch(ctx);
+        }
+    }
+
+    private boolean isAllGroupsSearch(SearchOperationContext ctx) {
+        Dn searchDn = ctx.getDn();
+        if (searchDn == null) {
+            return false;
+        }
+
+        if (ctx.getScope() == SearchScope.OBJECT || 
!isAllGroupsFilter(ctx.getFilter())) {
+            return false;
+        }
+        // Either the proxy groups base, or the root with an explicit group 
filter
+        return searchDn.toString().equalsIgnoreCase(proxyGroupSearchBase) || 
searchDn.size() <= 2;
+    }
+
+    private boolean isAllGroupsFilter(ExprNode filter) {
+        // Case 1: Simple objectClass evaluation (e.g., 
objectClass=groupOfNames)
+        if (filter instanceof EqualityNode) {
+            EqualityNode<?> eqNode = (EqualityNode<?>) filter;
+            if ("objectClass".equalsIgnoreCase(eqNode.getAttribute())) {
+                String value = eqNode.getValue().toString();
+                return "groupOfNames".equalsIgnoreCase(value) ||
+                        "groupOfUniqueNames".equalsIgnoreCase(value);
+            }
+        }
+
+        // Case 2a: Wildcard match on all common names and object classes 
(e.g., cn=*, objectClass=*)
+        if (filter instanceof PresenceNode) {
+            PresenceNode presNode = (PresenceNode) filter;
+            return "cn".equalsIgnoreCase(presNode.getAttribute()) ||
+                    "objectClass".equalsIgnoreCase(presNode.getAttribute());
+        }
+        // Case 2b: Wildcard match on object class (e.g., objectClass=*)
+        if (filter instanceof ObjectClassNode) {
+            return true;
+        }
+
+        // Case 3: Compound filters. An AND is an all groups filter only if 
every child is, an OR
+        // if any child is, e.g. (&(objectClass=groupOfNames)(cn=*)) or 
(|(uid=alice)(cn=*)).
+        // A NOT is never an all groups filter: negating a condition never 
positively selects groups.
+        if (filter instanceof AndNode) {
+            List<ExprNode> children = ((AndNode) filter).getChildren();
+            return !children.isEmpty() && 
children.stream().allMatch(this::isAllGroupsFilter);
+        }
+        if (filter instanceof OrNode) {
+            return ((OrNode) 
filter).getChildren().stream().anyMatch(this::isAllGroupsFilter);
+        }
+
+        return false;
+    }
+
+    private EntryFilteringCursor handleAllGroupsSearch(SearchOperationContext 
ctx) throws LdapException {
+        // short-circuit the LDAP search to return all roles
+        Collection<String> roles = null;
+        try {
+            roles = rolesLookupService.listRoles();
+        } catch (Exception e) {
+            throw new LdapException("Failed to retrieve roles from roles 
lookup service.", e);
+        }
+        List<Entry> entries = new ArrayList<>();
+        for (String role : roles) {
+            Dn roleDn = new Dn(schemaManager, createGroupDnFromName(role));
+            Entry entry = createRoleEntry(roleDn);
+            entries.add(entry);
+        }
+
+        return new EntryFilteringCursorImpl(new ListCursor<>(entries), ctx, 
schemaManager);
+    }
+
+    private EntryFilteringCursor handleSearch(SearchOperationContext ctx) 
throws LdapException {
+        // Replace the role dn with the member dns if the search filter 
contains a "memberOf" node.
+        ExprNode filter = ctx.getFilter();
+        ReverseRoleLookupMappingVisitor reverseRoleLookupMappingVisitor =
+                new ReverseRoleLookupMappingVisitor(schemaManager, 
rolesLookupService, this::createGroupDnFromName);
+        Object updatedFilter = filter.accept(reverseRoleLookupMappingVisitor);

Review Comment:
   done



##########
gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/backend/LdapProxyBackend.java:
##########
@@ -576,6 +586,54 @@ public List<Entry> search(String searchBase, SearchScope 
searchScope, String fil
         }
     }
 
+    private String mapMemberOfExpression(String filter, SchemaManager 
schemaManager) throws Exception {
+        if (useMemberOf || !filter.toLowerCase(ROOT).contains("memberof")) {
+            return filter;
+        }
+        // Convert filter if it contains "memberOf" but the backend doesn't 
support "memberOf"
+        MemberOfMappingVisitor visitor = new 
MemberOfMappingVisitor(schemaManager, this::lookupGroup, this::isUser);
+        ExprNode node = FilterParser.parse(schemaManager, filter);

Review Comment:
   moved the filter cleanup to LdapProxyBackend to run before either filter is 
applied





Issue Time Tracking
-------------------

    Worklog Id:     (was: 1048383)
    Time Spent: 1h 20m  (was: 1h 10m)

> LDAP Proxy find all members of a role
> -------------------------------------
>
>                 Key: KNOX-3487
>                 URL: https://issues.apache.org/jira/browse/KNOX-3487
>             Project: Apache Knox
>          Issue Type: Improvement
>          Components: Server
>    Affects Versions: 3.1.0
>            Reporter: David Han
>            Assignee: David Han
>            Priority: Major
>             Fix For: 3.1.0
>
>          Time Spent: 1h 20m
>  Remaining Estimate: 0h
>
> When role lookup is enabled on the LDAP Proxy, the LDAP Proxy should be able 
> to return all users that are assigned a role. E.g., 
> {code}
>  ldapsearch  -b 'ou=users,DC=proxy,DC=com' -s sub 
> '(memberOf=cn=rolename,ou=groups,dc=proxy,dc=com)' '*'
> {code}
> This would require calling the roles lookup service to get the mapped users 
> and groups for the given role. Then modifying the search filter to replace 
> the rolename with the users and groups.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to