LDAP
JVM since1.1.0 Native since3.0.0
Perform searches on LDAP servers.
What’s inside
-
LDAP component, URI syntax:
ldap:dirContextName
Please refer to the above link for usage and configuration details.
Maven coordinates
Or add the coordinates to your existing project:
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-ldap</artifactId>
</dependency>
Check the User guide for more information about writing Camel Quarkus applications.
Usage
DirContext
The URI, ldap:ldapserver
, references a bean with the ID ldapserver
. A CDI producer method may be used to instantiate a DirContext
object as follows:
public class LdapServerProducer {
@Produces
@Dependent
@Named("ldapserver")
public DirContext createLdapServer() throws Exception {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389");
env.put(Context.SECURITY_AUTHENTICATION, "none");
return new InitialDirContext(env);
}
}
The preceding example creates a regular Sun based LDAP DirContext
that connects anonymously to a locally hosted LDAP server. The use of the @Named
annotation binds the DirContext
into the Camel registry automatically.
Configuring SSL
When connecting to an LDAP server over SSL/TLS, you may encounter situations where the default trust manager used by the JVM is unable to verify the certificate. This can happen, for example, when the server uses a self-signed certificate or when the certificate is issued by a non-trusted CA. In such cases, you may need to provide a custom trust manager implementation that can verify the server’s certificate.
The following code shows an implementation of a custom socket factory that can be used to create SSL/TLS sockets. The class name of the custom SSL socket factory is then specified in the java.naming.ldap.factory.socket
property of the environment hashtable used to create the LDAP context.
public class CustomSSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory delegate;
public CustomSSLSocketFactory() throws Exception {
String trustStoreFilename = ConfigProvider.getConfig().getValue("ldap.trustStore", String.class);
String trustStorePassword = ConfigProvider.getConfig().getValue("ldap.trustStorePassword", String.class);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream in = new FileInputStream(trustStoreFilename)) {
keyStore.load(in, trustStorePassword.toCharArray());
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
delegate = ctx.getSocketFactory();
}
public static SocketFactory getDefault() {
try {
return new CustomSSLSocketFactory();
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return delegate.createSocket(s, host, port, autoClose);
}
@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return delegate.createSocket(host, port);
}
@Override
public Socket createSocket(InetAddress address, int port) throws IOException {
return delegate.createSocket(address, port);
}
@Override
public Socket createSocket(String host, int port, InetAddress localAddress, int localPort)
throws IOException, UnknownHostException {
return delegate.createSocket(host, port, localAddress, localPort);
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
throws IOException {
return delegate.createSocket(address, port, localAddress, localPort);
}
}
The constructor uses the ConfigProvider
to read the ldap.trustStore
and ldap.trustStorePassword
configuration properties, which could be specified in the application.properties
file as follows:
ldap.trustStore=/path/to/truststore.jks
ldap.trustStorePassword=secret
Finally, alter the LdapServerProducer.createLdapServer()
method so that the PROVIDER_URL
entry uses the ldaps
protocol instead of ldap
, and add the CustomSSLSocketFactory
entry:
public class LdapServerProducer {
@Produces
@Dependent
@Named("ldapserver")
public DirContext createLdapServer() throws Exception {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldaps://" + InetAddress.getLocalHost().getCanonicalHostName() + ":10636");
env.put(Context.SECURITY_AUTHENTICATION, "none");
env.put("java.naming.ldap.factory.socket", CustomSSLSocketFactory.class.getName());
return new InitialDirContext(env);
}
}
Using SSL in Native Mode
When using a custom SSLSocketFactory
in native mode, you need to register the class for reflection otherwise the class will not be made available on the classpath. Add the @RegisterForReflection
annotation above the class definition, as follows:
@RegisterForReflection
public class CustomSSLSocketFactory extends SSLSocketFactory {
// The class definition is the same as above.
}