KEYCLOAK-1531 Added embedded LDAP for examples. Added module keycloak-util-embedded-ldap with common code for testsuite and examples
This commit is contained in:
parent
351a17f68d
commit
c6c73e5e59
34 changed files with 1262 additions and 428 deletions
|
@ -89,13 +89,6 @@ public class BasicDBObjectMapper<S> implements Mapper<BasicDBObject, S> {
|
|||
Type[] genericTypeArguments = parameterized.getActualTypeArguments();
|
||||
|
||||
List<Type> genericTypes = Arrays.asList(genericTypeArguments);
|
||||
/*for (Type genericType : genericTypeArguments) {
|
||||
if (genericType instanceof Class) {
|
||||
genericTypes.add((Class<?>) genericType);
|
||||
} else {
|
||||
System.out.println("foo");
|
||||
}
|
||||
}*/
|
||||
|
||||
Class<?> expectedReturnType = (Class<?>)parameterized.getRawType();
|
||||
context = new MapperContext<Object, Object>(valueFromDB, expectedReturnType, genericTypes);
|
||||
|
|
|
@ -19,7 +19,7 @@ cp http.keytab /tmp/http.keytab
|
|||
```
|
||||
|
||||
Alternative is to configure different location for `keyTab` property in `kerberosrealm.json` configuration file (On Windows this will be needed).
|
||||
Note that in production, keytab file should be in secured location accessible just to the user under which is Keycloak server running.
|
||||
WARNING: In production, keytab file should be in secured location accessible just to the user under which is Keycloak server running.
|
||||
|
||||
|
||||
**3)** Run Keycloak server and import `kerberosrealm.json` into it through admin console. This will import realm with sample application
|
||||
|
@ -37,12 +37,13 @@ Also if you are on Linux, make sure that record like:
|
|||
```
|
||||
is in your `/etc/hosts` before other records for the 127.0.0.1 host to avoid issues related to incompatible reverse lookup (Ensure the similar for other OS as well)
|
||||
|
||||
**4)** Install kerberos client. This is platform dependent. If you are on Fedora, Ubuntu or RHEL, you can install package `freeipa-client`, which contains Kerberos client and bunch of other stuff.
|
||||
|
||||
**4)** Configure Kerberos client (On linux it's in file `/etc/krb5.conf` ). You need to configure `KEYCLOAK.ORG` realm and enable `forwardable` flag, which is needed
|
||||
**5)** Configure Kerberos client (On linux it's in file `/etc/krb5.conf` ). You need to configure `KEYCLOAK.ORG` realm for host `localhost` and enable `forwardable` flag, which is needed
|
||||
for credential delegation example, as application needs to forward Kerberos ticket and authenticate with it against LDAP server.
|
||||
See [this file](https://github.com/keycloak/keycloak/blob/master/testsuite/integration/src/test/resources/kerberos/test-krb5.conf) for inspiration.
|
||||
|
||||
**5)** Run ApacheDS based Kerberos server embedded in Keycloak. Easiest is to checkout keycloak sources, build and then run KerberosEmbeddedServer
|
||||
**6)** Run ApacheDS based Kerberos server embedded in Keycloak. Easiest is to checkout keycloak sources, build and then run KerberosEmbeddedServer
|
||||
as shown here:
|
||||
|
||||
```
|
||||
|
@ -55,12 +56,12 @@ mvn exec:java -Pkerberos
|
|||
More details about embedded Kerberos server in [testsuite README](https://github.com/keycloak/keycloak/blob/master/misc/Testsuite.md#kerberos-server).
|
||||
|
||||
|
||||
**6)** Configure browser (Firefox, Chrome or other) and enable SPNEGO authentication and credential delegation for `localhost` .
|
||||
**7)** Configure browser (Firefox, Chrome or other) and enable SPNEGO authentication and credential delegation for `localhost` .
|
||||
In Firefox it can be done by adding `localhost` to both `network.negotiate-auth.trusted-uris` and `network.negotiate-auth.delegation-uris` .
|
||||
More info in [testsuite README](https://github.com/keycloak/keycloak/blob/master/misc/Testsuite.md#kerberos-server).
|
||||
|
||||
|
||||
**7)** Test the example. Obtain kerberos ticket by running command from CMD (on linux):
|
||||
**8)** Test the example. Obtain kerberos ticket by running command from CMD (on linux):
|
||||
```
|
||||
kinit hnelson@KEYCLOAK.ORG
|
||||
```
|
||||
|
|
0
examples/kerberos/users.ldif
Normal file
0
examples/kerberos/users.ldif
Normal file
21
examples/ldap/embedded-ldap/assembly.xml
Normal file
21
examples/ldap/embedded-ldap/assembly.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<assembly>
|
||||
<id>embedded-ldap</id>
|
||||
|
||||
<formats>
|
||||
<format>dir</format>
|
||||
</formats>
|
||||
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<unpack>false</unpack>
|
||||
<useTransitiveDependencies>true</useTransitiveDependencies>
|
||||
<useTransitiveFiltering>true</useTransitiveFiltering>
|
||||
<includes>
|
||||
<include>org.keycloak:keycloak-util-embedded-ldap</include>
|
||||
<include>org.slf4j:slf4j-log4j12</include>
|
||||
</includes>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
</assembly>
|
82
examples/ldap/embedded-ldap/pom.xml
Normal file
82
examples/ldap/embedded-ldap/pom.xml
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-examples-ldap-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.4.0.Final-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>keycloak-examples-embedded-ldap</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>LDAP Demo Application</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-util-embedded-ldap</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>embedded-ldap</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>assemble</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>
|
||||
target
|
||||
</outputDirectory>
|
||||
<workDirectory>
|
||||
target/assembly/work
|
||||
</workDirectory>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.keycloak.example.ldap.embedded.EmbeddedLDAPLauncher</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,127 @@
|
|||
package org.keycloak.example.ldap.embedded;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* This is supposed to be executed from JAR file (java -jar target/embedded-ldap.jar ). For executing from IDE or Maven use directly
|
||||
* the proper class (LDAPEmbeddedServer, KerberosEmbeddedServer or KerberosKeytabCreator)
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class EmbeddedLDAPLauncher {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String arg = args.length == 0 ? null : args[0];
|
||||
if (arg == null) {
|
||||
System.err.println("Missing argument: either 'kerberos', 'ldap' or 'keytabCreator' must be passed as argument");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String clazz = null;
|
||||
File home = getHome();
|
||||
Properties defaultProperties = new Properties();
|
||||
if (arg.equalsIgnoreCase("ldap")) {
|
||||
|
||||
clazz = "org.keycloak.util.ldap.LDAPEmbeddedServer";
|
||||
File ldapLdif = file(home, "..", "ldap-app", "users.ldif");
|
||||
defaultProperties.put("ldap.ldif", ldapLdif.getAbsolutePath());
|
||||
} else if (arg.equalsIgnoreCase("kerberos")) {
|
||||
|
||||
clazz = "org.keycloak.util.ldap.KerberosEmbeddedServer";
|
||||
File kerberosLdif = file(home, "..", "..", "kerberos", "users.ldif");
|
||||
defaultProperties.put("ldap.ldif", kerberosLdif.getAbsolutePath());
|
||||
} else if (arg.equalsIgnoreCase("keytabCreator")) {
|
||||
|
||||
clazz = "org.keycloak.util.ldap.KerberosKeytabCreator";
|
||||
} else {
|
||||
|
||||
System.err.println("Invalid argument: '" + arg + "' . Either 'kerberos', 'ldap' or 'keytabCreator' must be passed as argument");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Remove first argument
|
||||
String[] newArgs = new String[args.length - 1];
|
||||
for (int i=0 ; i<(args.length - 1) ; i++) {
|
||||
newArgs[i] = args[i + 1];
|
||||
}
|
||||
|
||||
System.out.println("Executing " + clazz);
|
||||
runClass(clazz, newArgs, defaultProperties);
|
||||
}
|
||||
|
||||
|
||||
private static void runClass(String className, String[] args, Properties defaultProperties) throws Exception {
|
||||
File home = getHome();
|
||||
File lib = file(home, "target", "embedded-ldap");
|
||||
|
||||
if (!lib.exists()) {
|
||||
System.err.println("Could not find lib directory: " + lib.toString());
|
||||
System.exit(1);
|
||||
} else {
|
||||
System.out.println("Found directory to load jars: " + lib.getAbsolutePath());
|
||||
}
|
||||
|
||||
List<URL> jars = new ArrayList<URL>();
|
||||
for (File file : lib.listFiles()) {
|
||||
jars.add(file.toURI().toURL());
|
||||
}
|
||||
URL[] urls = jars.toArray(new URL[jars.size()]);
|
||||
URLClassLoader loader = new URLClassLoader(urls, EmbeddedLDAPLauncher.class.getClassLoader());
|
||||
|
||||
Class mainClass = loader.loadClass(className);
|
||||
Method executeMethod = null;
|
||||
for (Method m : mainClass.getMethods()) if (m.getName().equals("execute")) { executeMethod = m; break; }
|
||||
Object obj = args;
|
||||
executeMethod.invoke(null, obj, defaultProperties);
|
||||
}
|
||||
|
||||
|
||||
private static File getHome() {
|
||||
String launcherPath = EmbeddedLDAPLauncher.class.getName().replace('.', '/') + ".class";
|
||||
URL jarfile = EmbeddedLDAPLauncher.class.getClassLoader().getResource(launcherPath);
|
||||
if (jarfile != null) {
|
||||
Matcher m = Pattern.compile("jar:(file:.*)!/" + launcherPath).matcher(jarfile.toString());
|
||||
if (m.matches()) {
|
||||
try {
|
||||
File jarPath = new File(new URI(m.group(1)));
|
||||
File libPath = jarPath.getParentFile().getParentFile();
|
||||
System.out.println("Home directory: " + libPath.toString());
|
||||
if (!libPath.exists()) {
|
||||
System.exit(1);
|
||||
|
||||
}
|
||||
return libPath;
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.err.println("jar file null: " + launcherPath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static File file(File home, String... pathItems) {
|
||||
File current = home;
|
||||
|
||||
for (String item : pathItems) {
|
||||
if (item.equals("..")) {
|
||||
current = current.getParentFile();
|
||||
} else {
|
||||
current = new File(current, item);
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
68
examples/ldap/ldap-app/pom.xml
Normal file
68
examples/ldap/ldap-app/pom.xml
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-examples-ldap-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.4.0.Final-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>keycloak-examples-ldap-app</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>LDAP Demo Application</name>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jboss</id>
|
||||
<name>jboss repo</name>
|
||||
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>ldap-portal</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jboss.as.plugins</groupId>
|
||||
<artifactId>jboss-as-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>false</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.wildfly.plugins</groupId>
|
||||
<artifactId>wildfly-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>false</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
0
examples/ldap/ldap-app/users.ldif
Normal file
0
examples/ldap/ldap-app/users.ldif
Normal file
20
examples/ldap/pom.xml
Normal file
20
examples/ldap/pom.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-examples-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.4.0.Final-SNAPSHOT</version>
|
||||
</parent>
|
||||
<name>Keycloak LDAP Examples - Parent</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-examples-ldap-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>embedded-ldap</module>
|
||||
<module>ldap-app</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
|
@ -44,5 +44,6 @@
|
|||
<module>kerberos</module>
|
||||
<module>themes</module>
|
||||
<module>saml</module>
|
||||
<module>ldap</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
11
pom.xml
11
pom.xml
|
@ -155,6 +155,7 @@
|
|||
<module>testsuite</module>
|
||||
<module>timer</module>
|
||||
<module>export-import</module>
|
||||
<module>util</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -431,25 +432,21 @@
|
|||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core-annotations</artifactId>
|
||||
<version>${apacheds.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-interceptor-kerberos</artifactId>
|
||||
<version>${apacheds.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-server-annotations</artifactId>
|
||||
<version>${apacheds.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.api</groupId>
|
||||
<artifactId>api-ldap-codec-standalone</artifactId>
|
||||
<version>${apacheds.codec.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Selenium -->
|
||||
|
@ -1120,6 +1117,11 @@
|
|||
<version>${project.version}</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-util-embedded-ldap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-docs-dist</artifactId>
|
||||
|
@ -1184,6 +1186,7 @@
|
|||
<version>${project.version}</version>
|
||||
<classifier>classes</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>federation-properties-example</artifactId>
|
||||
|
|
|
@ -190,40 +190,8 @@
|
|||
|
||||
<!-- Apache DS -->
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core-annotations</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.directory.jdbm</groupId>
|
||||
<artifactId>apacheds-jdbm1</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-interceptor-kerberos</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-server-annotations</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.directory.jdbm</groupId>
|
||||
<artifactId>apacheds-jdbm1</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.api</groupId>
|
||||
<artifactId>api-ldap-codec-standalone</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-util-embedded-ldap</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -344,7 +312,7 @@
|
|||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>org.keycloak.testsuite.ldap.LDAPEmbeddedServer</mainClass>
|
||||
<mainClass>org.keycloak.util.ldap.LDAPEmbeddedServer</mainClass>
|
||||
<classpathScope>test</classpathScope>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
@ -359,7 +327,7 @@
|
|||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>org.keycloak.testsuite.ldap.KerberosEmbeddedServer</mainClass>
|
||||
<mainClass>org.keycloak.util.ldap.KerberosEmbeddedServer</mainClass>
|
||||
<classpathScope>test</classpathScope>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -68,10 +68,10 @@ public class FederationProvidersIntegrationTest {
|
|||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
FederationTestUtils.removeAllLDAPUsers(ldapFedProvider, appRealm);
|
||||
|
||||
LDAPObject john = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johnkeycloak", "John", "Doe", "john@email.org", "1234");
|
||||
LDAPObject john = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johnkeycloak", "John", "Doe", "john@email.org", null, "1234");
|
||||
ldapFedProvider.getLdapIdentityStore().updatePassword(john, "Password1");
|
||||
|
||||
LDAPObject existing = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "existing", "Existing", "Foo", "existing@email.org", "5678");
|
||||
LDAPObject existing = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "existing", "Existing", "Foo", "existing@email.org", null, "5678");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -270,7 +270,7 @@ public class FederationProvidersIntegrationTest {
|
|||
RealmModel appRealm = new RealmManager(session).getRealmByName("test");
|
||||
|
||||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
LDAPObject johnZip = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johnzip", "John", "Zip", "johnzip@email.org", "12398");
|
||||
LDAPObject johnZip = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johnzip", "John", "Zip", "johnzip@email.org", null, "12398");
|
||||
|
||||
// Remove default zipcode mapper and add the mapper for "POstalCode" to test case sensitivity
|
||||
UserFederationMapperModel currentZipMapper = appRealm.getUserFederationMapperByName(ldapModel.getId(), "zipCodeMapper");
|
||||
|
@ -295,7 +295,7 @@ public class FederationProvidersIntegrationTest {
|
|||
RealmModel appRealm = new RealmManager(session).getRealmByName("test");
|
||||
|
||||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
LDAPObject johnDirect = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johndirect", "John", "Direct", "johndirect@email.org", "12399");
|
||||
LDAPObject johnDirect = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johndirect", "John", "Direct", "johndirect@email.org", null, "12399");
|
||||
|
||||
// Fetch user from LDAP and check that postalCode is filled
|
||||
UserModel user = session.users().getUserByUsername("johndirect", appRealm);
|
||||
|
@ -370,7 +370,7 @@ public class FederationProvidersIntegrationTest {
|
|||
|
||||
// Add the user with some fullName into LDAP directly. Ensure that fullName is saved into "cn" attribute in LDAP (currently mapped to model firstName)
|
||||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "fullname", "James Dee", "Dee", "fullname@email.org", "4578");
|
||||
FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "fullname", "James Dee", "Dee", "fullname@email.org", null, "4578");
|
||||
|
||||
// add fullname mapper to the provider and remove "firstNameMapper". For this test, we will simply map full name to the LDAP attribute, which was before firstName ( "givenName" on active directory, "cn" on other LDAP servers)
|
||||
firstNameMapper = appRealm.getUserFederationMapperByName(ldapModel.getId(), "first name");
|
||||
|
@ -485,10 +485,10 @@ public class FederationProvidersIntegrationTest {
|
|||
RealmModel appRealm = session.realms().getRealmByName("test");
|
||||
LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
|
||||
FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username1", "John1", "Doel1", "user1@email.org", "121");
|
||||
FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username2", "John2", "Doel2", "user2@email.org", "122");
|
||||
FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username3", "John3", "Doel3", "user3@email.org", "123");
|
||||
FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username4", "John4", "Doel4", "user4@email.org", "124");
|
||||
FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username1", "John1", "Doel1", "user1@email.org", null, "121");
|
||||
FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username2", "John2", "Doel2", "user2@email.org", null, "122");
|
||||
FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username3", "John3", "Doel3", "user3@email.org", null, "123");
|
||||
FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username4", "John4", "Doel4", "user4@email.org", null, "124");
|
||||
|
||||
// Users are not at local store at this moment
|
||||
Assert.assertNull(session.userStorage().getUserByUsername("username1", appRealm));
|
||||
|
|
|
@ -47,7 +47,7 @@ class FederationTestUtils {
|
|||
}
|
||||
|
||||
public static LDAPObject addLDAPUser(LDAPFederationProvider ldapProvider, RealmModel realm, final String username,
|
||||
final String firstName, final String lastName, final String email, final String postalCode) {
|
||||
final String firstName, final String lastName, final String email, final String street, final String... postalCode) {
|
||||
UserModel helperUser = new UserModelDelegate(null) {
|
||||
|
||||
@Override
|
||||
|
@ -74,6 +74,8 @@ class FederationTestUtils {
|
|||
public List<String> getAttribute(String name) {
|
||||
if ("postal_code".equals(name)) {
|
||||
return Arrays.asList(postalCode);
|
||||
} else if ("street".equals(name)) {
|
||||
return Arrays.asList(street);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package org.keycloak.testsuite.federation;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -17,6 +20,7 @@ import org.junit.runners.MethodSorters;
|
|||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.federation.ldap.LDAPFederationProvider;
|
||||
import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
|
||||
import org.keycloak.federation.ldap.idm.model.LDAPObject;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
|
@ -60,6 +64,19 @@ public class LDAPMultipleAttributesTest {
|
|||
FederationTestUtils.addZipCodeLDAPMapper(appRealm, ldapModel);
|
||||
FederationTestUtils.addUserAttributeMapper(appRealm, ldapModel, "streetMapper", "street", LDAPConstants.STREET);
|
||||
|
||||
// Remove current users and add default users
|
||||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
FederationTestUtils.removeAllLDAPUsers(ldapFedProvider, appRealm);
|
||||
|
||||
LDAPObject james = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "jbrown", "James", "Brown", "jbrown@keycloak.org", "", "88441");
|
||||
ldapFedProvider.getLdapIdentityStore().updatePassword(james, "password");
|
||||
|
||||
// User for testing duplicating surname and postalCode
|
||||
LDAPObject bruce = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "bwilson", "Bruce", "Wilson", "bwilson@keycloak.org", "Elm 5", "88441", "77332");
|
||||
bruce.setAttribute("sn", new LinkedHashSet<>(Arrays.asList("Wilson", "Schneider")));
|
||||
ldapFedProvider.getLdapIdentityStore().update(bruce);
|
||||
ldapFedProvider.getLdapIdentityStore().updatePassword(bruce, "password");
|
||||
|
||||
// Create ldap-portal client
|
||||
ClientModel ldapClient = appRealm.addClient("ldap-portal");
|
||||
ldapClient.addRedirectUri("/ldap-portal");
|
||||
|
|
|
@ -76,13 +76,13 @@ public class LDAPRoleMappingsTest {
|
|||
FederationTestUtils.removeAllLDAPRoles(manager.getSession(), appRealm, ldapModel, "financeRolesMapper");
|
||||
|
||||
// Add some users for testing
|
||||
LDAPObject john = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johnkeycloak", "John", "Doe", "john@email.org", "1234");
|
||||
LDAPObject john = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johnkeycloak", "John", "Doe", "john@email.org", null, "1234");
|
||||
ldapFedProvider.getLdapIdentityStore().updatePassword(john, "Password1");
|
||||
|
||||
LDAPObject mary = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "marykeycloak", "Mary", "Kelly", "mary@email.org", "5678");
|
||||
LDAPObject mary = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "marykeycloak", "Mary", "Kelly", "mary@email.org", null, "5678");
|
||||
ldapFedProvider.getLdapIdentityStore().updatePassword(mary, "Password1");
|
||||
|
||||
LDAPObject rob = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "robkeycloak", "Rob", "Brown", "rob@email.org", "8910");
|
||||
LDAPObject rob = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "robkeycloak", "Rob", "Brown", "rob@email.org", null, "8910");
|
||||
ldapFedProvider.getLdapIdentityStore().updatePassword(rob, "Password1");
|
||||
|
||||
// Add some roles for testing
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.testsuite.ldap;
|
||||
package org.keycloak.testsuite.federation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
|
@ -61,7 +61,7 @@ public class SyncProvidersTest {
|
|||
FederationTestUtils.removeAllLDAPUsers(ldapFedProvider, appRealm);
|
||||
|
||||
for (int i=1 ; i<=5 ; i++) {
|
||||
LDAPObject ldapUser = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "user" + i, "User" + i + "FN", "User" + i + "LN", "user" + i + "@email.org", "12" + i);
|
||||
LDAPObject ldapUser = FederationTestUtils.addLDAPUser(ldapFedProvider, appRealm, "user" + i, "User" + i + "FN", "User" + i + "LN", "user" + i + "@email.org", null, "12" + i);
|
||||
ldapFedProvider.getLdapIdentityStore().updatePassword(ldapUser, "Password1");
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ public class SyncProvidersTest {
|
|||
|
||||
// Add user to LDAP and update 'user5' in LDAP
|
||||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
FederationTestUtils.addLDAPUser(ldapFedProvider, testRealm, "user6", "User6FN", "User6LN", "user6@email.org", "126");
|
||||
FederationTestUtils.addLDAPUser(ldapFedProvider, testRealm, "user6", "User6FN", "User6LN", "user6@email.org", null, "126");
|
||||
LDAPObject ldapUser5 = ldapFedProvider.loadLDAPUserByUsername(testRealm, "user5");
|
||||
// NOTE: Changing LDAP attributes directly here
|
||||
ldapUser5.setSingleAttribute(LDAPConstants.EMAIL, "user5Updated@email.org");
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
package org.keycloak.testsuite.ldap;
|
||||
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
import org.ietf.jgss.GSSName;
|
||||
import org.keycloak.util.KerberosSerializationUtils;
|
||||
import sun.security.jgss.GSSNameImpl;
|
||||
import sun.security.jgss.krb5.Krb5NameElement;
|
||||
|
||||
/**
|
||||
* Factory for ApacheDS based LDAP and Kerberos servers
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class EmbeddedServersFactory {
|
||||
|
||||
private static final String DEFAULT_BASE_DN = "dc=keycloak,dc=org";
|
||||
private static final String DEFAULT_BIND_HOST = "localhost";
|
||||
private static final int DEFAULT_BIND_PORT = 10389;
|
||||
private static final String DEFAULT_LDIF_FILE = "ldap/users.ldif";
|
||||
|
||||
private static final String DEFAULT_KERBEROS_LDIF_FILE = "kerberos/users-kerberos.ldif";
|
||||
|
||||
private static final String DEFAULT_KERBEROS_REALM = "KEYCLOAK.ORG";
|
||||
private static final int DEFAULT_KDC_PORT = 6088;
|
||||
private static final String DEFAULT_KDC_ENCRYPTION_TYPES = "aes128-cts-hmac-sha1-96, des-cbc-md5, des3-cbc-sha1-kd";
|
||||
|
||||
private String baseDN;
|
||||
private String bindHost;
|
||||
private int bindPort;
|
||||
private String ldapSaslPrincipal;
|
||||
private String ldifFile;
|
||||
private String kerberosRealm;
|
||||
private int kdcPort;
|
||||
private String kdcEncryptionTypes;
|
||||
|
||||
|
||||
public static EmbeddedServersFactory readConfiguration() {
|
||||
EmbeddedServersFactory factory = new EmbeddedServersFactory();
|
||||
factory.readProperties();
|
||||
return factory;
|
||||
}
|
||||
|
||||
|
||||
protected void readProperties() {
|
||||
this.baseDN = System.getProperty("ldap.baseDN");
|
||||
this.bindHost = System.getProperty("ldap.host");
|
||||
String bindPort = System.getProperty("ldap.port");
|
||||
this.ldifFile = System.getProperty("ldap.ldif");
|
||||
this.ldapSaslPrincipal = System.getProperty("ldap.saslPrincipal");
|
||||
|
||||
this.kerberosRealm = System.getProperty("kerberos.realm");
|
||||
String kdcPort = System.getProperty("kerberos.port");
|
||||
this.kdcEncryptionTypes = System.getProperty("kerberos.encTypes");
|
||||
|
||||
if (baseDN == null || baseDN.isEmpty()) {
|
||||
baseDN = DEFAULT_BASE_DN;
|
||||
}
|
||||
if (bindHost == null || bindHost.isEmpty()) {
|
||||
bindHost = DEFAULT_BIND_HOST;
|
||||
}
|
||||
this.bindPort = (bindPort == null || bindPort.isEmpty()) ? DEFAULT_BIND_PORT : Integer.parseInt(bindPort);
|
||||
if (ldifFile == null || ldifFile.isEmpty()) {
|
||||
ldifFile = DEFAULT_LDIF_FILE;
|
||||
}
|
||||
|
||||
if (kerberosRealm == null || kerberosRealm.isEmpty()) {
|
||||
kerberosRealm = DEFAULT_KERBEROS_REALM;
|
||||
}
|
||||
this.kdcPort = (kdcPort == null || kdcPort.isEmpty()) ? DEFAULT_KDC_PORT : Integer.parseInt(kdcPort);
|
||||
if (kdcEncryptionTypes == null || kdcEncryptionTypes.isEmpty()) {
|
||||
kdcEncryptionTypes = DEFAULT_KDC_ENCRYPTION_TYPES;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public LDAPEmbeddedServer createLdapServer() {
|
||||
|
||||
// Override LDIF file with default for embedded LDAP
|
||||
if (ldifFile.equals(DEFAULT_KERBEROS_LDIF_FILE)) {
|
||||
ldifFile = DEFAULT_LDIF_FILE;
|
||||
}
|
||||
|
||||
return new LDAPEmbeddedServer(baseDN, bindHost, bindPort, ldifFile, ldapSaslPrincipal);
|
||||
}
|
||||
|
||||
|
||||
public KerberosEmbeddedServer createKerberosServer() {
|
||||
|
||||
// Override LDIF file with default for embedded Kerberos
|
||||
if (ldifFile.equals(DEFAULT_LDIF_FILE)) {
|
||||
ldifFile = DEFAULT_KERBEROS_LDIF_FILE;
|
||||
}
|
||||
|
||||
// Init ldap sasl principal just when creating kerberos server
|
||||
if (ldapSaslPrincipal == null || ldapSaslPrincipal.isEmpty()) {
|
||||
try {
|
||||
// Same algorithm like sun.security.krb5.PrincipalName constructor
|
||||
GSSName gssName = GSSManager.getInstance().createName("ldap@" + bindHost, GSSName.NT_HOSTBASED_SERVICE);
|
||||
GSSNameImpl gssName1 = (GSSNameImpl) gssName;
|
||||
Krb5NameElement krb5NameElement = (Krb5NameElement) gssName1.getElement(KerberosSerializationUtils.KRB5_OID);
|
||||
this.ldapSaslPrincipal = krb5NameElement.getKrb5PrincipalName().toString();
|
||||
} catch (GSSException uhe) {
|
||||
throw new RuntimeException(uhe);
|
||||
}
|
||||
}
|
||||
|
||||
return new KerberosEmbeddedServer(baseDN, bindHost, bindPort, ldifFile, ldapSaslPrincipal, kerberosRealm, kdcPort, kdcEncryptionTypes);
|
||||
}
|
||||
}
|
|
@ -1,196 +0,0 @@
|
|||
package org.keycloak.testsuite.ldap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.text.StrSubstitutor;
|
||||
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
|
||||
import org.apache.directory.api.ldap.model.exception.LdapEntryAlreadyExistsException;
|
||||
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.schema.SchemaManager;
|
||||
import org.apache.directory.server.core.api.DirectoryService;
|
||||
import org.apache.directory.server.core.api.partition.Partition;
|
||||
import org.apache.directory.server.core.factory.DSAnnotationProcessor;
|
||||
import org.apache.directory.server.core.factory.PartitionFactory;
|
||||
import org.apache.directory.server.ldap.LdapServer;
|
||||
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
|
||||
import org.apache.directory.server.protocol.shared.transport.Transport;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.util.StreamUtil;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class LDAPEmbeddedServer {
|
||||
|
||||
private static final Logger log = Logger.getLogger(LDAPEmbeddedServer.class);
|
||||
|
||||
protected final String baseDN;
|
||||
protected final String bindHost;
|
||||
protected final int bindPort;
|
||||
protected final String ldifFile;
|
||||
protected final String ldapSaslPrincipal;
|
||||
|
||||
protected DirectoryService directoryService;
|
||||
protected LdapServer ldapServer;
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
EmbeddedServersFactory factory = EmbeddedServersFactory.readConfiguration();
|
||||
LDAPEmbeddedServer ldapEmbeddedServer = factory.createLdapServer();
|
||||
ldapEmbeddedServer.init();
|
||||
ldapEmbeddedServer.start();
|
||||
}
|
||||
|
||||
public LDAPEmbeddedServer(String baseDN, String bindHost, int bindPort, String ldifFile, String ldapSaslPrincipal) {
|
||||
this.baseDN = baseDN;
|
||||
this.bindHost = bindHost;
|
||||
this.bindPort = bindPort;
|
||||
this.ldifFile = ldifFile;
|
||||
this.ldapSaslPrincipal = ldapSaslPrincipal;
|
||||
}
|
||||
|
||||
|
||||
public void init() throws Exception {
|
||||
log.info("Creating LDAP Directory Service. Config: baseDN=" + baseDN + ", bindHost=" + bindHost + ", bindPort=" + bindPort +
|
||||
", ldapSaslPrincipal=" + ldapSaslPrincipal);
|
||||
|
||||
this.directoryService = createDirectoryService();
|
||||
|
||||
log.info("Importing LDIF: " + ldifFile);
|
||||
importLdif();
|
||||
|
||||
log.info("Creating LDAP Server");
|
||||
this.ldapServer = createLdapServer();
|
||||
}
|
||||
|
||||
|
||||
public void start() throws Exception {
|
||||
log.info("Starting LDAP Server");
|
||||
ldapServer.start();
|
||||
log.info("LDAP Server started");
|
||||
}
|
||||
|
||||
|
||||
protected DirectoryService createDirectoryService() throws Exception {
|
||||
// Parse "keycloak" from "dc=keycloak,dc=org"
|
||||
String dcName = baseDN.split(",")[0].substring(3);
|
||||
|
||||
InMemoryDirectoryServiceFactory dsf = new InMemoryDirectoryServiceFactory();
|
||||
|
||||
DirectoryService service = dsf.getDirectoryService();
|
||||
service.setAccessControlEnabled(false);
|
||||
service.setAllowAnonymousAccess(false);
|
||||
service.getChangeLog().setEnabled(false);
|
||||
|
||||
dsf.init(dcName + "DS");
|
||||
|
||||
SchemaManager schemaManager = service.getSchemaManager();
|
||||
|
||||
PartitionFactory partitionFactory = dsf.getPartitionFactory();
|
||||
Partition partition = partitionFactory.createPartition(
|
||||
schemaManager,
|
||||
service.getDnFactory(),
|
||||
dcName,
|
||||
this.baseDN,
|
||||
1000,
|
||||
new File(service.getInstanceLayout().getPartitionsDirectory(), dcName));
|
||||
partition.setCacheService( service.getCacheService() );
|
||||
partition.initialize();
|
||||
|
||||
partition.setSchemaManager( schemaManager );
|
||||
|
||||
// Inject the partition into the DirectoryService
|
||||
service.addPartition( partition );
|
||||
|
||||
// Last, process the context entry
|
||||
String entryLdif =
|
||||
"dn: " + baseDN + "\n" +
|
||||
"dc: " + dcName + "\n" +
|
||||
"objectClass: top\n" +
|
||||
"objectClass: domain\n\n";
|
||||
DSAnnotationProcessor.injectEntries(service, entryLdif);
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
protected LdapServer createLdapServer() {
|
||||
LdapServer ldapServer = new LdapServer();
|
||||
|
||||
ldapServer.setServiceName("DefaultLdapServer");
|
||||
ldapServer.setSearchBaseDn(this.baseDN);
|
||||
|
||||
// Read the transports
|
||||
Transport ldap = new TcpTransport(this.bindHost, this.bindPort, 3, 50);
|
||||
ldapServer.addTransports( ldap );
|
||||
|
||||
// Associate the DS to this LdapServer
|
||||
ldapServer.setDirectoryService( directoryService );
|
||||
|
||||
// Propagate the anonymous flag to the DS
|
||||
directoryService.setAllowAnonymousAccess(false);
|
||||
|
||||
return ldapServer;
|
||||
}
|
||||
|
||||
|
||||
private void importLdif() throws Exception {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("hostname", this.bindHost);
|
||||
if (this.ldapSaslPrincipal != null) {
|
||||
map.put("ldapSaslPrincipal", this.ldapSaslPrincipal);
|
||||
}
|
||||
|
||||
// For now, assume that LDIF file is on classpath
|
||||
InputStream is;
|
||||
if (ldifFile.startsWith("file:")) {
|
||||
is = new URL(ldifFile).openStream();
|
||||
} else {
|
||||
is = getClass().getClassLoader().getResourceAsStream(ldifFile);
|
||||
}
|
||||
if (is == null) {
|
||||
throw new IllegalStateException("LDIF file not found on classpath. Location was: " + ldifFile);
|
||||
}
|
||||
|
||||
final String ldifContent = StrSubstitutor.replace(StreamUtil.readString(is), map);
|
||||
log.info("Content of LDIF: " + ldifContent);
|
||||
final SchemaManager schemaManager = directoryService.getSchemaManager();
|
||||
|
||||
for (LdifEntry ldifEntry : new LdifReader(IOUtils.toInputStream(ldifContent))) {
|
||||
try {
|
||||
directoryService.getAdminSession().add(new DefaultEntry(schemaManager, ldifEntry.getEntry()));
|
||||
} catch (LdapEntryAlreadyExistsException ignore) {
|
||||
log.debug("Entry " + ldifEntry.getNewRdn() + " already exists. Ignoring");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void stop() throws Exception {
|
||||
stopLdapServer();
|
||||
shutdownDirectoryService();
|
||||
}
|
||||
|
||||
|
||||
protected void stopLdapServer() {
|
||||
log.info("Stopping LDAP server.");
|
||||
ldapServer.stop();
|
||||
}
|
||||
|
||||
|
||||
protected void shutdownDirectoryService() throws Exception {
|
||||
log.info("Stopping Directory service.");
|
||||
directoryService.shutdown();
|
||||
|
||||
log.info("Removing Directory service workfiles.");
|
||||
FileUtils.deleteDirectory(directoryService.getInstanceLayout().getInstanceDirectory());
|
||||
}
|
||||
|
||||
}
|
|
@ -2,11 +2,12 @@ package org.keycloak.testsuite.rule;
|
|||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.testsuite.ldap.EmbeddedServersFactory;
|
||||
import org.keycloak.testsuite.ldap.LDAPTestConfiguration;
|
||||
import org.keycloak.testsuite.ldap.LDAPEmbeddedServer;
|
||||
import org.keycloak.testsuite.federation.LDAPTestConfiguration;
|
||||
import org.keycloak.util.ldap.KerberosEmbeddedServer;
|
||||
import org.keycloak.util.ldap.LDAPEmbeddedServer;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
@ -33,7 +34,11 @@ public class KerberosRule extends LDAPRule {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected LDAPEmbeddedServer createServer(EmbeddedServersFactory factory) {
|
||||
return factory.createKerberosServer();
|
||||
protected LDAPEmbeddedServer createServer() {
|
||||
Properties defaultProperties = new Properties();
|
||||
defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_DSF, LDAPEmbeddedServer.DSF_INMEMORY);
|
||||
defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_LDIF_FILE, "classpath:kerberos/users-kerberos.ldif");
|
||||
|
||||
return new KerberosEmbeddedServer(defaultProperties);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package org.keycloak.testsuite.rule;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.keycloak.testsuite.ldap.EmbeddedServersFactory;
|
||||
import org.keycloak.testsuite.ldap.LDAPTestConfiguration;
|
||||
import org.keycloak.testsuite.ldap.LDAPEmbeddedServer;
|
||||
import org.keycloak.testsuite.federation.LDAPTestConfiguration;
|
||||
import org.keycloak.util.ldap.LDAPEmbeddedServer;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
@ -23,8 +23,7 @@ public class LDAPRule extends ExternalResource {
|
|||
ldapTestConfiguration = LDAPTestConfiguration.readConfiguration(connectionPropsLocation);
|
||||
|
||||
if (ldapTestConfiguration.isStartEmbeddedLdapLerver()) {
|
||||
EmbeddedServersFactory factory = EmbeddedServersFactory.readConfiguration();
|
||||
ldapEmbeddedServer = createServer(factory);
|
||||
ldapEmbeddedServer = createServer();
|
||||
ldapEmbeddedServer.init();
|
||||
ldapEmbeddedServer.start();
|
||||
}
|
||||
|
@ -47,8 +46,12 @@ public class LDAPRule extends ExternalResource {
|
|||
return LDAP_CONNECTION_PROPERTIES_LOCATION;
|
||||
}
|
||||
|
||||
protected LDAPEmbeddedServer createServer(EmbeddedServersFactory factory) {
|
||||
return factory.createLdapServer();
|
||||
protected LDAPEmbeddedServer createServer() {
|
||||
Properties defaultProperties = new Properties();
|
||||
defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_DSF, LDAPEmbeddedServer.DSF_INMEMORY);
|
||||
defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_LDIF_FILE, "classpath:ldap/users.ldif");
|
||||
|
||||
return new LDAPEmbeddedServer(defaultProperties);
|
||||
}
|
||||
|
||||
public Map<String, String> getConfig() {
|
||||
|
|
|
@ -18,30 +18,3 @@ dn: ou=FinanceRoles,dc=keycloak,dc=org
|
|||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: FinanceRoles
|
||||
|
||||
dn: uid=jbrown,ou=People,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
uid: jbrown
|
||||
cn: James
|
||||
sn: Brown
|
||||
mail: jbrown@keycloak.org
|
||||
postalCode: 88441
|
||||
userPassword: password
|
||||
|
||||
dn: uid=bwilson,ou=People,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
uid: bwilson
|
||||
cn: Bruce
|
||||
sn: Wilson
|
||||
sn: Schneider
|
||||
mail: bwilson@keycloak.org
|
||||
postalCode: 88441
|
||||
postalCode: 77332
|
||||
street: Elm 5
|
||||
userPassword: password
|
||||
|
|
91
util/embedded-ldap/pom.xml
Normal file
91
util/embedded-ldap/pom.xml
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.4.0.Final-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-util-embedded-ldap</artifactId>
|
||||
<name>Keycloak Util Embedded LDAP</name>
|
||||
<description/>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core-annotations</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.directory.jdbm</groupId>
|
||||
<artifactId>apacheds-jdbm1</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-interceptor-kerberos</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-server-annotations</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.directory.jdbm</groupId>
|
||||
<artifactId>apacheds-jdbm1</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.api</groupId>
|
||||
<artifactId>api-ldap-codec-standalone</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,267 @@
|
|||
package org.keycloak.util.ldap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
|
||||
import org.apache.directory.api.ldap.model.exception.LdapEntryAlreadyExistsException;
|
||||
import org.apache.directory.api.ldap.model.exception.LdapException;
|
||||
import org.apache.directory.api.ldap.model.schema.LdapComparator;
|
||||
import org.apache.directory.api.ldap.model.schema.SchemaManager;
|
||||
import org.apache.directory.api.ldap.model.schema.comparators.NormalizingComparator;
|
||||
import org.apache.directory.api.ldap.model.schema.registries.ComparatorRegistry;
|
||||
import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
|
||||
import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
|
||||
import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
|
||||
import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
|
||||
import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
|
||||
import org.apache.directory.api.util.exception.Exceptions;
|
||||
import org.apache.directory.server.constants.ServerDNConstants;
|
||||
import org.apache.directory.server.core.DefaultDirectoryService;
|
||||
import org.apache.directory.server.core.api.CacheService;
|
||||
import org.apache.directory.server.core.api.DirectoryService;
|
||||
import org.apache.directory.server.core.api.InstanceLayout;
|
||||
import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
|
||||
import org.apache.directory.server.core.api.partition.Partition;
|
||||
import org.apache.directory.server.core.api.schema.SchemaPartition;
|
||||
import org.apache.directory.server.core.factory.DefaultDirectoryServiceFactory;
|
||||
import org.apache.directory.server.core.factory.DirectoryServiceFactory;
|
||||
import org.apache.directory.server.core.factory.JdbmPartitionFactory;
|
||||
import org.apache.directory.server.core.factory.LdifPartitionFactory;
|
||||
import org.apache.directory.server.core.factory.PartitionFactory;
|
||||
import org.apache.directory.server.core.partition.ldif.LdifPartition;
|
||||
import org.apache.directory.server.i18n.I18n;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Slightly modified version of {@link DefaultDirectoryServiceFactory} which allows persistence among restarts and uses LDIF partitions by default
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
class FileDirectoryServiceFactory implements DirectoryServiceFactory {
|
||||
|
||||
/** A logger for this class */
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FileDirectoryServiceFactory.class);
|
||||
|
||||
/** The directory service. */
|
||||
private DirectoryService directoryService;
|
||||
|
||||
/** The partition factory. */
|
||||
private PartitionFactory partitionFactory;
|
||||
|
||||
|
||||
public FileDirectoryServiceFactory()
|
||||
{
|
||||
try
|
||||
{
|
||||
// creating the instance here so that
|
||||
// we we can set some properties like accesscontrol, anon access
|
||||
// before starting up the service
|
||||
directoryService = new DefaultDirectoryService();
|
||||
|
||||
// no need to register a shutdown hook during tests because this
|
||||
// starts a lot of threads and slows down test execution
|
||||
directoryService.setShutdownHookEnabled( false );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
String typeName = System.getProperty( "apacheds.partition.factory" );
|
||||
|
||||
if ( typeName != null )
|
||||
{
|
||||
Class<? extends PartitionFactory> type = ( Class<? extends PartitionFactory> ) Class.forName( typeName );
|
||||
partitionFactory = type.newInstance();
|
||||
}
|
||||
else
|
||||
{
|
||||
// partitionFactory = new JdbmPartitionFactory();
|
||||
partitionFactory = new LdifPartitionFactory();
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
LOG.error( "Error instantiating custom partiton factory", e );
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public FileDirectoryServiceFactory( DirectoryService directoryService, PartitionFactory partitionFactory )
|
||||
{
|
||||
this.directoryService = directoryService;
|
||||
this.partitionFactory = partitionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void init( String name ) throws Exception
|
||||
{
|
||||
if ( ( directoryService != null ) && directoryService.isStarted() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
build(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the working directory
|
||||
*/
|
||||
private void buildInstanceDirectory( String name ) throws IOException
|
||||
{
|
||||
String instanceDirectory = System.getProperty( "workingDirectory" );
|
||||
|
||||
if ( instanceDirectory == null )
|
||||
{
|
||||
instanceDirectory = System.getProperty( "java.io.tmpdir" ) + "/server-work-" + name;
|
||||
}
|
||||
|
||||
InstanceLayout instanceLayout = new InstanceLayout( instanceDirectory );
|
||||
|
||||
/*if ( instanceLayout.getInstanceDirectory().exists() )
|
||||
{
|
||||
try
|
||||
{
|
||||
FileUtils.deleteDirectory(instanceLayout.getInstanceDirectory());
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
LOG.warn( "couldn't delete the instance directory before initializing the DirectoryService", e );
|
||||
}
|
||||
}*/
|
||||
|
||||
directoryService.setInstanceLayout( instanceLayout );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inits the schema and schema partition.
|
||||
*/
|
||||
private void initSchema() throws Exception
|
||||
{
|
||||
File workingDirectory = directoryService.getInstanceLayout().getPartitionsDirectory();
|
||||
|
||||
// Extract the schema on disk (a brand new one) and load the registries
|
||||
File schemaRepository = new File( workingDirectory, "schema" );
|
||||
SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( workingDirectory );
|
||||
|
||||
try
|
||||
{
|
||||
extractor.extractOrCopy();
|
||||
}
|
||||
catch ( IOException ioe )
|
||||
{
|
||||
// The schema has already been extracted, bypass
|
||||
}
|
||||
|
||||
SchemaLoader loader = new LdifSchemaLoader( schemaRepository );
|
||||
SchemaManager schemaManager = new DefaultSchemaManager( loader );
|
||||
|
||||
// We have to load the schema now, otherwise we won't be able
|
||||
// to initialize the Partitions, as we won't be able to parse
|
||||
// and normalize their suffix Dn
|
||||
schemaManager.loadAllEnabled();
|
||||
|
||||
// Tell all the normalizer comparators that they should not normalize anything
|
||||
ComparatorRegistry comparatorRegistry = schemaManager.getComparatorRegistry();
|
||||
|
||||
for ( LdapComparator<?> comparator : comparatorRegistry )
|
||||
{
|
||||
if ( comparator instanceof NormalizingComparator)
|
||||
{
|
||||
( ( NormalizingComparator ) comparator ).setOnServer();
|
||||
}
|
||||
}
|
||||
|
||||
directoryService.setSchemaManager( schemaManager );
|
||||
|
||||
// Init the LdifPartition
|
||||
LdifPartition ldifPartition = new LdifPartition( schemaManager, directoryService.getDnFactory() );
|
||||
ldifPartition.setPartitionPath( new File( workingDirectory, "schema" ).toURI() );
|
||||
SchemaPartition schemaPartition = new SchemaPartition( schemaManager );
|
||||
schemaPartition.setWrappedPartition( ldifPartition );
|
||||
directoryService.setSchemaPartition( schemaPartition );
|
||||
|
||||
List<Throwable> errors = schemaManager.getErrors();
|
||||
|
||||
if ( errors.size() != 0 )
|
||||
{
|
||||
throw new Exception( I18n.err(I18n.ERR_317, Exceptions.printErrors(errors)) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inits the system partition.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
private void initSystemPartition() throws Exception
|
||||
{
|
||||
// change the working directory to something that is unique
|
||||
// on the system and somewhere either under target directory
|
||||
// or somewhere in a temp area of the machine.
|
||||
|
||||
// Inject the System Partition
|
||||
Partition systemPartition = partitionFactory.createPartition( directoryService.getSchemaManager(),
|
||||
directoryService.getDnFactory(),
|
||||
"system", ServerDNConstants.SYSTEM_DN, 500,
|
||||
new File( directoryService.getInstanceLayout().getPartitionsDirectory(), "system" ) );
|
||||
systemPartition.setSchemaManager(directoryService.getSchemaManager());
|
||||
|
||||
partitionFactory.addIndex(systemPartition, SchemaConstants.OBJECT_CLASS_AT, 100 );
|
||||
|
||||
directoryService.setSystemPartition( systemPartition );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the directory server instance.
|
||||
*
|
||||
* @param name the instance name
|
||||
*/
|
||||
private void build( String name ) throws Exception
|
||||
{
|
||||
directoryService.setInstanceId( name );
|
||||
buildInstanceDirectory( name );
|
||||
|
||||
CacheService cacheService = new CacheService();
|
||||
cacheService.initialize( directoryService.getInstanceLayout() );
|
||||
|
||||
directoryService.setCacheService( cacheService );
|
||||
|
||||
// Init the service now
|
||||
initSchema();
|
||||
initSystemPartition();
|
||||
|
||||
directoryService.startup();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public DirectoryService getDirectoryService() throws Exception
|
||||
{
|
||||
return directoryService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public PartitionFactory getPartitionFactory() throws Exception
|
||||
{
|
||||
return partitionFactory;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.testsuite.ldap;
|
||||
package org.keycloak.util.ldap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -76,7 +76,7 @@ class InMemoryDirectoryServiceFactory implements DirectoryServiceFactory {
|
|||
directoryService.setInstanceId(name);
|
||||
|
||||
// instance layout
|
||||
InstanceLayout instanceLayout = new InstanceLayout(System.getProperty("java.io.tmpdir") + "/server-work-" + name);
|
||||
InstanceLayout instanceLayout = new InstanceLayout(System.getProperty("java.io.tmpdir") + "/server-work-inmemory-" + name);
|
||||
if (instanceLayout.getInstanceDirectory().exists()) {
|
||||
try {
|
||||
FileUtils.deleteDirectory(instanceLayout.getInstanceDirectory());
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.testsuite.ldap;
|
||||
package org.keycloak.util.ldap;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
@ -61,7 +61,7 @@ class InMemorySchemaPartition extends AbstractLdifPartition {
|
|||
|
||||
// add mandatory attributes
|
||||
if (entry.get(SchemaConstants.ENTRY_CSN_AT) == null) {
|
||||
entry.add(SchemaConstants.ENTRY_CSN_AT, defaultCSNFactory.newInstance().toString());
|
||||
entry.add(SchemaConstants.ENTRY_CSN_AT, AbstractLdifPartition.defaultCSNFactory.newInstance().toString());
|
||||
}
|
||||
if (entry.get(SchemaConstants.ENTRY_UUID_AT) == null) {
|
||||
entry.add(SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString());
|
|
@ -1,9 +1,10 @@
|
|||
package org.keycloak.testsuite.ldap;
|
||||
package org.keycloak.util.ldap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.security.auth.kerberos.KerberosPrincipal;
|
||||
|
@ -25,7 +26,13 @@ import org.apache.directory.server.protocol.shared.transport.UdpTransport;
|
|||
import org.apache.directory.shared.kerberos.KerberosTime;
|
||||
import org.apache.directory.shared.kerberos.KerberosUtils;
|
||||
import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
import org.ietf.jgss.GSSName;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.util.KerberosSerializationUtils;
|
||||
import sun.security.jgss.GSSNameImpl;
|
||||
import sun.security.jgss.krb5.Krb5NameElement;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
@ -34,6 +41,16 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
|||
|
||||
private static final Logger log = Logger.getLogger(KerberosEmbeddedServer.class);
|
||||
|
||||
public static final String PROPERTY_KERBEROS_REALM = "kerberos.realm";
|
||||
public static final String PROPERTY_KDC_PORT = "kerberos.port";
|
||||
public static final String PROPERTY_KDC_ENCTYPES = "kerberos.encTypes";
|
||||
|
||||
private static final String DEFAULT_KERBEROS_LDIF_FILE = "classpath:kerberos/default-users.ldif";
|
||||
|
||||
private static final String DEFAULT_KERBEROS_REALM = "KEYCLOAK.ORG";
|
||||
private static final String DEFAULT_KDC_PORT = "6088";
|
||||
private static final String DEFAULT_KDC_ENCRYPTION_TYPES = "aes128-cts-hmac-sha1-96, des-cbc-md5, des3-cbc-sha1-kd";
|
||||
|
||||
private final String kerberosRealm;
|
||||
private final int kdcPort;
|
||||
private final String kdcEncryptionTypes;
|
||||
|
@ -42,18 +59,53 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
|||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
EmbeddedServersFactory factory = EmbeddedServersFactory.readConfiguration();
|
||||
KerberosEmbeddedServer kerberosEmbeddedServer = factory.createKerberosServer();
|
||||
Properties defaultProperties = new Properties();
|
||||
defaultProperties.put(PROPERTY_DSF, DSF_FILE);
|
||||
|
||||
execute(args, defaultProperties);
|
||||
}
|
||||
|
||||
public static void execute(String[] args, Properties defaultProperties) throws Exception {
|
||||
final KerberosEmbeddedServer kerberosEmbeddedServer = new KerberosEmbeddedServer(defaultProperties);
|
||||
kerberosEmbeddedServer.init();
|
||||
kerberosEmbeddedServer.start();
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
kerberosEmbeddedServer.stop();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected KerberosEmbeddedServer(String baseDN, String bindHost, int bindPort, String ldifFile, String ldapSaslPrincipal, String kerberosRealm, int kdcPort, String kdcEncryptionTypes) {
|
||||
super(baseDN, bindHost, bindPort, ldifFile, ldapSaslPrincipal);
|
||||
this.kdcEncryptionTypes = kdcEncryptionTypes;
|
||||
this.kerberosRealm = kerberosRealm;
|
||||
this.kdcPort = kdcPort;
|
||||
public KerberosEmbeddedServer(Properties defaultProperties) {
|
||||
super(defaultProperties);
|
||||
|
||||
this.ldifFile = readProperty(PROPERTY_LDIF_FILE, DEFAULT_KERBEROS_LDIF_FILE);
|
||||
|
||||
this.kerberosRealm = readProperty(PROPERTY_KERBEROS_REALM, DEFAULT_KERBEROS_REALM);
|
||||
String kdcPort = readProperty(PROPERTY_KDC_PORT, DEFAULT_KDC_PORT);
|
||||
this.kdcPort = Integer.parseInt(kdcPort);
|
||||
this.kdcEncryptionTypes = readProperty(PROPERTY_KDC_ENCTYPES, DEFAULT_KDC_ENCRYPTION_TYPES);
|
||||
|
||||
if (ldapSaslPrincipal == null || ldapSaslPrincipal.isEmpty()) {
|
||||
try {
|
||||
// Same algorithm like sun.security.krb5.PrincipalName constructor
|
||||
GSSName gssName = GSSManager.getInstance().createName("ldap@" + bindHost, GSSName.NT_HOSTBASED_SERVICE);
|
||||
GSSNameImpl gssName1 = (GSSNameImpl) gssName;
|
||||
Krb5NameElement krb5NameElement = (Krb5NameElement) gssName1.getElement(KerberosSerializationUtils.KRB5_OID);
|
||||
this.ldapSaslPrincipal = krb5NameElement.getKrb5PrincipalName().toString();
|
||||
} catch (GSSException uhe) {
|
||||
throw new RuntimeException(uhe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,7 +131,7 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
|||
protected LdapServer createLdapServer() {
|
||||
LdapServer ldapServer = super.createLdapServer();
|
||||
|
||||
ldapServer.setSaslHost( this.bindHost );
|
||||
ldapServer.setSaslHost(this.bindHost);
|
||||
ldapServer.setSaslPrincipal( this.ldapSaslPrincipal);
|
||||
ldapServer.setSaslRealms(new ArrayList<String>());
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
package org.keycloak.testsuite.ldap;
|
||||
package org.keycloak.util.ldap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.directory.server.kerberos.shared.crypto.encryption.KerberosKeyFactory;
|
||||
import org.apache.directory.server.kerberos.shared.keytab.Keytab;
|
||||
|
@ -34,7 +35,7 @@ public class KerberosKeytabCreator {
|
|||
System.out.println("-------------------------");
|
||||
System.out.println("Arguments missing or invalid. Required arguments are: <principalName> <passPhrase> <outputKeytabFile>");
|
||||
System.out.println("Example of usage:");
|
||||
System.out.println("mvn exec:java -Dexec.mainClass=\"org.keycloak.testsuite.ldap.KerberosKeytabCreator\" -Dexec.args=\"HTTP/localhost@KEYCLOAK.ORG httppwd src/main/resources/kerberos/http.keytab\"");
|
||||
System.out.println("java -jar embedded-ldap/target/embedded-ldap.jar keytabCreator HTTP/localhost@KEYCLOAK.ORG httppassword /tmp/http.keytab");
|
||||
} else {
|
||||
final File keytabFile = new File(args[2]);
|
||||
createKeytab(args[0], args[1], keytabFile);
|
||||
|
@ -42,6 +43,11 @@ public class KerberosKeytabCreator {
|
|||
}
|
||||
}
|
||||
|
||||
// Just for the reflection purposes
|
||||
public static void execute(String[] args, Properties defaultProperties) throws Exception {
|
||||
main(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keytab file for given principal.
|
||||
*
|
|
@ -0,0 +1,272 @@
|
|||
package org.keycloak.util.ldap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.text.StrSubstitutor;
|
||||
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
|
||||
import org.apache.directory.api.ldap.model.exception.LdapEntryAlreadyExistsException;
|
||||
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.schema.SchemaManager;
|
||||
import org.apache.directory.server.core.api.DirectoryService;
|
||||
import org.apache.directory.server.core.api.partition.Partition;
|
||||
import org.apache.directory.server.core.factory.DirectoryServiceFactory;
|
||||
import org.apache.directory.server.core.factory.PartitionFactory;
|
||||
import org.apache.directory.server.ldap.LdapServer;
|
||||
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
|
||||
import org.apache.directory.server.protocol.shared.transport.Transport;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.util.FindFile;
|
||||
import org.keycloak.util.StreamUtil;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class LDAPEmbeddedServer {
|
||||
|
||||
private static final Logger log = Logger.getLogger(LDAPEmbeddedServer.class);
|
||||
|
||||
public static final String PROPERTY_BASE_DN = "ldap.baseDN";
|
||||
public static final String PROPERTY_BIND_HOST = "ldap.host";
|
||||
public static final String PROPERTY_BIND_PORT = "ldap.port";
|
||||
public static final String PROPERTY_LDIF_FILE = "ldap.ldif";
|
||||
public static final String PROPERTY_SASL_PRINCIPAL = "ldap.saslPrincipal";
|
||||
public static final String PROPERTY_DSF = "ldap.dsf";
|
||||
|
||||
private static final String DEFAULT_BASE_DN = "dc=keycloak,dc=org";
|
||||
private static final String DEFAULT_BIND_HOST = "localhost";
|
||||
private static final String DEFAULT_BIND_PORT = "10389";
|
||||
private static final String DEFAULT_LDIF_FILE = "classpath:ldap/default-users.ldif";
|
||||
|
||||
public static final String DSF_INMEMORY = "mem";
|
||||
public static final String DSF_FILE = "file";
|
||||
public static final String DEFAULT_DSF = DSF_FILE;
|
||||
|
||||
protected Properties defaultProperties;
|
||||
|
||||
protected String baseDN;
|
||||
protected String bindHost;
|
||||
protected int bindPort;
|
||||
protected String ldifFile;
|
||||
protected String ldapSaslPrincipal;
|
||||
protected String directoryServiceFactory;
|
||||
|
||||
protected DirectoryService directoryService;
|
||||
protected LdapServer ldapServer;
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Properties defaultProperties = new Properties();
|
||||
defaultProperties.put(PROPERTY_DSF, DSF_FILE);
|
||||
|
||||
execute(args, defaultProperties);
|
||||
}
|
||||
|
||||
public static void execute(String[] args, Properties defaultProperties) throws Exception {
|
||||
final LDAPEmbeddedServer ldapEmbeddedServer = new LDAPEmbeddedServer(defaultProperties);
|
||||
ldapEmbeddedServer.init();
|
||||
ldapEmbeddedServer.start();
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ldapEmbeddedServer.stop();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public LDAPEmbeddedServer(Properties defaultProperties) {
|
||||
this.defaultProperties = defaultProperties;
|
||||
|
||||
this.baseDN = readProperty(PROPERTY_BASE_DN, DEFAULT_BASE_DN);
|
||||
this.bindHost = readProperty(PROPERTY_BIND_HOST, DEFAULT_BIND_HOST);
|
||||
String bindPort = readProperty(PROPERTY_BIND_PORT, DEFAULT_BIND_PORT);
|
||||
this.bindPort = Integer.parseInt(bindPort);
|
||||
this.ldifFile = readProperty(PROPERTY_LDIF_FILE, DEFAULT_LDIF_FILE);
|
||||
this.ldapSaslPrincipal = readProperty(PROPERTY_SASL_PRINCIPAL, null);
|
||||
this.directoryServiceFactory = readProperty(PROPERTY_DSF, DEFAULT_DSF);
|
||||
}
|
||||
|
||||
protected String readProperty(String propertyName, String defaultValue) {
|
||||
String value = System.getProperty(propertyName);
|
||||
|
||||
if (value == null || value.isEmpty()) {
|
||||
value = (String) this.defaultProperties.get(propertyName);
|
||||
}
|
||||
|
||||
if (value == null || value.isEmpty()) {
|
||||
value = defaultValue;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
public void init() throws Exception {
|
||||
log.info("Creating LDAP Directory Service. Config: baseDN=" + baseDN + ", bindHost=" + bindHost + ", bindPort=" + bindPort +
|
||||
", ldapSaslPrincipal=" + ldapSaslPrincipal + ", directoryServiceFactory=" + directoryServiceFactory + ", ldif=" + ldifFile);
|
||||
|
||||
this.directoryService = createDirectoryService();
|
||||
|
||||
log.info("Importing LDIF: " + ldifFile);
|
||||
importLdif();
|
||||
|
||||
log.info("Creating LDAP Server");
|
||||
this.ldapServer = createLdapServer();
|
||||
}
|
||||
|
||||
|
||||
public void start() throws Exception {
|
||||
log.info("Starting LDAP Server");
|
||||
ldapServer.start();
|
||||
log.info("LDAP Server started");
|
||||
}
|
||||
|
||||
|
||||
protected DirectoryService createDirectoryService() throws Exception {
|
||||
// Parse "keycloak" from "dc=keycloak,dc=org"
|
||||
String dcName = baseDN.split(",")[0];
|
||||
dcName = dcName.substring(dcName.indexOf("=") + 1);
|
||||
|
||||
DirectoryServiceFactory dsf;
|
||||
if (this.directoryServiceFactory.equals(DSF_INMEMORY)) {
|
||||
dsf = new InMemoryDirectoryServiceFactory();
|
||||
} else if (this.directoryServiceFactory.equals(DSF_FILE)) {
|
||||
dsf = new FileDirectoryServiceFactory();
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown value of directoryServiceFactory: " + this.directoryServiceFactory);
|
||||
}
|
||||
|
||||
DirectoryService service = dsf.getDirectoryService();
|
||||
service.setAccessControlEnabled(false);
|
||||
service.setAllowAnonymousAccess(false);
|
||||
service.getChangeLog().setEnabled(false);
|
||||
|
||||
dsf.init(dcName + "DS");
|
||||
|
||||
SchemaManager schemaManager = service.getSchemaManager();
|
||||
|
||||
PartitionFactory partitionFactory = dsf.getPartitionFactory();
|
||||
Partition partition = partitionFactory.createPartition(
|
||||
schemaManager,
|
||||
service.getDnFactory(),
|
||||
dcName,
|
||||
this.baseDN,
|
||||
1000,
|
||||
new File(service.getInstanceLayout().getPartitionsDirectory(), dcName));
|
||||
partition.setCacheService( service.getCacheService() );
|
||||
partition.initialize();
|
||||
|
||||
partition.setSchemaManager( schemaManager );
|
||||
|
||||
// Inject the partition into the DirectoryService
|
||||
service.addPartition( partition );
|
||||
|
||||
// Last, process the context entry
|
||||
String entryLdif =
|
||||
"dn: " + baseDN + "\n" +
|
||||
"dc: " + dcName + "\n" +
|
||||
"objectClass: top\n" +
|
||||
"objectClass: domain\n\n";
|
||||
importLdifContent(service, entryLdif);
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
protected LdapServer createLdapServer() {
|
||||
LdapServer ldapServer = new LdapServer();
|
||||
|
||||
ldapServer.setServiceName("DefaultLdapServer");
|
||||
ldapServer.setSearchBaseDn(this.baseDN);
|
||||
|
||||
// Read the transports
|
||||
Transport ldap = new TcpTransport(this.bindHost, this.bindPort, 3, 50);
|
||||
ldapServer.addTransports( ldap );
|
||||
|
||||
// Associate the DS to this LdapServer
|
||||
ldapServer.setDirectoryService( directoryService );
|
||||
|
||||
// Propagate the anonymous flag to the DS
|
||||
directoryService.setAllowAnonymousAccess(false);
|
||||
|
||||
return ldapServer;
|
||||
}
|
||||
|
||||
|
||||
private void importLdif() throws Exception {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("hostname", this.bindHost);
|
||||
if (this.ldapSaslPrincipal != null) {
|
||||
map.put("ldapSaslPrincipal", this.ldapSaslPrincipal);
|
||||
}
|
||||
|
||||
// Find LDIF file on filesystem or classpath ( if it's like classpath:ldap/users.ldif )
|
||||
InputStream is = FindFile.findFile(ldifFile);
|
||||
if (is == null) {
|
||||
throw new IllegalStateException("LDIF file not found on classpath or on file system. Location was: " + ldifFile);
|
||||
}
|
||||
|
||||
final String ldifContent = StrSubstitutor.replace(StreamUtil.readString(is), map);
|
||||
log.info("Content of LDIF: " + ldifContent);
|
||||
final SchemaManager schemaManager = directoryService.getSchemaManager();
|
||||
|
||||
importLdifContent(directoryService, ldifContent);
|
||||
}
|
||||
|
||||
private static void importLdifContent(DirectoryService directoryService, String ldifContent) throws Exception {
|
||||
LdifReader ldifReader = new LdifReader(IOUtils.toInputStream(ldifContent));
|
||||
|
||||
try {
|
||||
for (LdifEntry ldifEntry : ldifReader) {
|
||||
try {
|
||||
directoryService.getAdminSession().add(new DefaultEntry(directoryService.getSchemaManager(), ldifEntry.getEntry()));
|
||||
} catch (LdapEntryAlreadyExistsException ignore) {
|
||||
log.info("Entry " + ldifEntry.getDn() + " already exists. Ignoring");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
ldifReader.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void stop() throws Exception {
|
||||
stopLdapServer();
|
||||
shutdownDirectoryService();
|
||||
}
|
||||
|
||||
|
||||
protected void stopLdapServer() {
|
||||
log.info("Stopping LDAP server.");
|
||||
ldapServer.stop();
|
||||
}
|
||||
|
||||
|
||||
protected void shutdownDirectoryService() throws Exception {
|
||||
log.info("Stopping Directory service.");
|
||||
directoryService.shutdown();
|
||||
|
||||
// Delete workfiles just for 'inmemory' implementation used in tests. Normally we want LDAP data to persist
|
||||
File instanceDir = directoryService.getInstanceLayout().getInstanceDirectory();
|
||||
if (this.directoryServiceFactory.equals(DSF_INMEMORY)) {
|
||||
log.infof("Removing Directory service workfiles: %s", instanceDir.getAbsolutePath());
|
||||
FileUtils.deleteDirectory(instanceDir);
|
||||
} else {
|
||||
log.info("Working LDAP directory not deleted. Delete it manually if you want to start with fresh LDAP data. Directory location: " + instanceDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
dn: dc=keycloak,dc=org
|
||||
objectclass: dcObject
|
||||
objectclass: organization
|
||||
o: Keycloak
|
||||
dc: Keycloak
|
||||
|
||||
dn: ou=People,dc=keycloak,dc=org
|
||||
objectClass: organizationalUnit
|
||||
objectClass: top
|
||||
ou: People
|
||||
|
||||
dn: uid=krbtgt,ou=People,dc=keycloak,dc=org
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: krb5principal
|
||||
objectClass: krb5kdcentry
|
||||
cn: KDC Service
|
||||
sn: Service
|
||||
uid: krbtgt
|
||||
userPassword: secret
|
||||
krb5PrincipalName: krbtgt/KEYCLOAK.ORG@KEYCLOAK.ORG
|
||||
krb5KeyVersionNumber: 0
|
||||
|
||||
dn: uid=ldap,ou=People,dc=keycloak,dc=org
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: krb5principal
|
||||
objectClass: krb5kdcentry
|
||||
cn: LDAP
|
||||
sn: Service
|
||||
uid: ldap
|
||||
userPassword: randall
|
||||
krb5PrincipalName: ${ldapSaslPrincipal}
|
||||
krb5KeyVersionNumber: 0
|
||||
|
||||
dn: uid=HTTP,ou=People,dc=keycloak,dc=org
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: krb5principal
|
||||
objectClass: krb5kdcentry
|
||||
cn: HTTP
|
||||
sn: Service
|
||||
uid: HTTP
|
||||
userPassword: httppwd
|
||||
krb5PrincipalName: HTTP/${hostname}@KEYCLOAK.ORG
|
||||
krb5KeyVersionNumber: 0
|
||||
|
||||
dn: uid=hnelson,ou=People,dc=keycloak,dc=org
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: krb5principal
|
||||
objectClass: krb5kdcentry
|
||||
cn: Horatio
|
||||
sn: Nelson
|
||||
mail: hnelson@keycloak.org
|
||||
uid: hnelson
|
||||
userPassword: secret
|
||||
krb5PrincipalName: hnelson@KEYCLOAK.ORG
|
||||
krb5KeyVersionNumber: 0
|
||||
|
||||
dn: uid=jduke,ou=People,dc=keycloak,dc=org
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: krb5principal
|
||||
objectClass: krb5kdcentry
|
||||
cn: Java
|
||||
sn: Duke
|
||||
mail: jduke@keycloak.org
|
||||
uid: jduke
|
||||
userPassword: theduke
|
||||
krb5PrincipalName: jduke@KEYCLOAK.ORG
|
||||
krb5KeyVersionNumber: 0
|
||||
|
||||
dn: uid=gsstestserver,ou=People,dc=keycloak,dc=org
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: krb5principal
|
||||
objectClass: krb5kdcentry
|
||||
cn: gsstestserver
|
||||
sn: Service
|
||||
uid: gsstestserver
|
||||
userPassword: gsstestpwd
|
||||
krb5PrincipalName: gsstestserver/xxx@KEYCLOAK.ORG
|
||||
krb5KeyVersionNumber: 0
|
|
@ -0,0 +1,47 @@
|
|||
dn: dc=keycloak,dc=org
|
||||
objectclass: dcObject
|
||||
objectclass: organization
|
||||
o: Keycloak
|
||||
dc: Keycloak
|
||||
|
||||
dn: ou=People,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: People
|
||||
|
||||
dn: ou=RealmRoles,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: RealmRoles
|
||||
|
||||
dn: ou=FinanceRoles,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: FinanceRoles
|
||||
|
||||
dn: uid=jbrown,ou=People,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
uid: jbrown
|
||||
cn: James
|
||||
sn: Brown
|
||||
mail: jbrown@keycloak.org
|
||||
postalCode: 88441
|
||||
userPassword: password
|
||||
|
||||
dn: uid=bwilson,ou=People,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
uid: bwilson
|
||||
cn: Bruce
|
||||
sn: Wilson
|
||||
sn: Schneider
|
||||
mail: bwilson@keycloak.org
|
||||
postalCode: 88441
|
||||
postalCode: 77332
|
||||
street: Elm 5
|
||||
userPassword: password
|
9
util/embedded-ldap/src/main/resources/log4j.properties
Normal file
9
util/embedded-ldap/src/main/resources/log4j.properties
Normal file
|
@ -0,0 +1,9 @@
|
|||
log4j.rootLogger=info, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] %m%n
|
||||
|
||||
log4j.logger.org.keycloak=info
|
||||
log4j.logger.org.apache.directory.api=warn
|
||||
log4j.logger.org.apache.directory.server.core=warn
|
22
util/pom.xml
Normal file
22
util/pom.xml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.4.0.Final-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<name>Keycloak Util Parent</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-util-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>embedded-ldap</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
Loading…
Reference in a new issue