Automatically start embedded LDAP server if configured
Automatically start on first login attempt, if
useEmbeddedServer=true in ldap.conf
Change-Id: Id81a4d23a4e205d05545b22a5655ebd5eb25599b
diff --git a/full/pom.xml b/full/pom.xml
index 5b2ecfb..c89dd84 100644
--- a/full/pom.xml
+++ b/full/pom.xml
@@ -130,7 +130,6 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
- <useSystemClassLoader>false</useSystemClassLoader>
<reuseForks>true</reuseForks>
<forkCount>1</forkCount>
<threadCount>10</threadCount>
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/LdapAuth3.java b/full/src/main/java/de/ids_mannheim/korap/authentication/LdapAuth3.java
index 53c8a1b..26a81fb 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/LdapAuth3.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/LdapAuth3.java
@@ -11,15 +11,17 @@
import com.unboundid.util.ssl.TrustStoreTrustManager;
import de.ids_mannheim.korap.config.FullConfiguration;
import de.ids_mannheim.korap.constant.TokenType;
+import de.ids_mannheim.korap.server.EmbeddedLdapServer;
import org.apache.commons.text.StringSubstitutor;
import javax.net.ssl.SSLSocketFactory;
-import java.io.FileInputStream;
import java.io.IOException;
+import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
-import java.util.Properties;
+
+import static de.ids_mannheim.korap.server.EmbeddedLdapServer.loadProp;
/**
@@ -71,36 +73,6 @@
}
}
- static HashMap<String, String> typeCastConvert(Properties prop) {
- Map<String, String> step2 = (Map<String, String>) (Map) prop;
- return new HashMap<>(step2);
- }
-
- static HashMap<String, String> loadProp(String sConfFile) throws IOException {
- FileInputStream in;
- Properties prop;
-
- try {
- in = new FileInputStream(sConfFile);
- } catch (IOException ex) {
- System.err.printf("Error: LDAP.loadProp: cannot load Property file '%s'!\n", sConfFile);
- ex.printStackTrace();
- return null;
- }
-
- if (DEBUGLOG) System.out.println("Debug: loaded: " + sConfFile);
-
- prop = new Properties();
-
- try {
- prop.load(in);
- return typeCastConvert(prop);
- } catch (IOException ex) {
- ex.printStackTrace();
- }
-
- return new HashMap<>();
- }
public static int login(String sUserDN, String sUserPwd, String ldapConfigFilename) throws LDAPException {
@@ -123,6 +95,17 @@
final String ldapFilter = ldapConfig.getOrDefault("ldapFilter", "(&(|(&(mail=${username})(idsC2Password=${password}))(&(idsC2Profile=${username})(idsC2Password=${password})))(&(idsC2=TRUE)(|(idsStatus=1)(|(idsStatus=0)(xidsStatus=\00)))))");
final String sPwd = ldapConfig.getOrDefault("pwd", "");
final String trustStorePath = ldapConfig.getOrDefault("trustStore", null);
+ final Boolean useEmbeddedServer = Boolean.parseBoolean(ldapConfig.getOrDefault("useEmbeddedServer", "false"));
+
+ if (useEmbeddedServer && EmbeddedLdapServer.server == null) {
+ try {
+ EmbeddedLdapServer.start(ldapConfigFilename);
+ } catch (GeneralSecurityException e) {
+ throw new RuntimeException(e);
+ } catch (UnknownHostException e) {
+ throw new RuntimeException(e);
+ }
+ }
Map<String, String> valuesMap = new HashMap<>();
valuesMap.put("username", sUserDN);
diff --git a/full/src/main/java/de/ids_mannheim/korap/server/EmbeddedLdapServer.java b/full/src/main/java/de/ids_mannheim/korap/server/EmbeddedLdapServer.java
new file mode 100644
index 0000000..e6bd261
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/server/EmbeddedLdapServer.java
@@ -0,0 +1,87 @@
+package de.ids_mannheim.korap.server;
+
+import com.unboundid.ldap.listener.InMemoryDirectoryServer;
+import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
+import com.unboundid.ldap.listener.InMemoryListenerConfig;
+import com.unboundid.ldap.sdk.LDAPException;
+import com.unboundid.util.ssl.SSLUtil;
+import com.unboundid.util.ssl.TrustAllTrustManager;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.GeneralSecurityException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+public class EmbeddedLdapServer {
+ public static InMemoryDirectoryServer server;
+
+ public static void start(String ldapConfigFilename) throws LDAPException, GeneralSecurityException, UnknownHostException {
+ Map<String, String> ldapConfig = null;
+ try {
+ ldapConfig = loadProp(ldapConfigFilename);
+ } catch (IOException e) {
+ System.out.println("Error: LDAPAuth.login: cannot load Property file!");
+ }
+
+ final int ldapPort = Integer.parseInt(ldapConfig.getOrDefault("ldapPort", "3268"));
+ final String ldapBase = ldapConfig.getOrDefault("ldapBase", "dc=example,dc=com");
+ final String sLoginDN = ldapConfig.getOrDefault("sLoginDN", "cn=admin,dc=example,dc=com");
+ final String sPwd = ldapConfig.getOrDefault("pwd", "");
+ final String ldif = ldapConfig.getOrDefault("ldifFile", "");
+
+ InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(ldapBase);
+ config.addAdditionalBindCredentials(sLoginDN, sPwd);
+ config.setSchema(null);
+
+ final SSLUtil clientSslUtil = new SSLUtil(new TrustAllTrustManager());
+
+ config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("LDAP", // Listener name
+ InetAddress.getByName("localhost"), // Listen address. (null = listen on all interfaces)
+ ldapPort, // Listen port (0 = automatically choose an available port)
+ clientSslUtil.createSSLSocketFactory()));
+ server = new InMemoryDirectoryServer(config);
+
+ server.importFromLDIF(true, ldif);
+ server.startListening();
+ }
+
+ public static void stop() {
+ if (server != null) {
+ server.shutDown(true);
+ }
+ }
+
+ static HashMap<String, String> typeCastConvert(Properties prop) {
+ Map<String, String> step2 = (Map<String, String>) (Map) prop;
+ return new HashMap<>(step2);
+ }
+
+ public static HashMap<String, String> loadProp(String sConfFile) throws IOException {
+ FileInputStream in;
+ Properties prop;
+
+ try {
+ in = new FileInputStream(sConfFile);
+ } catch (IOException ex) {
+ System.err.printf("Error: LDAP.loadProp: cannot load Property file '%s'!\n", sConfFile);
+ ex.printStackTrace();
+ return null;
+ }
+
+ prop = new Properties();
+
+ try {
+ prop.load(in);
+ return typeCastConvert(prop);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+
+ return new HashMap<>();
+ }
+
+}
diff --git a/full/src/main/resources/korap-users.ldif b/full/src/main/resources/korap-users.ldif
new file mode 100644
index 0000000..4a3e69c
--- /dev/null
+++ b/full/src/main/resources/korap-users.ldif
@@ -0,0 +1,27 @@
+dn: dc=example,dc=com
+dc: example
+ou: people
+objectClass: dcObject
+objectClass: organizationalUnit
+
+dn: ou=people,dc=example,dc=com
+ou: people
+objectClass: organizationalUnit
+
+dn: uid=user,ou=people,dc=example,dc=com
+cn: user
+uid: user
+mail: user@example.com
+userPassword: cGFzc3dvcmQ=
+
+dn: uid=user1,ou=people,dc=example,dc=com
+cn: user1
+uid: user1
+mail: user1@example.com
+userPassword: password1
+
+dn: uid=user2,ou=people,dc=example,dc=com
+cn: user2
+uid: user2
+mail: user2@example.com
+userPassword: password2
diff --git a/full/src/main/resources/ldap.properties b/full/src/main/resources/ldap.properties
new file mode 100644
index 0000000..c822988
--- /dev/null
+++ b/full/src/main/resources/ldap.properties
@@ -0,0 +1,8 @@
+ldapHost=localhost
+ldapPort=3267
+ldapBase=dc=example,dc=com
+sLoginDN=cn=admin,dc=example,dc=com
+pwd=admin
+ldapFilter=(&(uid=${username})(userPassword=${password}))
+useEmbeddedServer=true
+ldifFile=src/main/resources/korap-users.ldif
diff --git a/full/src/test/java/de/ids_mannheim/korap/server/EmbeddedLdapServerTest.java b/full/src/test/java/de/ids_mannheim/korap/server/EmbeddedLdapServerTest.java
new file mode 100644
index 0000000..8a32281
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/server/EmbeddedLdapServerTest.java
@@ -0,0 +1,43 @@
+package de.ids_mannheim.korap.server;
+
+import com.unboundid.ldap.sdk.LDAPException;
+import com.unboundid.util.Base64;
+import com.unboundid.util.StaticUtils;
+import de.ids_mannheim.korap.authentication.LdapAuth3;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import static de.ids_mannheim.korap.authentication.LdapAuth3.LDAP_AUTH_RNAUTH;
+import static de.ids_mannheim.korap.authentication.LdapAuth3.LDAP_AUTH_ROK;
+import static org.junit.Assert.assertEquals;
+
+public class EmbeddedLdapServerTest {
+
+ @AfterClass
+ public static void shutdownEmbeddedLdapServer() {
+ EmbeddedLdapServer.stop();
+ }
+
+ @Test
+ public void embeddedServerStartsAutomaticallyAndUsersCanLogin() throws LDAPException {
+ final byte[] passwordBytes = StaticUtils.getBytes("password");
+ String pw = Base64.encode(passwordBytes);
+
+ assertEquals(LDAP_AUTH_ROK, LdapAuth3.login("user", pw, "src/main/resources/ldap.properties"));
+ }
+
+ @Test
+ public void usersWithUnencodedPasswowrdCanLogin() throws LDAPException {
+ assertEquals(LDAP_AUTH_ROK, LdapAuth3.login("user1", "password1", "src/main/resources/ldap.properties"));
+ }
+
+ @Test
+ public void asteriskPasswordsFail() throws LDAPException {
+ assertEquals(LDAP_AUTH_RNAUTH, LdapAuth3.login("user1", "*", "src/main/resources/ldap.properties"));
+ }
+
+ @Test
+ public void unauthorizedUsersAreNotAllowed() throws LDAPException {
+ assertEquals(LDAP_AUTH_RNAUTH, LdapAuth3.login("yuser", "password", "src/main/resources/ldap.properties"));
+ }
+}
\ No newline at end of file