From 1a15359336f8eef8d7a07db26a6822595be44963 Mon Sep 17 00:00:00 2001 From: Croway Date: Tue, 7 Apr 2026 16:54:16 +0200 Subject: [PATCH] chore: default authentication path to /* in platform-http-main --- .../BasicAuthenticationConfigurer.java | 15 +-- .../JWTAuthenticationConfigurer.java | 16 +-- .../MainAuthenticationConfigurer.java | 12 ++ .../BasicAuthenticationNonRootPathTest.java | 88 +++++++++++++++ .../BasicAuthenticationSelectivePathTest.java | 104 ++++++++++++++++++ ...sic-auth-nonroot-path-selective.properties | 22 ++++ .../basic-auth-nonroot-path.properties | 21 ++++ .../pages/camel-4x-upgrade-guide-4_18.adoc | 18 ++- 8 files changed, 268 insertions(+), 28 deletions(-) create mode 100644 components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationNonRootPathTest.java create mode 100644 components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationSelectivePathTest.java create mode 100644 components/camel-platform-http-main/src/test/resources/basic-auth-nonroot-path-selective.properties create mode 100644 components/camel-platform-http-main/src/test/resources/basic-auth-nonroot-path.properties diff --git a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationConfigurer.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationConfigurer.java index bef37925b8639..b36e294e44646 100644 --- a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationConfigurer.java +++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationConfigurer.java @@ -26,7 +26,6 @@ import org.apache.camel.main.HttpServerConfigurationProperties; import static io.vertx.ext.web.handler.BasicAuthHandler.DEFAULT_REALM; -import static org.apache.camel.util.ObjectHelper.isNotEmpty; public class BasicAuthenticationConfigurer implements MainAuthenticationConfigurer { @@ -35,12 +34,7 @@ public void configureAuthentication( AuthenticationConfig authenticationConfig, HttpServerConfigurationProperties properties) { String authPropertiesFileName = properties.getBasicPropertiesFile(); - String path - = isNotEmpty(properties.getAuthenticationPath()) ? properties.getAuthenticationPath() : properties.getPath(); - // root means to authenticate everything - if ("/".equals(path)) { - path = "/*"; - } + String path = resolveAuthenticationPath(properties.getAuthenticationPath(), properties.getPath()); String realm = properties.getAuthenticationRealm() != null ? properties.getAuthenticationRealm() : DEFAULT_REALM; AuthenticationConfigEntry entry = new AuthenticationConfigEntry(); @@ -64,12 +58,7 @@ public void configureAuthentication( AuthenticationConfig authenticationConfig, HttpManagementServerConfigurationProperties properties) { String authPropertiesFileName = properties.getBasicPropertiesFile(); - String path - = isNotEmpty(properties.getAuthenticationPath()) ? properties.getAuthenticationPath() : properties.getPath(); - // root means to authenticate everything - if ("/".equals(path)) { - path = "/*"; - } + String path = resolveAuthenticationPath(properties.getAuthenticationPath(), properties.getPath()); String realm = properties.getAuthenticationRealm() != null ? properties.getAuthenticationRealm() : DEFAULT_REALM; AuthenticationConfigEntry entry = new AuthenticationConfigEntry(); diff --git a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/JWTAuthenticationConfigurer.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/JWTAuthenticationConfigurer.java index 616161074347a..03380ba21611d 100644 --- a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/JWTAuthenticationConfigurer.java +++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/JWTAuthenticationConfigurer.java @@ -28,8 +28,6 @@ import org.apache.camel.main.HttpManagementServerConfigurationProperties; import org.apache.camel.main.HttpServerConfigurationProperties; -import static org.apache.camel.util.ObjectHelper.isNotEmpty; - public class JWTAuthenticationConfigurer implements MainAuthenticationConfigurer { @Override @@ -37,12 +35,7 @@ public void configureAuthentication( AuthenticationConfig authenticationConfig, HttpServerConfigurationProperties properties) { - String path - = isNotEmpty(properties.getAuthenticationPath()) ? properties.getAuthenticationPath() : properties.getPath(); - // root means to authenticate everything - if ("/".equals(path)) { - path = "/*"; - } + String path = resolveAuthenticationPath(properties.getAuthenticationPath(), properties.getPath()); String realm = properties.getAuthenticationRealm() != null ? properties.getAuthenticationRealm() : null; AuthenticationConfigEntry entry = new AuthenticationConfigEntry(); @@ -72,12 +65,7 @@ public void configureAuthentication( AuthenticationConfig authenticationConfig, HttpManagementServerConfigurationProperties properties) { - String path - = isNotEmpty(properties.getAuthenticationPath()) ? properties.getAuthenticationPath() : properties.getPath(); - // root means to authenticate everything - if ("/".equals(path)) { - path = "/*"; - } + String path = resolveAuthenticationPath(properties.getAuthenticationPath(), properties.getPath()); String realm = properties.getAuthenticationRealm() != null ? properties.getAuthenticationRealm() : null; AuthenticationConfigEntry entry = new AuthenticationConfigEntry(); diff --git a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/MainAuthenticationConfigurer.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/MainAuthenticationConfigurer.java index 72011adc37913..2d7c26428cc20 100644 --- a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/MainAuthenticationConfigurer.java +++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/MainAuthenticationConfigurer.java @@ -19,6 +19,7 @@ import org.apache.camel.component.platform.http.vertx.auth.AuthenticationConfig; import org.apache.camel.main.HttpManagementServerConfigurationProperties; import org.apache.camel.main.HttpServerConfigurationProperties; +import org.apache.camel.util.ObjectHelper; /** * Configure authentication on the embedded HTTP server. @@ -30,4 +31,15 @@ public interface MainAuthenticationConfigurer { void configureAuthentication( AuthenticationConfig authenticationConfig, HttpManagementServerConfigurationProperties properties); + /** + * Resolves the effective authentication path. When no explicit authentication path is configured, defaults to + * {@code /*} so that all subpaths under the context path are protected. + */ + default String resolveAuthenticationPath(String authenticationPath, String contextPath) { + if (ObjectHelper.isNotEmpty(authenticationPath)) { + return authenticationPath; + } + return "/*"; + } + } diff --git a/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationNonRootPathTest.java b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationNonRootPathTest.java new file mode 100644 index 0000000000000..b997da33ec9ae --- /dev/null +++ b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationNonRootPathTest.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.platform.http.main.authentication; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.main.Main; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * Tests that authentication is enforced on all subpaths when a non-root context path is configured and + * authenticationPath is not explicitly set. + */ +public class BasicAuthenticationNonRootPathTest { + + private static Main main; + + @BeforeAll + static void init() { + main = new Main(); + main.setPropertyPlaceholderLocations("basic-auth-nonroot-path.properties"); + main.configure().addRoutesBuilder(new PlatformHttpRouteBuilder()); + main.start(); + } + + @AfterAll + static void tearDown() { + main.stop(); + } + + @Test + public void testUnauthenticatedRequestToSubpathShouldReturn401() { + CamelContext camelContext = main.getCamelContext(); + assertNotNull(camelContext); + + // Unauthenticated request to a subpath must be rejected + given() + .when() + .get("/api/hello") + .then() + .statusCode(401) + .body(equalTo("Unauthorized")); + } + + @Test + public void testAuthenticatedRequestToSubpathShouldReturn200() { + CamelContext camelContext = main.getCamelContext(); + assertNotNull(camelContext); + + // With valid credentials, the request should succeed + given() + .auth().basic("camel", "propertiesPass") + .when() + .get("/api/hello") + .then() + .statusCode(200) + .body(equalTo("hello-response")); + } + + private static class PlatformHttpRouteBuilder extends RouteBuilder { + + @Override + public void configure() throws Exception { + from("platform-http:/hello?httpMethodRestrict=GET") + .setBody(constant("hello-response")); + } + } +} diff --git a/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationSelectivePathTest.java b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationSelectivePathTest.java new file mode 100644 index 0000000000000..5ab9d92d60f0e --- /dev/null +++ b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/authentication/BasicAuthenticationSelectivePathTest.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.platform.http.main.authentication; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.main.Main; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * Tests that when an explicit authenticationPath is configured (e.g. /secure/*), only matching subpaths require + * authentication while other subpaths remain accessible without credentials. + */ +public class BasicAuthenticationSelectivePathTest { + + private static Main main; + + @BeforeAll + static void init() { + main = new Main(); + main.setPropertyPlaceholderLocations("basic-auth-nonroot-path-selective.properties"); + main.configure().addRoutesBuilder(new PlatformHttpRouteBuilder()); + main.start(); + } + + @AfterAll + static void tearDown() { + main.stop(); + } + + @Test + public void testUnauthenticatedRequestToSecurePathShouldReturn401() { + CamelContext camelContext = main.getCamelContext(); + assertNotNull(camelContext); + + // /secure/data is covered by authenticationPath=/secure/*, must require credentials + given() + .when() + .get("/api/secure/data") + .then() + .statusCode(401) + .body(equalTo("Unauthorized")); + } + + @Test + public void testAuthenticatedRequestToSecurePathShouldReturn200() { + CamelContext camelContext = main.getCamelContext(); + assertNotNull(camelContext); + + given() + .auth().basic("camel", "propertiesPass") + .when() + .get("/api/secure/data") + .then() + .statusCode(200) + .body(equalTo("secure-data-response")); + } + + @Test + public void testUnauthenticatedRequestToPublicPathShouldReturn200() { + CamelContext camelContext = main.getCamelContext(); + assertNotNull(camelContext); + + // /public is NOT covered by authenticationPath=/secure/*, so it should be accessible + given() + .when() + .get("/api/public") + .then() + .statusCode(200) + .body(equalTo("public-response")); + } + + private static class PlatformHttpRouteBuilder extends RouteBuilder { + + @Override + public void configure() throws Exception { + from("platform-http:/secure/data?httpMethodRestrict=GET") + .setBody(constant("secure-data-response")); + + from("platform-http:/public?httpMethodRestrict=GET") + .setBody(constant("public-response")); + } + } +} diff --git a/components/camel-platform-http-main/src/test/resources/basic-auth-nonroot-path-selective.properties b/components/camel-platform-http-main/src/test/resources/basic-auth-nonroot-path-selective.properties new file mode 100644 index 0000000000000..6b8015a074de2 --- /dev/null +++ b/components/camel-platform-http-main/src/test/resources/basic-auth-nonroot-path-selective.properties @@ -0,0 +1,22 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- +camel.server.enabled=true +camel.server.path=/api + +camel.server.authenticationEnabled=true +camel.server.authenticationPath=/secure/* +camel.server.basicPropertiesFile=camel-platform-http-vertx-auth.properties diff --git a/components/camel-platform-http-main/src/test/resources/basic-auth-nonroot-path.properties b/components/camel-platform-http-main/src/test/resources/basic-auth-nonroot-path.properties new file mode 100644 index 0000000000000..0d0eea81fbac8 --- /dev/null +++ b/components/camel-platform-http-main/src/test/resources/basic-auth-nonroot-path.properties @@ -0,0 +1,21 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- +camel.server.enabled=true +camel.server.path=/api + +camel.server.authenticationEnabled=true +camel.server.basicPropertiesFile=camel-platform-http-vertx-auth.properties diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc index 5988e0b7e1563..914762203e8a2 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc @@ -11,6 +11,23 @@ Note that manual migration is still required. See the xref:camel-upgrade-recipes-tool.adoc[documentation] page for details. ==== +== Upgrading from 4.18.1 to 4.18.2 + +=== camel-platform-http-main + +When `authenticationEnabled` is set to `true` and no explicit `authenticationPath` is configured, +the default authentication path is now `/*`. This means all subpaths under the configured context path +are protected by authentication. + +Previously, the authentication path defaulted to the value of `path` (e.g. `/api`), which only covered +that exact path. If you relied on this behavior and need selective path protection, set +`authenticationPath` explicitly: + +[source,properties] +---- +camel.server.authenticationPath=/secure/* +---- + == Upgrading Camel 4.17 to 4.18 === camel-simple @@ -91,7 +108,6 @@ to the API specification. All together this would make Camel behave similar for Rest DSL for both _code first_ and _contract first_ style. - === camel-ftp (SFTP) and camel-jsch (SCP) ==== JSch upgrade