This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch 3.27.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 45983836de9cea8818b408c434d992fc748ae370 Author: Andrea Cosentino <[email protected]> AuthorDate: Tue Sep 1 12:22:13 2026 +0200 Fixes #9054. Only set LDAP security-authentication when it is configured securityAuthentication() carried @WithDefault("none") while its documentation said the behaviour is determined by the service provider when the property is unspecified, and it was the only option in the group with a default. The recorder put that value into the JNDI environment for every directory context. An operator supplying only a principal and credentials through additional-options, which is the only way to pass them, therefore got an anonymous bind with the credentials silently ignored. Make it Optional and set it only when configured, matching the documentation and the surrounding options. Adds a migration guide note, since a context that relied on the default now lets the provider decide. The new LdapTest case asserts the property reaches the JNDI environment only for a context that configures it. It fails against the previous behaviour. Co-authored-by: Claude Opus 5 (1M context) <[email protected]> (cherry picked from commit 3ad9f401c496fb97838e1208b72ceb20fc32a768) --- .../modules/ROOT/pages/migration-guide/3.40.0.adoc | 20 ++++++++++++++++++++ .../ROOT/pages/reference/extensions/ldap.adoc | 2 +- .../quarkus/component/ldap/CamelLdapConfig.java | 4 +--- .../quarkus/component/ldap/CamelLdapRecorder.java | 2 +- .../quarkus/component/ldap/it/LdapResource.java | 17 +++++++++++++++++ .../camel/quarkus/component/ldap/it/LdapTest.java | 22 ++++++++++++++++++++++ 6 files changed, 62 insertions(+), 5 deletions(-) diff --git a/docs/modules/ROOT/pages/migration-guide/3.40.0.adoc b/docs/modules/ROOT/pages/migration-guide/3.40.0.adoc new file mode 100644 index 0000000000..69cb3e0074 --- /dev/null +++ b/docs/modules/ROOT/pages/migration-guide/3.40.0.adoc @@ -0,0 +1,20 @@ += Camel Quarkus 3.40.0 Migration Guide + +The following guide outlines how to adapt your code to changes that were made in Camel Quarkus 3.40.0. + +== LDAP extension changes + +=== security-authentication is no longer defaulted to none + +`quarkus.camel.ldap.dir-contexts."name".security-authentication` previously defaulted to `none`, which was put into the JNDI environment for every directory context whether or not it had been configured. Its documentation has always said that the behaviour is determined by the service provider when the property is unspecified, and it is now the only option in that configuration group without a default, matching `initial-context-factory`, `provider-url`, `security-protocol` and `socket-factory`. + +The property is now only placed into the JNDI environment when it is configured, so the service provider decides otherwise. + +This matters where credentials are supplied through `additional-options`, which is the only way to pass them. Previously `none` was already in the environment, and supplying only a principal and credentials left the bind anonymous with the credentials ignored. They now take effect. + +To keep the previous behaviour for a context that relied on the default, set it explicitly. + +[source,properties] +---- +quarkus.camel.ldap.dir-contexts."my-context".security-authentication=none +---- diff --git a/docs/modules/ROOT/pages/reference/extensions/ldap.adoc b/docs/modules/ROOT/pages/reference/extensions/ldap.adoc index c9eaef3000..159cdc58a7 100644 --- a/docs/modules/ROOT/pages/reference/extensions/ldap.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/ldap.adoc @@ -136,7 +136,7 @@ Its value is one of the following strings: If this property is unspecified, the behaviour is determined by the service provider. | `string` -| `none` +| a| [[quarkus-camel-ldap-dir-contexts-dir-contexts-socket-factory]]`link:#quarkus-camel-ldap-dir-contexts-dir-contexts-socket-factory[quarkus.camel.ldap.dir-contexts."dir-contexts".socket-factory]` diff --git a/extensions/ldap/runtime/src/main/java/org/apache/camel/quarkus/component/ldap/CamelLdapConfig.java b/extensions/ldap/runtime/src/main/java/org/apache/camel/quarkus/component/ldap/CamelLdapConfig.java index 9036fbac4e..a4585daee2 100644 --- a/extensions/ldap/runtime/src/main/java/org/apache/camel/quarkus/component/ldap/CamelLdapConfig.java +++ b/extensions/ldap/runtime/src/main/java/org/apache/camel/quarkus/component/ldap/CamelLdapConfig.java @@ -23,7 +23,6 @@ import io.quarkus.runtime.annotations.ConfigGroup; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; import io.smallrye.config.ConfigMapping; -import io.smallrye.config.WithDefault; @ConfigRoot(phase = ConfigPhase.RUN_TIME) @ConfigMapping(prefix = "quarkus.camel.ldap") @@ -64,8 +63,7 @@ public interface CamelLdapConfig { * If this property is unspecified, * the behaviour is determined by the service provider. */ - @WithDefault("none") - String securityAuthentication(); + Optional<String> securityAuthentication(); /** * The custom socket factory to use. The value of the property should be the fully qualified class name diff --git a/extensions/ldap/runtime/src/main/java/org/apache/camel/quarkus/component/ldap/CamelLdapRecorder.java b/extensions/ldap/runtime/src/main/java/org/apache/camel/quarkus/component/ldap/CamelLdapRecorder.java index 0fb6a451c8..008e2ad4fc 100644 --- a/extensions/ldap/runtime/src/main/java/org/apache/camel/quarkus/component/ldap/CamelLdapRecorder.java +++ b/extensions/ldap/runtime/src/main/java/org/apache/camel/quarkus/component/ldap/CamelLdapRecorder.java @@ -42,7 +42,7 @@ public class CamelLdapRecorder { Hashtable<String, Object> env = new Hashtable<>(); dirConfig.initialContextFactory().ifPresent(v -> env.put(Context.INITIAL_CONTEXT_FACTORY, v)); dirConfig.providerUrl().ifPresent(v -> env.put(Context.PROVIDER_URL, v)); - env.put(Context.SECURITY_AUTHENTICATION, dirConfig.securityAuthentication()); + dirConfig.securityAuthentication().ifPresent(v -> env.put(Context.SECURITY_AUTHENTICATION, v)); dirConfig.securityProtocol().ifPresent(v -> env.put(Context.SECURITY_PROTOCOL, v)); dirConfig.socketFactory().ifPresent(v -> env.put("java.naming.ldap.factory.socket", v)); 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 03ae765b57..01fb8fd136 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 @@ -18,6 +18,7 @@ package org.apache.camel.quarkus.component.ldap.it; import java.util.ArrayList; import java.util.HashMap; +import java.util.Hashtable; import java.util.List; import java.util.Map; @@ -53,6 +54,22 @@ public class LdapResource { return Response.ok(searchByUid(directName, ldapQuery)).build(); } + /** + * Reports a single entry of the JNDI environment bound for the named dir context, so that a test can assert + * which properties the extension actually put there. Answers {@code <absent>} when the key was not set. + */ + @Path("/dirContextEnv/{name}/{key}") + @GET + @Produces(MediaType.TEXT_PLAIN) + public Response dirContextEnv(@PathParam("name") String name, @PathParam("key") String key) { + Hashtable<?, ?> env = camelContext.getRegistry().lookupByNameAndType(name, Hashtable.class); + if (env == null) { + return Response.status(Response.Status.NOT_FOUND).build(); + } + Object value = env.get(key); + return Response.ok(value == null ? "<absent>" : value.toString()).build(); + } + @Path("/safeSearch") @GET @Produces(MediaType.APPLICATION_JSON) 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 20ec562f0e..a501c432d8 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 @@ -31,6 +31,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; @TestCertificates(certificates = { @@ -46,6 +47,27 @@ class LdapTest { * * @throws Exception */ + /** + * security-authentication must only reach the JNDI environment when it was configured, so that credentials + * passed through additional-options are not silently overridden by a default. + */ + @Test + public void securityAuthenticationOnlySetWhenConfigured() { + String key = "java.naming.security.authentication"; + + // httpserver sets it explicitly + RestAssured.get("/ldap/dirContextEnv/httpserver/" + key) + .then() + .statusCode(200) + .body(is("none")); + + // sslserver does not, so the service provider decides rather than the extension + RestAssured.get("/ldap/dirContextEnv/sslserver/" + key) + .then() + .statusCode(200) + .body(is("<absent>")); + } + @ParameterizedTest @ValueSource(strings = { "http", "ssl", "originalConfig", "additionalOptions" }) public void ldapSearchTest(String direct) throws Exception {
