[
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)