You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2015/07/08 01:21:51 UTC

svn commit: r1689773 - in /jackrabbit/oak/trunk/oak-auth-ldap/src: main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/ test/java/org/apache/jackrabbit/oak/security/authentication/ldap/

Author: tripod
Date: Tue Jul  7 23:21:51 2015
New Revision: 1689773

URL: http://svn.apache.org/r1689773
Log:
OAK-2874 enable listUsers to work for more than 1000 external users

- adding test cases

Added:
    jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LargeLdapProviderTest.java
Modified:
    jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
    jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java
    jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java
    jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java

Modified: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java?rev=1689773&r1=1689772&r2=1689773&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java (original)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java Tue Jul  7 23:21:51 2015
@@ -459,9 +459,13 @@ public class LdapIdentityProvider implem
             Entry entry = connection.lookup(ref.getId());
             timer.mark("lookup");
             Attribute attr = entry.get(config.getGroupMemberAttribute());
-            for (Value value: attr) {
-                ExternalIdentityRef memberRef = new ExternalIdentityRef(value.getString(), this.getName());
-                members.put(memberRef.getId(), memberRef);
+            if (attr == null) {
+                log.warn("LDAP group does not have configured attribute: {}", config.getGroupMemberAttribute());
+            } else {
+                for (Value value: attr) {
+                    ExternalIdentityRef memberRef = new ExternalIdentityRef(value.getString(), this.getName());
+                    members.put(memberRef.getId(), memberRef);
+                }
             }
             timer.mark("iterate");
             if (log.isDebugEnabled()) {

Modified: jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java?rev=1689773&r1=1689772&r2=1689773&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java (original)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java Tue Jul  7 23:21:51 2015
@@ -39,6 +39,8 @@ import javax.naming.ldap.LdapContext;
 import org.apache.commons.io.FileUtils;
 import org.apache.directory.api.ldap.model.constants.SupportedSaslMechanisms;
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.ldif.LdifEntry;
 import org.apache.directory.api.ldap.model.ldif.LdifReader;
 import org.apache.directory.api.ldap.model.name.Dn;
@@ -73,6 +75,9 @@ import org.slf4j.LoggerFactory;
  * A simple ldap test server
  */
 public abstract class AbstractServer {
+
+    public static final String  EXAMPLE_DN = "dc=example,dc=com";
+
     private static final Logger LOG = LoggerFactory.getLogger(AbstractServer.class);
     private static final List<LdifEntry> EMPTY_LIST = Collections.unmodifiableList(new ArrayList<LdifEntry>(0));
     private static final String CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
@@ -209,21 +214,72 @@ public abstract class AbstractServer {
         sysPart.setSuffixDn(directoryService.getDnFactory().create(ServerDNConstants.SYSTEM_DN));
         directoryService.setSystemPartition(sysPart);
 
+        LdifPartition examplePart = new LdifPartition(directoryService.getSchemaManager(), directoryService.getDnFactory());
+        examplePart.setId("example");
+        examplePart.setPartitionPath(new File(directoryService.getInstanceLayout().getPartitionsDirectory(), "example").toURI());
+        examplePart.setSuffixDn(directoryService.getDnFactory().create(EXAMPLE_DN));
+        examplePart.setCacheService(cache);
+        directoryService.addPartition(examplePart);
+
         // setup ldap server
         port = AvailablePortFinder.getNextAvailable(1024);
         ldapServer = new LdapServer();
-        ldapServer.setTransports(new TcpTransport(port));
-        ldapServer.setDirectoryService(directoryService);
-
+        setupLdapServer();
         setupSaslMechanisms();
 
         directoryService.startup();
+        setupExamplePartition();
+        ldapServer.start();
+        setContexts(ServerDNConstants.ADMIN_SYSTEM_DN, "secret");
+    }
 
+    protected void setupLdapServer() throws Exception {
+        ldapServer.setTransports(new TcpTransport(port));
+        ldapServer.setDirectoryService(directoryService);
         ldapServer.addExtendedOperationHandler(new StartTlsHandler());
         ldapServer.addExtendedOperationHandler(new StoredProcedureExtendedOperationHandler());
+    }
 
-        ldapServer.start();
-        setContexts(ServerDNConstants.ADMIN_SYSTEM_DN, "secret");
+    protected void setupExamplePartition() throws Exception {
+        // setup acl to allow read all users
+        // Inject the context entry for dc=example,dc=com partition if it does not already exist
+        try {
+            directoryService.getAdminSession().lookup(new Dn(EXAMPLE_DN));
+        } catch (LdapException lnnfe) {
+            Entry entry = directoryService.newEntry(new Dn(EXAMPLE_DN));
+            entry.add("objectClass", "top", "domain", "extensibleObject");
+            entry.add("dc", "example");
+            entry.add("administrativeRole", "accessControlSpecificArea");
+            directoryService.getAdminSession().add(entry);
+
+            entry = directoryService.newEntry(new Dn("cn=enableSearchForAllUsers," + EXAMPLE_DN));
+            entry.add("objectClass", "top", "subentry", "accessControlSubentry");
+            entry.add("cn", "enableSearchForAllUsers");
+            entry.add("subtreeSpecification", "{}");
+            entry.add("prescriptiveACI",
+                    "{ \n" +
+                            "  identificationTag \"enableSearchForAllUsers\",\n" +
+                            "  precedence 14,\n" +
+                            "  authenticationLevel simple,\n" +
+                            "  itemOrUserFirst userFirst: \n" +
+                            "  { \n" +
+                            "    userClasses { allUsers }, \n" +
+                            "    userPermissions \n" +
+                            "    { \n" +
+                            "      {\n" +
+                            "        protectedItems {entry, allUserAttributeTypesAndValues}, \n" +
+                            "        grantsAndDenials { grantRead, grantReturnDN, grantBrowse } \n" +
+                            "      }\n" +
+                            "    } \n" +
+                            "  } \n" +
+                            "}");
+            directoryService.getAdminSession().add(entry);
+            directoryService.sync();
+        }
+    }
+
+    public void setMaxSizeLimit(long maxSizeLimit) {
+        ldapServer.setMaxSizeLimit(maxSizeLimit);
     }
 
     private void setupSaslMechanisms() {

Modified: jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java?rev=1689773&r1=1689772&r2=1689773&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java (original)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java Tue Jul  7 23:21:51 2015
@@ -20,8 +20,6 @@ import javax.naming.directory.BasicAttri
 import javax.naming.directory.DirContext;
 import javax.naming.ldap.LdapContext;
 
-import org.apache.directory.server.constants.ServerDNConstants;
-
 class InternalLdapServer extends AbstractServer {
 
     public static final String GROUP_MEMBER_ATTR = "member";
@@ -48,21 +46,25 @@ class InternalLdapServer extends Abstrac
         String dn = buildDn(cn, false);
         StringBuilder entries = new StringBuilder();
         entries.append("dn: ").append(dn).append('\n')
-                .append("objectClass: inetOrgPerson\n").append("cn: ").append(cn)
-                .append('\n').append("sn: ").append(lastName)
-                .append('\n').append("givenName:").append(firstName)
-                .append('\n').append("uid: ").append(userId)
-                .append('\n').append("userPassword: ").append(password).append("\n\n");
+                .append("objectClass: inetOrgPerson\n")
+                .append("cn: ").append(cn).append('\n')
+                .append("sn: ").append(lastName).append('\n')
+                .append("givenName:").append(firstName).append('\n')
+                .append("uid: ").append(userId).append('\n')
+                .append("userPassword: ").append(password).append("\n")
+                .append("\n");
         addEntry(entries.toString());
         return dn;
     }
 
-    public String addGroup(String name) throws Exception {
+    public String addGroup(String name, String member) throws Exception {
         String dn = buildDn(name, true);
         StringBuilder entries = new StringBuilder();
-        entries.append("dn: ").append(dn).append('\n').append("objectClass: ")
-                .append(GROUP_CLASS_ATTR).append('\n').append(GROUP_MEMBER_ATTR)
-                .append(":\n").append("cn: ").append(name).append("\n\n");
+        entries.append("dn: ").append(dn).append('\n')
+                .append("objectClass: ").append(GROUP_CLASS_ATTR).append('\n')
+                .append(GROUP_MEMBER_ATTR).append(":").append(member).append("\n")
+                .append("cn: ").append(name).append("\n")
+                .append("\n");
         addEntry(entries.toString());
         return dn;
     }
@@ -83,12 +85,7 @@ class InternalLdapServer extends Abstrac
 
     private static String buildDn(String name, boolean isGroup) {
         StringBuilder dn = new StringBuilder();
-        dn.append("cn=").append(name).append(',');
-        if (isGroup) {
-            dn.append(ServerDNConstants.GROUPS_SYSTEM_DN);
-        } else {
-            dn.append(ServerDNConstants.USERS_SYSTEM_DN);
-        }
+        dn.append("cn=").append(name).append(',').append(EXAMPLE_DN);
         return dn.toString();
     }
 }

Added: jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LargeLdapProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LargeLdapProviderTest.java?rev=1689773&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LargeLdapProviderTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LargeLdapProviderTest.java Tue Jul  7 23:21:51 2015
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.oak.security.authentication.ldap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapIdentityProvider;
+import org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapProviderConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+import org.apache.jackrabbit.util.Text;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+public class LargeLdapProviderTest {
+
+    protected static final InternalLdapServer LDAP_SERVER = new InternalLdapServer();
+
+    //initialize LDAP server only once (fast, but might turn out to be not sufficiently flexible in the future)
+    protected static final boolean USE_COMMON_LDAP_FIXTURE = false;
+
+    public static final String IDP_NAME = "ldap";
+
+    protected static final String GROUP_NAME = "foobargroup";
+
+    protected static String GROUP_DN;
+
+    protected static String[] TEST_MEMBERS;
+
+    protected static int NUM_USERS = 100;
+
+    protected static int SIZE_LIMIT = 50;
+
+    protected LdapIdentityProvider idp;
+
+    protected LdapProviderConfig providerConfig;
+
+    @BeforeClass
+    public static void beforeClass() throws Exception {
+        if (USE_COMMON_LDAP_FIXTURE) {
+            LDAP_SERVER.setUp();
+            LDAP_SERVER.setMaxSizeLimit(SIZE_LIMIT);
+            initLdapFixture(LDAP_SERVER);
+        }
+    }
+
+    @AfterClass
+    public static void afterClass() throws Exception {
+        if (USE_COMMON_LDAP_FIXTURE) {
+            LDAP_SERVER.tearDown();
+        }
+    }
+
+    @Before
+    public void before() throws Exception {
+        if (!USE_COMMON_LDAP_FIXTURE) {
+            LDAP_SERVER.setUp();
+            LDAP_SERVER.setMaxSizeLimit(SIZE_LIMIT);
+            initLdapFixture(LDAP_SERVER);
+        }
+        idp = createIDP();
+    }
+
+    @After
+    public void after() throws Exception {
+        if (!USE_COMMON_LDAP_FIXTURE) {
+            LDAP_SERVER.tearDown();
+        }
+        idp.close();
+        idp = null;
+    }
+
+    protected LdapIdentityProvider createIDP() {
+        providerConfig = new LdapProviderConfig()
+                .setName(IDP_NAME)
+                .setHostname("127.0.0.1")
+                .setPort(LDAP_SERVER.getPort())
+                .setBindDN(USER_DN)
+                .setBindPassword(USER_PWD)
+                .setGroupMemberAttribute("member");
+
+        providerConfig.getUserConfig()
+                .setBaseDN(AbstractServer.EXAMPLE_DN)
+                .setObjectClasses("inetOrgPerson");
+
+        providerConfig.getGroupConfig()
+                .setBaseDN(AbstractServer.EXAMPLE_DN)
+                .setObjectClasses(InternalLdapServer.GROUP_CLASS_ATTR);
+
+        providerConfig.getAdminPoolConfig().setMaxActive(0);
+        providerConfig.getUserPoolConfig().setMaxActive(0);
+        return new LdapIdentityProvider(providerConfig);
+    }
+
+    protected static final String USER_ID = "foobar";
+    protected static final String USER_PWD = "foobar";
+    protected static final String USER_FIRSTNAME = "Foo";
+    protected static final String USER_LASTNAME = "Bar";
+
+    protected static String USER_DN;
+
+    protected static void initLdapFixture(InternalLdapServer server) throws Exception {
+        ArrayList<String> members = new ArrayList<String>();
+
+        USER_DN = LDAP_SERVER.addUser(USER_FIRSTNAME, USER_LASTNAME, USER_ID, USER_PWD);
+        GROUP_DN = server.addGroup(GROUP_NAME, USER_DN);
+        members.add(USER_DN);
+
+        for (int i = 0; i < NUM_USERS; i++) {
+            final String userId = "user-" + i;
+            String userDN = server.addUser(userId, "test", userId, "test");
+            LDAP_SERVER.addMember(GROUP_DN, userDN);
+            members.add(userDN);
+        }
+        TEST_MEMBERS = members.toArray(new String[members.size()]);
+    }
+
+
+    @Test
+    public void testGetMembers() throws Exception {
+        ExternalIdentityRef ref = new ExternalIdentityRef(GROUP_DN, IDP_NAME);
+        ExternalIdentity id = idp.getIdentity(ref);
+        assertTrue("Group instance", id instanceof ExternalGroup);
+
+        ExternalGroup grp = (ExternalGroup) id;
+        assertIfEquals("Group members", TEST_MEMBERS, grp.getDeclaredMembers());
+    }
+
+    @Test
+    @Ignore("OAK-2874")
+    public void testListUsers() throws Exception {
+        Iterator<ExternalUser> users = idp.listUsers();
+        List<ExternalIdentityRef> refs = new ArrayList<ExternalIdentityRef>();
+        while (users.hasNext()) {
+            refs.add(users.next().getExternalId());
+        }
+        assertIfEquals("Test users", TEST_MEMBERS, refs);
+    }
+
+    public static void assertIfEquals(String message, String[] expected, Iterable<ExternalIdentityRef> result) {
+        List<String> dns = new LinkedList<String>();
+        for (ExternalIdentityRef ref: result) {
+            dns.add(ref.getId());
+        }
+        Collections.sort(dns);
+        Arrays.sort(expected);
+        String exp = Text.implode(expected, ",\n");
+        String res = Text.implode(dns.toArray(new String[dns.size()]), ",\n");
+        assertEquals(message, exp, res);
+    }
+
+}

Modified: jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java?rev=1689773&r1=1689772&r2=1689773&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java (original)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java Tue Jul  7 23:21:51 2015
@@ -151,10 +151,10 @@ public abstract class LdapLoginTestBase
                 .setGroupMemberAttribute(InternalLdapServer.GROUP_MEMBER_ATTR);
 
         cfg.getUserConfig()
-                .setBaseDN(ServerDNConstants.USERS_SYSTEM_DN)
+                .setBaseDN(AbstractServer.EXAMPLE_DN)
                 .setObjectClasses("inetOrgPerson");
         cfg.getGroupConfig()
-                .setBaseDN(ServerDNConstants.GROUPS_SYSTEM_DN)
+                .setBaseDN(AbstractServer.EXAMPLE_DN)
                 .setObjectClasses(InternalLdapServer.GROUP_CLASS_ATTR);
 
         cfg.getAdminPoolConfig().setMaxActive(0);
@@ -394,12 +394,11 @@ public abstract class LdapLoginTestBase
     }
 
     protected static void createLdapFixture() throws Exception {
-        LDAP_SERVER.addMember(
-                GROUP_DN = LDAP_SERVER.addGroup(GROUP_NAME),
-                LDAP_SERVER.addUser(USER_FIRSTNAME, USER_LASTNAME, USER_ID, USER_PWD));
+        String userDN = LDAP_SERVER.addUser(USER_FIRSTNAME, USER_LASTNAME, USER_ID, USER_PWD);
+        GROUP_DN = LDAP_SERVER.addGroup(GROUP_NAME, userDN);
         for (int i = 0; i < NUM_CONCURRENT_LOGINS * 2; i++) {
             final String userId = "user-" + i;
-            String userDN = LDAP_SERVER.addUser(userId, "test", userId, USER_PWD);
+            userDN = LDAP_SERVER.addUser(userId, "test", userId, USER_PWD);
             if (i%2 == 0) {
                 CONCURRENT_GROUP_TEST_USERS[i/2] = userId;
                 LDAP_SERVER.addMember(GROUP_DN, userDN);