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

jamesnetherton pushed a commit to branch 3.2.x
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit dc220e3bf1924e6b9602f66c8ee5c768115ba55d
Author: Darren Coleman <[email protected]>
AuthorDate: Mon Sep 18 12:21:36 2023 +0100

    Updates to LDAP tests and usage docs (#5310)
    
    Fixes #5309
---
 .../ROOT/pages/reference/extensions/ldap.adoc      | 136 +--------------------
 extensions/ldap/runtime/src/main/doc/usage.adoc    | 134 +-------------------
 .../quarkus/component/ldap/it/LdapResource.java    |  48 +++++---
 .../camel/quarkus/component/ldap/it/LdapTest.java  |  28 ++++-
 4 files changed, 60 insertions(+), 286 deletions(-)

diff --git a/docs/modules/ROOT/pages/reference/extensions/ldap.adoc 
b/docs/modules/ROOT/pages/reference/extensions/ldap.adoc
index f0880d6d3d..8194a85386 100644
--- a/docs/modules/ROOT/pages/reference/extensions/ldap.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/ldap.adoc
@@ -46,146 +46,16 @@ endif::[]
 
 [id="extensions-ldap-usage"]
 == Usage
-[id="extensions-ldap-usage-dircontext"]
-=== 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:
-
-[source,java]
-----
-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.
-
-[id="extensions-ldap-usage-configuring-ssl"]
-=== 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.
-
-[source,java]
-----
-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:
-
-[source,properties]
-----
-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:
-
-[source,java]
-----
-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);
-    }
-}
-----
-
 [id="extensions-ldap-usage-using-ssl-in-native-mode"]
-==== Using SSL in Native Mode
+=== 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:
+When using a custom `SSLSocketFactory` in native mode, such as the one in the 
xref:{cq-camel-components}::ldap-component.adoc#_configuring_ssl[Configuring 
SSL] section, 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:
 
 [source,java]
 ----
 @RegisterForReflection
 public class CustomSSLSocketFactory extends SSLSocketFactory {
-    // The class definition is the same as above. 
+    // The class definition is the same as in the above link. 
 }
 ----
 
diff --git a/extensions/ldap/runtime/src/main/doc/usage.adoc 
b/extensions/ldap/runtime/src/main/doc/usage.adoc
index ffbc96e7c5..dbb52638a8 100644
--- a/extensions/ldap/runtime/src/main/doc/usage.adoc
+++ b/extensions/ldap/runtime/src/main/doc/usage.adoc
@@ -1,139 +1,11 @@
-=== DirContext
+=== Using SSL in Native Mode
 
-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:
-
-[source,java]
-----
-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.
-
-[source,java]
-----
-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:
-
-[source,properties]
-----
-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:
-
-[source,java]
-----
-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:
+When using a custom `SSLSocketFactory` in native mode, such as the one in the 
xref:{cq-camel-components}::ldap-component.adoc#_configuring_ssl[Configuring 
SSL] section, 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:
 
 [source,java]
 ----
 @RegisterForReflection
 public class CustomSSLSocketFactory extends SSLSocketFactory {
-    // The class definition is the same as above. 
+    // The class definition is the same as in the above link. 
 }
 ----
diff --git 
a/integration-tests/ldap/src/main/java/org/apache/camel/quarkus/component/ldap/it/LdapResource.java
 
b/integration-tests/ldap/src/main/java/org/apache/camel/quarkus/component/ldap/it/LdapResource.java
index 746524857b..73828a6c02 100644
--- 
a/integration-tests/ldap/src/main/java/org/apache/camel/quarkus/component/ldap/it/LdapResource.java
+++ 
b/integration-tests/ldap/src/main/java/org/apache/camel/quarkus/component/ldap/it/LdapResource.java
@@ -30,7 +30,9 @@ import javax.naming.directory.InitialDirContext;
 import javax.naming.directory.SearchResult;
 
 import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.context.Dependent;
 import jakarta.inject.Inject;
+import jakarta.inject.Named;
 import jakarta.ws.rs.Consumes;
 import jakarta.ws.rs.GET;
 import jakarta.ws.rs.POST;
@@ -50,6 +52,12 @@ public class LdapResource {
     @Inject
     CamelContext camelContext;
 
+    private String ldapHost;
+    private String ldapPort;
+    private boolean useSSL;
+    private String trustStoreFilename;
+    private String trustStorePassword;
+
     /**
      * Extracts the LDAP connection parameters passed from the test and 
creates a
      * {@link javax.naming.directory.DirContext} from them.
@@ -62,43 +70,43 @@ public class LdapResource {
     @POST
     @Consumes(MediaType.APPLICATION_JSON)
     public void configure(Map<String, String> options) throws Exception {
-        String host = options.get("host");
-        String port = options.get("port");
-        boolean useSSL = Boolean.valueOf(options.get("ssl"));
-        String trustStoreFilename = options.get("trustStore");
-        String trustStorePassword = options.get("trustStorePassword");
-
-        DirContext dirContext = createLdapContext(host, port, useSSL, 
trustStoreFilename, trustStorePassword);
-        camelContext.getRegistry().bind("ldapserver", dirContext);
+        ldapHost = options.get("host");
+        ldapPort = options.get("port");
+        useSSL = Boolean.valueOf(options.get("ssl"));
+        trustStoreFilename = options.get("trustStore");
+        trustStorePassword = options.get("trustStorePassword");
     }
 
     @Path("/search")
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    public Response search(@QueryParam("q") String filter) throws Exception {
-        ProducerTemplate producer = camelContext.createProducerTemplate();
-        List<SearchResult> results = producer.requestBody("direct:start", 
filter, List.class);
-        return Response.ok(convertSearchResults(results)).build();
+    public Response search(@QueryParam("q") String q) throws Exception {
+        return Response.ok(searchByUid(q)).build();
     }
 
     @Path("/safeSearch")
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    public Response safeSearch(@QueryParam("q") String unsafeFilter) throws 
Exception {
-        String filter = String.format("(ou=%s)", 
LdapHelper.escapeFilter(unsafeFilter));
+    public Response safeSearch(@QueryParam("q") String q) throws Exception {
+        return Response.ok(searchByUid(LdapHelper.escapeFilter(q))).build();
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<Map<String, String>> searchByUid(String uid) throws Exception 
{
+        String filter = String.format("(uid=%s)", uid);
         ProducerTemplate producer = camelContext.createProducerTemplate();
         List<SearchResult> results = producer.requestBody("direct:start", 
filter, List.class);
-
-        return Response.ok(convertSearchResults(results)).build();
+        return convertSearchResults(results);
     }
 
-    private DirContext createLdapContext(String host, String port, boolean 
useSSL, String trustStoreFilename,
-            String trustStorePassword)
-            throws Exception {
+    @Produces
+    @Dependent
+    @Named("ldapserver")
+    public DirContext createLdapContext() throws Exception {
         String scheme = useSSL ? "ldaps" : "ldap";
         Hashtable<String, Object> env = new Hashtable<>();
         env.put(Context.INITIAL_CONTEXT_FACTORY, 
"com.sun.jndi.ldap.LdapCtxFactory");
-        env.put(Context.PROVIDER_URL, String.format("%s://%s:%s", scheme, 
host, port));
+        env.put(Context.PROVIDER_URL, String.format("%s://%s:%s", scheme, 
ldapHost, ldapPort));
         env.put(Context.SECURITY_AUTHENTICATION, "none");
 
         if (useSSL) {
diff --git 
a/integration-tests/ldap/src/test/java/org/apache/camel/quarkus/component/ldap/it/LdapTest.java
 
b/integration-tests/ldap/src/test/java/org/apache/camel/quarkus/component/ldap/it/LdapTest.java
index 672a437f82..962ec3b7c7 100644
--- 
a/integration-tests/ldap/src/test/java/org/apache/camel/quarkus/component/ldap/it/LdapTest.java
+++ 
b/integration-tests/ldap/src/test/java/org/apache/camel/quarkus/component/ldap/it/LdapTest.java
@@ -24,6 +24,7 @@ import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import com.unboundid.ldap.listener.InMemoryDirectoryServer;
 import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
@@ -110,7 +111,7 @@ class LdapTest {
         TypeRef<List<Map<String, Object>>> typeRef = new TypeRef<>() {
         };
         List<Map<String, Object>> results = RestAssured.given()
-                .queryParam("q", "(uid=tcruise)")
+                .queryParam("q", "tcruise")
                 .get("/ldap/search")
                 .then()
                 .statusCode(200)
@@ -132,14 +133,37 @@ class LdapTest {
 
         TypeRef<List<Map<String, Object>>> typeRef = new TypeRef<>() {
         };
+
+        // Verfiy that calling the unsafe endpoint with a wildcard returns 
multiple results.
         List<Map<String, Object>> results = RestAssured.given()
                 .queryParam("q", "test*")
-                .get("/ldap/safeSearch")
+                .get("/ldap/search")
                 .then()
                 .statusCode(200)
                 .extract().as(typeRef);
+        assertEquals(3, results.size());
+        assertEquals(List.of("test1", "test2", "testNoOU"),
+                results.stream().map(r -> 
r.get("uid")).collect(Collectors.toList()));
 
+        // Verify that the same query passed to the safeSearch returns no 
matching results.
+        results = RestAssured.given()
+                .queryParam("q", "test*")
+                .get("/ldap/safeSearch")
+                .then()
+                .statusCode(200)
+                .extract().as(typeRef);
         assertEquals(0, results.size());
+
+        // Verify that non-escaped queries also work with escaped search
+        results = RestAssured.given()
+                .queryParam("q", "test1")
+                .get("/ldap/safeSearch")
+                .then()
+                .statusCode(200)
+                .extract().as(typeRef);
+        assertEquals(1, results.size());
+        assertEquals("test1", results.get(0).get("ou"));
+
     }
 
     /**

Reply via email to