[
https://issues.apache.org/jira/browse/KNOX-3487?focusedWorklogId=1048381&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1048381
]
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_r4322445212
##########
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;
Review Comment:
fixed to use separate criteria for the group search base and ancestor DNs.
##########
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);
Review Comment:
`anyMatch` is correct for searches on the `proxyGroupSearchBase`. This
criteria is too loose for searches on the ancestors or the root. This is solved
by splitting the filter examination depending on whether the search base is the
complete `proxyGroupSearchBase` or an ancestor.
##########
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);
+ // Baseline in the same form as the visitor output so an unchanged
visit exits on the first pass
+ String current = node.toString();
+ for (int i = 0; i < recursiveGroupResolutionMaxDepth; ++i) {
+ Object visitedNode = node.accept(visitor);
+ if (!(visitedNode instanceof ExprNode)) {
+ throw new Exception("Unable to transform memberOf expressions
in filter: " + filter);
+ }
+ node = (ExprNode) visitedNode;
+ String updated = node.toString();
+ if (updated.equals(current)) {
+ break;
+ }
+ current = updated;
+ }
+ return current;
+ }
+
+ private Entry lookupGroup(String dn, SchemaManager schemaManager) throws
Exception {
+ String remoteDn = remoteSchemaConverter.convertProxyDnToRemoteDn(dn);
+ LdapConnection connection = null;
+ try {
+ connection = getConnection();
+ Entry entry = connection.lookup(remoteDn);
+ if (entry != null) {
+ return
remoteSchemaConverter.convertRemoteEntryToProxyEntry(entry, schemaManager);
+ } else {
+ return null;
+ }
+ } finally {
+ releaseConnection(connection);
+ }
+ }
+
+ private boolean isUser(String userDn) {
+ if (userDn == null) {
+ return false;
+ }
+ String lowerCaseUserDn = userDn.toLowerCase(ROOT);
+ return lowerCaseUserDn.contains(proxyUserSearchBase) ||
lowerCaseUserDn.contains(remoteUserObjectClass);
Review Comment:
switched string handling to DN handling and check against both proxy and
backend user search base.
Issue Time Tracking
-------------------
Worklog Id: (was: 1048381)
Time Spent: 1h (was: 50m)
> 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
> 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)