Repository: knox
Updated Branches:
  refs/heads/master 6eb64e525 -> 62a75e0e0


KNOX-644 - Limit/page results of LDAP group membership search (Kevin Risden via 
lmccay)

Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/62a75e0e
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/62a75e0e
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/62a75e0e

Branch: refs/heads/master
Commit: 62a75e0e015ae35f27a08e156f792b6e5517fb6a
Parents: 6eb64e5
Author: Larry McCay <lmc...@hortonworks.com>
Authored: Sun Oct 2 13:01:34 2016 -0400
Committer: Larry McCay <lmc...@hortonworks.com>
Committed: Sun Oct 2 13:01:34 2016 -0400

----------------------------------------------------------------------
 .../ldap/BaseDirectoryServiceFactory.java       |   4 +-
 .../ldap/SimpleLdapDirectoryServer.java         |   4 +-
 .../gateway/shirorealm/KnoxLdapRealm.java       | 105 +++++++++++++------
 .../apache/hadoop/gateway/GatewayMessages.java  |   9 ++
 pom.xml                                         |   2 +-
 5 files changed, 89 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/62a75e0e/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/BaseDirectoryServiceFactory.java
----------------------------------------------------------------------
diff --git 
a/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/BaseDirectoryServiceFactory.java
 
b/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/BaseDirectoryServiceFactory.java
index dc3468d..2d2bc1f 100644
--- 
a/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/BaseDirectoryServiceFactory.java
+++ 
b/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/BaseDirectoryServiceFactory.java
@@ -206,7 +206,7 @@ public class BaseDirectoryServiceFactory implements 
DirectoryServiceFactory
     directoryService.setSchemaManager( schemaManager );
 
     // Init the LdifPartition
-    LdifPartition ldifPartition = new LdifPartition( schemaManager /*, 
directoryService.getDnFactory()*/ );
+    LdifPartition ldifPartition = new LdifPartition( schemaManager, 
directoryService.getDnFactory() );
     ldifPartition.setPartitionPath( new File( workingDirectory, "schema" 
).toURI() );
     SchemaPartition schemaPartition = new SchemaPartition( schemaManager );
     schemaPartition.setWrappedPartition( ldifPartition );
@@ -235,7 +235,7 @@ public class BaseDirectoryServiceFactory implements 
DirectoryServiceFactory
     // Inject the System Partition
     Partition systemPartition = partitionFactory.createPartition(
         directoryService.getSchemaManager(),
-        //directoryService.getDnFactory(),
+        directoryService.getDnFactory(),
         "system",
         ServerDNConstants.SYSTEM_DN,
         500,

http://git-wip-us.apache.org/repos/asf/knox/blob/62a75e0e/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/SimpleLdapDirectoryServer.java
----------------------------------------------------------------------
diff --git 
a/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/SimpleLdapDirectoryServer.java
 
b/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/SimpleLdapDirectoryServer.java
index efa8df8..12fe30d 100644
--- 
a/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/SimpleLdapDirectoryServer.java
+++ 
b/gateway-demo-ldap/src/main/java/org/apache/hadoop/gateway/security/ldap/SimpleLdapDirectoryServer.java
@@ -57,7 +57,8 @@ public class SimpleLdapDirectoryServer {
     enabledPosixSchema( service );
 
     Partition partition = factory.getPartitionFactory().createPartition(
-        service.getSchemaManager(), "users", rootDn, 500, 
service.getInstanceLayout().getInstanceDirectory() );
+        service.getSchemaManager(), service.getDnFactory(), "users", rootDn, 
500,
+        service.getInstanceLayout().getInstanceDirectory() );
     service.addPartition( partition );
 
     CoreSession session = service.getAdminSession();
@@ -67,7 +68,6 @@ public class SimpleLdapDirectoryServer {
     server = new LdapServer();
     server.setTransports( transports );
     server.setDirectoryService( service );
-
   }
 
   private static void enabledPosixSchema( DirectoryService service ) throws 
LdapException {

http://git-wip-us.apache.org/repos/asf/knox/blob/62a75e0e/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/shirorealm/KnoxLdapRealm.java
----------------------------------------------------------------------
diff --git 
a/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/shirorealm/KnoxLdapRealm.java
 
b/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/shirorealm/KnoxLdapRealm.java
index eb1e862..4cfc7e9 100644
--- 
a/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/shirorealm/KnoxLdapRealm.java
+++ 
b/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/shirorealm/KnoxLdapRealm.java
@@ -19,6 +19,7 @@
 
 package org.apache.hadoop.gateway.shirorealm;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -33,13 +34,19 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.naming.AuthenticationException;
+import javax.naming.Context;
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
+import javax.naming.PartialResultException;
+import javax.naming.SizeLimitExceededException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.SearchControls;
 import javax.naming.directory.SearchResult;
+import javax.naming.ldap.Control;
 import javax.naming.ldap.LdapContext;
 import javax.naming.ldap.LdapName;
+import javax.naming.ldap.PagedResultsControl;
+import javax.naming.ldap.PagedResultsResponseControl;
 
 import org.apache.hadoop.gateway.GatewayMessages;
 import org.apache.hadoop.gateway.audit.api.Action;
@@ -245,43 +252,81 @@ public class KnoxLdapRealm extends JndiLdapRealm {
 
     private Set<String> rolesFor(PrincipalCollection principals, final String 
userName, final LdapContext ldapCtx,
         final LdapContextFactory ldapContextFactory) throws NamingException {
-        final Set<String> roleNames = new HashSet();
-        final Set<String> groupNames = new HashSet();
-        NamingEnumeration<SearchResult> searchResultEnum = null;
-        try {
+      final Set<String> roleNames = new HashSet<>();
+      final Set<String> groupNames = new HashSet<>();
+
+      String userDn;
+      if (userSearchAttributeName == null || 
userSearchAttributeName.isEmpty()) {
+        // memberAttributeValuePrefix and memberAttributeValueSuffix were 
computed from memberAttributeValueTemplate
+        userDn = memberAttributeValuePrefix + userName + 
memberAttributeValueSuffix;
+      } else {
+        userDn = getUserDn(userName);
+      }
+
+      // Activate paged results
+      int pageSize = 100;
+      int numResults = 0;
+      byte[] cookie = null;
+      try {
+        ldapCtx.addToEnvironment(Context.REFERRAL, "ignore");
+
+        ldapCtx.setRequestControls(new Control[]{new 
PagedResultsControl(pageSize, Control.NONCRITICAL)});
+
+        do {
           // ldapsearch -h localhost -p 33389 -D 
uid=guest,ou=people,dc=hadoop,dc=apache,dc=org -w  guest-password
           //       -b dc=hadoop,dc=apache,dc=org -s sub '(objectclass=*)'
-          searchResultEnum = ldapCtx.search(
-              getGroupSearchBase(),
-              "objectClass=" + groupObjectClass,
-              SUBTREE_SCOPE);
-          
-          String userDn = null;
-          if (userSearchAttributeName == null || 
userSearchAttributeName.isEmpty()) {
-            // memberAttributeValuePrefix and memberAttributeValueSuffix were 
computed from memberAttributeValueTemplate
-            userDn = memberAttributeValuePrefix + userName + 
memberAttributeValueSuffix;
-          } else {
-            userDn = getUserDn(userName);
-          }
-          while (searchResultEnum.hasMore()) { // searchResults contains all 
the groups in search scope
+
+          NamingEnumeration<SearchResult> searchResultEnum = null;
+          try {
+            searchResultEnum = ldapCtx.search(
+                getGroupSearchBase(),
+                "objectClass=" + groupObjectClass,
+                SUBTREE_SCOPE);
+
+            while (searchResultEnum != null && searchResultEnum.hasMore()) { 
// searchResults contains all the groups in search scope
+              numResults++;
               final SearchResult group = searchResultEnum.next();
               addRoleIfMember(userDn, group, roleNames, groupNames, 
ldapContextFactory);
+            }
+          } catch (PartialResultException e) {
+            LOG.ignoringPartialResultException();
+          } finally {
+            if (searchResultEnum != null) {
+              searchResultEnum.close();
+            }
           }
 
-          // save role names and group names in session so that they can be 
easily looked up outside of this object
-          
SecurityUtils.getSubject().getSession().setAttribute(SUBJECT_USER_ROLES, 
roleNames);
-          
SecurityUtils.getSubject().getSession().setAttribute(SUBJECT_USER_GROUPS, 
groupNames);
-          if (!groupNames.isEmpty() && (principals instanceof 
MutablePrincipalCollection)) {
-            ((MutablePrincipalCollection)principals).addAll(groupNames, 
getName());
-          }
-          LOG.lookedUpUserRoles(roleNames, userName);
-        }
-        finally {
-          if (searchResultEnum != null) {
-            searchResultEnum.close();
+          // Examine the paged results control response
+          Control[] controls = ldapCtx.getResponseControls();
+          if (controls != null) {
+            for (Control control : controls) {
+              if (control instanceof PagedResultsResponseControl) {
+                PagedResultsResponseControl prrc = 
(PagedResultsResponseControl) control;
+                cookie = prrc.getCookie();
+              }
+            }
           }
-        }
-        return roleNames;
+
+          // Re-activate paged results
+          ldapCtx.setRequestControls(new Control[]{new 
PagedResultsControl(pageSize, cookie, Control.CRITICAL)});
+        } while (cookie != null);
+      } catch (SizeLimitExceededException e) {
+        LOG.sizeLimitExceededOnlyRetrieved(numResults);
+//        System.out.println("Only retrieved first " + numResults + " groups 
due to SizeLimitExceededException.");
+      } catch(IOException e) {
+        LOG.unableToSetupPagedResults();
+//        System.out.println("Unabled to setup paged results");
+      }
+
+      // save role names and group names in session so that they can be easily 
looked up outside of this object
+      SecurityUtils.getSubject().getSession().setAttribute(SUBJECT_USER_ROLES, 
roleNames);
+      
SecurityUtils.getSubject().getSession().setAttribute(SUBJECT_USER_GROUPS, 
groupNames);
+      if (!groupNames.isEmpty() && (principals instanceof 
MutablePrincipalCollection)) {
+        ((MutablePrincipalCollection)principals).addAll(groupNames, getName());
+      }
+      LOG.lookedUpUserRoles(roleNames, userName);
+
+      return roleNames;
     }
 
   private void addRoleIfMember(final String userDn, final SearchResult group,

http://git-wip-us.apache.org/repos/asf/knox/blob/62a75e0e/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
----------------------------------------------------------------------
diff --git 
a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java 
b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
index c9dc3b2..c256a65 100644
--- 
a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
+++ 
b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
@@ -412,4 +412,13 @@ public interface GatewayMessages {
 
   @Message( level = MessageLevel.DEBUG, text = "Default topology forward from 
{0} to {1}" )
   void defaultTopologyForward( String oldTarget, String newTarget );
+
+  @Message( level = MessageLevel.ERROR, text = "Unable to setup PagedResults" )
+  void unableToSetupPagedResults();
+
+  @Message( level = MessageLevel.INFO, text = "Ignoring 
PartialResultException" )
+  void ignoringPartialResultException();
+
+  @Message( level = MessageLevel.WARN, text = "Only retrieved first {0} groups 
due to SizeLimitExceededException." )
+  void sizeLimitExceededOnlyRetrieved(int numResults);
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/62a75e0e/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 50371b1..6746163 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1019,7 +1019,7 @@
             <dependency>
                 <groupId>org.apache.directory.server</groupId>
                 <artifactId>apacheds-all</artifactId>
-                <version>2.0.0-M15</version>
+                <version>2.0.0-M16</version>
                 <exclusions>
                     <exclusion>
                         <groupId>ldapsdk</groupId>

Reply via email to