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
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]