You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/10/12 11:53:12 UTC
[camel] branch camel-4.0.x updated: Refactored LDAP docs (#11709)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.0.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.0.x by this push:
new c25f74a6396 Refactored LDAP docs (#11709)
c25f74a6396 is described below
commit c25f74a639649f09c0eb53d2eb07bba112cec0c4
Author: Darren Coleman <dc...@redhat.com>
AuthorDate: Thu Oct 12 12:53:03 2023 +0100
Refactored LDAP docs (#11709)
Moved Spring-specific content into dedicated tabs, and added a equivalent tabs for Camel Quarkus.
---
.../camel-ldap/src/main/docs/ldap-component.adoc | 165 +++++++++++++++++++--
1 file changed, 155 insertions(+), 10 deletions(-)
diff --git a/components/camel-ldap/src/main/docs/ldap-component.adoc b/components/camel-ldap/src/main/docs/ldap-component.adoc
index 08faad5fa56..d5bf23823a7 100644
--- a/components/camel-ldap/src/main/docs/ldap-component.adoc
+++ b/components/camel-ldap/src/main/docs/ldap-component.adoc
@@ -64,9 +64,33 @@ The result is returned to Out body as a `List<javax.naming.directory.SearchResul
== DirContext
-The URI, `ldap:ldapserver`, references a Spring bean with the ID,
+The URI, `ldap:ldapserver`, references a bean with the ID
`ldapserver`. The `ldapserver` bean may be defined as follows:
+[tabs]
+====
+Java (Quarkus)::
++
+[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);
+ }
+}
+----
+
+XML (Spring)::
++
[source,xml]
-----------------------------------------------------------------------------------------
<bean id="ldapserver" class="javax.naming.directory.InitialDirContext" scope="prototype">
@@ -79,18 +103,16 @@ The URI, `ldap:ldapserver`, references a Spring bean with the ID,
</constructor-arg>
</bean>
-----------------------------------------------------------------------------------------
+====
The preceding example declares a regular Sun based LDAP `DirContext`
that connects anonymously to a locally hosted LDAP server.
[NOTE]
====
-`DirContext` objects are *not* required to support concurrency by
-contract. It is therefore important that the directory context is
-declared with the setting, `scope="prototype"`, in the `bean` definition
-or that the context supports concurrency. In the Spring framework,
-`prototype` scoped objects are instantiated each time they are looked
-up.
+`DirContext` objects are *not* required to support concurrency by contract. It is therefore important to manage the directory context's lifecycle appropriately. In the Spring framework, `prototype` scoped objects are instantiated each time they are looked up to ensure concurrency and avoid sharing the same context between multiple threads.
+
+For Camel Quarkus applications, you can achieve similar behavior by using the `@Dependent` annotation. When you annotate a component or bean with `@Dependent`, a new instance of the component is created for each injection point or usage, which effectively provides the same concurrency guarantees as Spring's `prototype` scope. This ensures that each part of your application interacts with a separate and isolated `DirContext` instance, preventing unintended thread interference.
====
== Security concerns related to LDAP injection
@@ -105,7 +127,7 @@ for information about https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Inject
== Samples
-Following on from the Spring configuration above, the code sample below
+Following on from the configuration above, the code sample below
sends an LDAP request to filter search a group for a member. The Common
Name is then extracted from the response.
@@ -120,7 +142,7 @@ Collection<SearchResult> results = template.requestBody(
if (results.size() > 0) {
// Extract what we need from the device's profile
- Iterator resultIter = results.iterator();
+ Iterator<SearchResult> resultIter = results.iterator();
SearchResult searchResult = (SearchResult) resultIter.next();
Attributes attributes = searchResult.getAttributes();
Attribute deviceCNAttr = attributes.get("cn");
@@ -190,6 +212,31 @@ the InitialDirContext bean - see below sample.
*SSL Configuration*
+[tabs]
+====
+Java (Quarkus)::
++
+[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);
+ }
+}
+----
+
+XML (Spring)::
++
[source,xml]
----------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
@@ -223,9 +270,107 @@ the InitialDirContext bean - see below sample.
</bean>
</beans>
----------------------------------------------------------------------------------------------------------------------------------
+====
*Custom Socket Factory*
+[tabs]
+====
+Java (Quarkus)::
++
+[source,java]
+----
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.KeyStore;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.eclipse.microprofile.config.ConfigProvider;
+
+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
+----
+
+XML (Spring)::
++
[source,java]
-----------------------------------------------------------------------------------------------------
package com.example.ldap;
@@ -314,6 +459,6 @@ public class CustomSocketFactory extends SSLSocketFactory {
}
}
-----------------------------------------------------------------------------------------------------
-
+====
include::spring-boot:partial$starter.adoc[]