You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by rc...@apache.org on 2020/03/06 03:07:20 UTC

[james-project] 19/21: JAMES-3087 LDAP user listing should filter out users without id field

This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit ffcbce782b52b409420d3209186c74f4d52a0c87
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Mar 5 10:41:16 2020 +0700

    JAMES-3087 LDAP user listing should filter out users without id field
    
    Before that a NPE was returned.
---
 .../user/ldap/ReadOnlyUsersLDAPRepository.java     | 20 +++--
 .../james/user/ldap/LdapGenericContainer.java      | 13 ++-
 .../ReadOnlyUsersLDAPRepositoryInvalidDnTest.java  | 96 ++++++++++++++++++++++
 .../user/ldap/ReadOnlyUsersLDAPRepositoryTest.java | 66 ++++++++++-----
 .../test/resources/invalid/ldif-files/Dockerfile   |  3 +
 .../resources/invalid/ldif-files/populate.ldif     | 11 +++
 6 files changed, 180 insertions(+), 29 deletions(-)

diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepository.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepository.java
index ebbd794..e9af7ac 100644
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepository.java
+++ b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepository.java
@@ -54,12 +54,14 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.user.api.model.User;
 import org.apache.james.user.ldap.api.LdapConstants;
+import org.apache.james.util.OptionalUtils;
 import org.apache.james.util.retry.DoublingRetrySchedule;
 import org.apache.james.util.retry.api.RetrySchedule;
 import org.apache.james.util.retry.naming.ldap.RetryingLdapContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.fge.lambdas.Throwing;
 import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Strings;
 
@@ -450,8 +452,8 @@ public class ReadOnlyUsersLDAPRepository implements UsersRepository, Configurabl
         List<ReadOnlyLDAPUser> results = new ArrayList<>();
 
         for (String userDN : userDNs) {
-            ReadOnlyLDAPUser user = buildUser(userDN);
-            results.add(user);
+            Optional<ReadOnlyLDAPUser> user = buildUser(userDN);
+            user.ifPresent(results::add);
         }
 
         return results;
@@ -518,10 +520,13 @@ public class ReadOnlyUsersLDAPRepository implements UsersRepository, Configurabl
      * @throws NamingException
      *             Propagated by the underlying LDAP communication layer.
      */
-    private ReadOnlyLDAPUser buildUser(String userDN) throws NamingException {
+    private Optional<ReadOnlyLDAPUser> buildUser(String userDN) throws NamingException {
       Attributes userAttributes = ldapContext.getAttributes(userDN);
-      Attribute userName = userAttributes.get(ldapConfiguration.getUserIdAttribute());
-      return new ReadOnlyLDAPUser(Username.of(userName.get().toString()), userDN, ldapContext);
+      Optional<Attribute> userName = Optional.ofNullable(userAttributes.get(ldapConfiguration.getUserIdAttribute()));
+      return userName
+          .map(Throwing.<Attribute, String>function(u -> u.get().toString()).sneakyThrow())
+          .map(Username::of)
+          .map(username -> new ReadOnlyLDAPUser(username, userDN, ldapContext));
     }
 
     @Override
@@ -537,7 +542,10 @@ public class ReadOnlyUsersLDAPRepository implements UsersRepository, Configurabl
     @Override
     public int countUsers() throws UsersRepositoryException {
         try {
-            return getValidUsers().size();
+            return Math.toIntExact(getValidUsers().stream()
+                .map(Throwing.function(this::buildUser).sneakyThrow())
+                .flatMap(OptionalUtils::toStream)
+                .count());
         } catch (NamingException e) {
             LOGGER.error("Unable to retrieve user count from ldap", e);
             throw new UsersRepositoryException("Unable to retrieve user count from ldap", e);
diff --git a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/LdapGenericContainer.java b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/LdapGenericContainer.java
index 050fe4f..36133f9 100644
--- a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/LdapGenericContainer.java
+++ b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/LdapGenericContainer.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.user.ldap;
 
+import java.util.Optional;
+
 import org.apache.james.util.docker.DockerContainer;
 import org.apache.james.util.docker.RateLimiters;
 import org.junit.rules.ExternalResource;
@@ -36,13 +38,18 @@ public class LdapGenericContainer extends ExternalResource {
     }
 
     public static class Builder {
-
+        private Optional<String> dockerFilePrefix = Optional.empty();
         private String domain;
         private String password;
 
         private Builder() {
         }
 
+        public Builder dockerFilePrefix(String prefix) {
+            this.dockerFilePrefix = Optional.of(prefix);
+            return this;
+        }
+
         public Builder domain(String domain) {
             this.domain = domain;
             return this;
@@ -62,8 +69,8 @@ public class LdapGenericContainer extends ExternalResource {
         private DockerContainer createContainer() {
             return DockerContainer.fromDockerfile(
                 new ImageFromDockerfile()
-                    .withFileFromClasspath("populate.ldif", "ldif-files/populate.ldif")
-                    .withFileFromClasspath("Dockerfile", "ldif-files/Dockerfile"))
+                    .withFileFromClasspath("populate.ldif", dockerFilePrefix.orElse("") + "ldif-files/populate.ldif")
+                    .withFileFromClasspath("Dockerfile", dockerFilePrefix.orElse("") + "ldif-files/Dockerfile"))
                 .withAffinityToContainer()
                 .withEnv("SLAPD_DOMAIN", domain)
                 .withEnv("SLAPD_PASSWORD", password)
diff --git a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryInvalidDnTest.java b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryInvalidDnTest.java
new file mode 100644
index 0000000..33fd239
--- /dev/null
+++ b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryInvalidDnTest.java
@@ -0,0 +1,96 @@
+/****************************************************************
+ * 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.james.user.ldap;
+
+import static org.apache.james.user.ldap.DockerLdapSingleton.ADMIN_PASSWORD;
+import static org.apache.james.user.ldap.DockerLdapSingleton.DOMAIN;
+import static org.apache.james.user.ldap.DockerLdapSingleton.JAMES_USER;
+import static org.apache.james.user.ldap.ReadOnlyUsersLDAPRepositoryTest.ldapRepositoryConfigurationWithVirtualHosting;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.apache.commons.configuration2.HierarchicalConfiguration;
+import org.apache.commons.configuration2.plist.PropertyListConfiguration;
+import org.apache.commons.configuration2.tree.ImmutableNode;
+import org.apache.james.core.Username;
+import org.apache.james.domainlist.api.DomainList;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+class ReadOnlyUsersLDAPRepositoryInvalidDnTest {
+    static LdapGenericContainer ldapContainer = LdapGenericContainer.builder()
+        .dockerFilePrefix("invalid/")
+        .domain(DOMAIN)
+        .password(ADMIN_PASSWORD)
+        .build();
+
+    DomainList domainList;
+    private ReadOnlyUsersLDAPRepository ldapRepository;
+
+    @BeforeAll
+    static void setUpAll() {
+        ldapContainer.start();
+    }
+
+    @AfterAll
+    static void afterAll() {
+        ldapContainer.start();
+    }
+
+    @BeforeEach
+    void setUp() throws Exception {
+        domainList = mock(DomainList.class);
+        ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
+    }
+
+    @Test
+    void listShouldFilterOutUsersWithoutIdField() throws Exception {
+        assertThat(ImmutableList.copyOf(ldapRepository.list()))
+            .isEmpty();
+    }
+
+    @Test
+    void getUserByNameShouldReturnNullWhenNoIdField() throws Exception {
+        assertThat(ldapRepository.getUserByName(JAMES_USER)).isNull();
+    }
+
+    @Test
+    void containsShouldReturnFalseWhenNoIdField() throws Exception {
+        assertThat(ldapRepository.contains(JAMES_USER)).isFalse();
+    }
+
+    @Test
+    void contShouldReturnZeroWhenInvalidUser() throws Exception {
+        assertThat(ldapRepository.countUsers()).isEqualTo(0);
+    }
+
+    private ReadOnlyUsersLDAPRepository startUsersRepository(HierarchicalConfiguration<ImmutableNode> ldapRepositoryConfiguration) throws Exception {
+        ReadOnlyUsersLDAPRepository ldapRepository = new ReadOnlyUsersLDAPRepository(domainList);
+        ldapRepository.configure(ldapRepositoryConfiguration);
+        ldapRepository.init();
+        return ldapRepository;
+    }
+}
diff --git a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryTest.java b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryTest.java
index fd26257..6b22f32 100644
--- a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryTest.java
+++ b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryTest.java
@@ -33,12 +33,16 @@ import org.apache.commons.configuration2.plist.PropertyListConfiguration;
 import org.apache.commons.configuration2.tree.ImmutableNode;
 import org.apache.james.core.Username;
 import org.apache.james.domainlist.api.DomainList;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.ImmutableList;
+
 class ReadOnlyUsersLDAPRepositoryTest {
 
     static final Logger LOGGER = LoggerFactory.getLogger(ReadOnlyUsersLDAPRepositoryTest.class);
@@ -46,8 +50,23 @@ class ReadOnlyUsersLDAPRepositoryTest {
     static final Username UNKNOWN = Username.of("unknown");
     static final String BAD_PASSWORD = "badpassword";
 
+    static LdapGenericContainer ldapContainer = LdapGenericContainer.builder()
+        .domain(DOMAIN)
+        .password(ADMIN_PASSWORD)
+        .build();
+
     DomainList domainList;
 
+    @BeforeAll
+    static void setUpAll() {
+        ldapContainer.start();
+    }
+
+    @AfterAll
+    static void afterAll() {
+        ldapContainer.start();
+    }
+
     @BeforeEach
     void setUp() {
         domainList = mock(DomainList.class);
@@ -59,14 +78,14 @@ class ReadOnlyUsersLDAPRepositoryTest {
         @Test
         void supportVirtualHostingShouldReturnFalseByDefault() throws Exception {
             ReadOnlyUsersLDAPRepository usersLDAPRepository = new ReadOnlyUsersLDAPRepository(domainList);
-            usersLDAPRepository.configure(ldapRepositoryConfiguration());
+            usersLDAPRepository.configure(ldapRepositoryConfiguration(ldapContainer));
 
             assertThat(usersLDAPRepository.supportVirtualHosting()).isFalse();
         }
 
         @Test
         void supportVirtualHostingShouldReturnTrueWhenReportedInConfig() throws Exception {
-            HierarchicalConfiguration<ImmutableNode> configuration = ldapRepositoryConfiguration();
+            HierarchicalConfiguration<ImmutableNode> configuration = ldapRepositoryConfiguration(ldapContainer);
             configuration.addProperty(ReadOnlyUsersLDAPRepository.SUPPORTS_VIRTUAL_HOSTING, "true");
 
             ReadOnlyUsersLDAPRepository usersLDAPRepository = new ReadOnlyUsersLDAPRepository(domainList);
@@ -77,7 +96,7 @@ class ReadOnlyUsersLDAPRepositoryTest {
 
         @Test
         void supportVirtualHostingShouldReturnFalseWhenReportedInConfig() throws Exception {
-            HierarchicalConfiguration<ImmutableNode> configuration = ldapRepositoryConfiguration();
+            HierarchicalConfiguration<ImmutableNode> configuration = ldapRepositoryConfiguration(ldapContainer);
             configuration.addProperty(ReadOnlyUsersLDAPRepository.SUPPORTS_VIRTUAL_HOSTING, "false");
 
             ReadOnlyUsersLDAPRepository usersLDAPRepository = new ReadOnlyUsersLDAPRepository(domainList);
@@ -88,7 +107,7 @@ class ReadOnlyUsersLDAPRepositoryTest {
 
         @Test
         void configureShouldThrowOnNonBooleanValueForSupportsVirtualHosting() {
-            HierarchicalConfiguration<ImmutableNode> configuration = ldapRepositoryConfiguration();
+            HierarchicalConfiguration<ImmutableNode> configuration = ldapRepositoryConfiguration(ldapContainer);
             configuration.addProperty(ReadOnlyUsersLDAPRepository.SUPPORTS_VIRTUAL_HOSTING, "bad");
 
             ReadOnlyUsersLDAPRepository usersLDAPRepository = new ReadOnlyUsersLDAPRepository(domainList);
@@ -103,37 +122,44 @@ class ReadOnlyUsersLDAPRepositoryTest {
 
         @Test
         void knownUserShouldBeAbleToLogInWhenPasswordIsCorrect() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration(ldapContainer));
             assertThat(ldapRepository.test(JAMES_USER, PASSWORD)).isTrue();
         }
 
         @Test
         void knownUserShouldNotBeAbleToLogInWhenPasswordIsNotCorrect() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration(ldapContainer));
             assertThat(ldapRepository.test(JAMES_USER, BAD_PASSWORD)).isFalse();
         }
 
         @Test
         void unknownUserShouldNotBeAbleToLogIn() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration(ldapContainer));
             assertThat(ldapRepository.test(UNKNOWN, BAD_PASSWORD)).isFalse();
         }
 
         @Test
         void unknownUserShouldNotBeAbleToLogInWhenPasswordIsCorrect() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration(ldapContainer));
             assertThat(ldapRepository.test(UNKNOWN, PASSWORD)).isFalse();
         }
 
         @Test
         void knownUserShouldBeAbleToLogInWhenPasswordIsCorrectWithVirtualHosting() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
             assertThat(ldapRepository.test(JAMES_USER_MAIL, PASSWORD)).isTrue();
         }
 
         @Test
+        void testShouldListUsers() throws Exception {
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
+            assertThat(ImmutableList.copyOf(ldapRepository.list()))
+                .containsOnly(JAMES_USER_MAIL);
+        }
+
+        @Test
         void testShouldStillWorkAfterRestartingLDAP() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
             ldapRepository.test(JAMES_USER_MAIL, PASSWORD);
 
             DockerLdapSingleton.ldapContainer.pause();
@@ -149,19 +175,19 @@ class ReadOnlyUsersLDAPRepositoryTest {
 
         @Test
         void knownUserShouldNotBeAbleToLogInWhenPasswordIsNotCorrectWithVirtualHosting() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
             assertThat(ldapRepository.test(JAMES_USER, BAD_PASSWORD)).isFalse();
         }
 
         @Test
         void unknownUserShouldNotBeAbleToLogInWithVirtualHosting() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
             assertThat(ldapRepository.test(UNKNOWN, BAD_PASSWORD)).isFalse();
         }
 
         @Test
         void unknownUserShouldNotBeAbleToLogInWhenPasswordIsCorrectWithVirtualHosting() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
             assertThat(ldapRepository.test(UNKNOWN, PASSWORD)).isFalse();
         }
 
@@ -169,19 +195,19 @@ class ReadOnlyUsersLDAPRepositoryTest {
         void specialCharacterInUserInputShouldBeSanitized() throws Exception {
             Username patternMatchingMultipleUsers = Username.of("j*");
 
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
             assertThat(ldapRepository.test(patternMatchingMultipleUsers, PASSWORD)).isFalse();
         }
 
         @Test
         void containsWithGetUserShouldBeTrue() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfiguration(ldapContainer));
             assertThat(ldapRepository.contains(ldapRepository.getUser(JAMES_USER_MAIL.asMailAddress()))).isTrue();
         }
 
         @Test
         void containsWithGetUserShouldBeTrueWithVirtualHosting() throws Exception {
-            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting());
+            ReadOnlyUsersLDAPRepository ldapRepository = startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer));
             assertThat(ldapRepository.contains(ldapRepository.getUser(JAMES_USER_MAIL.asMailAddress()))).isTrue();
         }
 
@@ -193,9 +219,9 @@ class ReadOnlyUsersLDAPRepositoryTest {
         }
     }
 
-    private static HierarchicalConfiguration<ImmutableNode> ldapRepositoryConfiguration() {
+    private HierarchicalConfiguration<ImmutableNode> ldapRepositoryConfiguration(LdapGenericContainer ldapContainer) {
         PropertyListConfiguration configuration = new PropertyListConfiguration();
-        configuration.addProperty("[@ldapHost]", DockerLdapSingleton.ldapContainer.getLdapHost());
+        configuration.addProperty("[@ldapHost]", ldapContainer.getLdapHost());
         configuration.addProperty("[@principal]", "cn=admin,dc=james,dc=org");
         configuration.addProperty("[@credentials]", ADMIN_PASSWORD);
         configuration.addProperty("[@userBase]", "ou=People,dc=james,dc=org");
@@ -210,9 +236,9 @@ class ReadOnlyUsersLDAPRepositoryTest {
         return configuration;
     }
 
-    private static HierarchicalConfiguration<ImmutableNode> ldapRepositoryConfigurationWithVirtualHosting() {
+    static HierarchicalConfiguration<ImmutableNode> ldapRepositoryConfigurationWithVirtualHosting(LdapGenericContainer ldapContainer) {
         PropertyListConfiguration configuration = new PropertyListConfiguration();
-        configuration.addProperty("[@ldapHost]", DockerLdapSingleton.ldapContainer.getLdapHost());
+        configuration.addProperty("[@ldapHost]", ldapContainer.getLdapHost());
         configuration.addProperty("[@principal]", "cn=admin,dc=james,dc=org");
         configuration.addProperty("[@credentials]", ADMIN_PASSWORD);
         configuration.addProperty("[@userBase]", "ou=People,dc=james,dc=org");
diff --git a/server/data/data-ldap/src/test/resources/invalid/ldif-files/Dockerfile b/server/data/data-ldap/src/test/resources/invalid/ldif-files/Dockerfile
new file mode 100644
index 0000000..d889a35
--- /dev/null
+++ b/server/data/data-ldap/src/test/resources/invalid/ldif-files/Dockerfile
@@ -0,0 +1,3 @@
+FROM dinkel/openldap:latest
+
+COPY populate.ldif /etc/ldap/prepopulate/prepop.ldif
diff --git a/server/data/data-ldap/src/test/resources/invalid/ldif-files/populate.ldif b/server/data/data-ldap/src/test/resources/invalid/ldif-files/populate.ldif
new file mode 100644
index 0000000..9376a6c
--- /dev/null
+++ b/server/data/data-ldap/src/test/resources/invalid/ldif-files/populate.ldif
@@ -0,0 +1,11 @@
+dn: ou=people, dc=james,dc=org
+ou: people
+objectClass: organizationalUnit
+
+dn: uid=james-user, ou=people, dc=james,dc=org
+objectClass: inetOrgPerson
+uid: james-user
+cn: james-user
+sn: james-user
+userPassword: secret
+description: James user


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org