This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new 5626afdfc9 Enforce quarkus.tls transport policy on bridged
SSLContextParameters
5626afdfc9 is described below
commit 5626afdfc9c4eadcce8dc1928ce68d5e4ca21fbe
Author: James Netherton <[email protected]>
AuthorDate: Mon Sep 7 07:08:04 2026 +0100
Enforce quarkus.tls transport policy on bridged SSLContextParameters
The conversion to SSLContextParameters carried over only key and trust
material.
Quarkus keeps protocols, cipher suites and key exchange groups on the Vert.x
SSLOptions and never applies them to the SSLContext, so Camel components
using a
registered bean negotiated with JVM defaults and nothing warned. Decorate
the context
the way SSLContextParameters.createSSLContext does, and copy the policy
onto the
parameters.
Warn about the configured options that cannot be carried over and that
weaken
verification if the operator assumes otherwise: a certificate revocation
list, which
leaves a bridged bean accepting certificates the rest of the application
rejects, and
the hostname verification algorithm.
Fixes #9113
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
.../modules/ROOT/pages/migration-guide/3.40.0.adoc | 47 ++++++++
.../pages/reference/extensions/tls-registry.adoc | 45 ++++++++
.../tls-registry/runtime/src/main/doc/usage.adoc | 43 ++++++++
.../core/tls/TlsConfigurationConverter.java | 100 ++++++++++++++++-
.../quarkus/core/tls/it/TlsRegistryResource.java | 24 +++++
.../core/tls/it/TlsRegistryTransportPolicyIT.java | 23 ++++
.../tls/it/TlsRegistryTransportPolicyTest.java | 118 +++++++++++++++++++++
7 files changed, 397 insertions(+), 3 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
index ac95c7f270..e5cd536d82 100644
--- a/docs/modules/ROOT/pages/migration-guide/3.40.0.adoc
+++ b/docs/modules/ROOT/pages/migration-guide/3.40.0.adoc
@@ -49,3 +49,50 @@ The option is now unset by default and has three states:
Setting the option to `false` therefore now bounds what the native image is
able to deserialize, at the cost of breaking any component that depends on Java
serialization. A build that requests the veto while extensions ask for
serialization logs a warning.
Applications that set the option to `false` while relying on one of the
extensions above must remove the setting to keep working. Applications that set
it to `true`, or that never set it, are unaffected.
+
+== TLS Registry extension changes
+
+=== quarkus.tls transport policy is now enforced
+
+Converting a Quarkus TLS configuration to `SSLContextParameters` previously
carried over only the key and trust material. `quarkus.tls.protocols`,
`quarkus.tls.cipher-suites` and `quarkus.tls.key-exchange-groups` were dropped,
so Camel components using a registered bean negotiated with the JVM defaults
rather than the policy that had been configured for them. Quarkus keeps those
alongside the Vert.x transport options and never applies them to the
`SSLContext` itself, so nothing carried t [...]
+
+All three are now applied to every `SSLEngine` and socket factory Camel
derives from a registered bean.
+
+`quarkus.tls.protocols` defaults to `TLSv1.3`, so a bean that previously
offered whatever the JVM enabled now offers TLSv1.3 alone, matching every other
consumer of the same TLS configuration. Where a route talks to an endpoint that
does not support TLSv1.3, widen the property.
+
+[source,properties]
+----
+quarkus.tls.protocols=TLSv1.3,TLSv1.2
+----
+
+Note that this applies to the whole TLS configuration, not only to Camel.
Define a named configuration for the endpoint that needs it if the rest of the
application should stay on TLSv1.3.
+
+[source,properties]
+----
+quarkus.tls.legacy-endpoint.protocols=TLSv1.3,TLSv1.2
+quarkus.tls.legacy-endpoint.trust-store.p12.path=/etc/ssl/truststore.p12
+quarkus.tls.legacy-endpoint.trust-store.p12.password=changeit
+----
+
+=== Unrecognised protocol and cipher suite names now fail
+
+Camel applies a configured list verbatim rather than reducing it to what the
JVM supports, so a name the JVM does not recognise now fails the creation of
the SSL context instead of being ignored. Disabled but known names, such as
`SSLv3`, are still accepted.
+
+This affects a configuration that sets `quarkus.tls.<name>.ssl-engine` to
`openssl` and names cipher suites in OpenSSL style, which Vert.x accepts. Use
the JSSE names for a configuration that Camel components consume.
+
+[source,properties]
+----
+# Rejected by the JVM
+# quarkus.tls.cipher-suites=ECDHE-RSA-AES128-GCM-SHA256
+quarkus.tls.cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+----
+
+Note also that a configured list takes precedence over Camel's own default
exclusion filters. Because `quarkus.tls.protocols` always carries a value,
those filters do not exclude the SSLv2 and SSLv3 protocols from a bridged
configuration, and they exclude the `NULL`, `anon`, `EXPORT`, `DES`, `MD5` and
`RC4` cipher suites only while `quarkus.tls.cipher-suites` is unset.
+
+=== Options that cannot be bridged are now reported
+
+`certificate-revocation-list`, `hostname-verification-algorithm`,
`key-store.sni`, `alpn` and `pqc-enforcement-policy` have no equivalent in
`SSLContextParameters` and are still not carried over. They remain the
responsibility of the consuming Camel component or endpoint, and continue to
apply to Quarkus's own TLS consumers as before.
+
+A warning is now logged at startup for the two that weaken verification if the
operator assumes otherwise, instead of them being dropped silently. In
particular, a Camel component using a bridged bean does not check certificate
revocation, and so accepts a revoked certificate that the rest of the
application rejects.
+
+Refer to the
xref:reference/extensions/tls-registry.adoc#extensions-tls-registry-usage-protocols-and-cipher-suites[TLS
Registry extension documentation] for details.
diff --git a/docs/modules/ROOT/pages/reference/extensions/tls-registry.adoc
b/docs/modules/ROOT/pages/reference/extensions/tls-registry.adoc
index 185e79ef3e..482c941daa 100644
--- a/docs/modules/ROOT/pages/reference/extensions/tls-registry.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/tls-registry.adoc
@@ -125,6 +125,51 @@ from("timer:tick")
.to("https://api.example.com?useGlobalSslContextParameters=true");
----
+[id="extensions-tls-registry-usage-protocols-and-cipher-suites"]
+=== Protocols And Cipher Suites
+
+The protocols, cipher suites and key exchange groups set on a Quarkus TLS
configuration are carried over to the `SSLContextParameters` bean and enforced
on every `SSLEngine` and socket factory Camel derives from it:
+
+[source,properties]
+----
+quarkus.tls.protocols=TLSv1.3,TLSv1.2
+quarkus.tls.cipher-suites=TLS_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+quarkus.tls.key-exchange-groups=x25519,secp384r1
+----
+
+IMPORTANT: `quarkus.tls.protocols` defaults to `TLSv1.3`. Camel components
consuming a bridged bean therefore negotiate TLSv1.3 only unless you widen the
property, matching the behaviour of every other consumer of the same Quarkus
TLS configuration. Set `quarkus.tls.protocols=TLSv1.3,TLSv1.2` if you need to
talk to endpoints that do not support TLSv1.3.
+
+WARNING: Camel applies a configured list verbatim, in preference to its own
default exclusion filters. Because `quarkus.tls.protocols` always carries a
value, those filters never exclude the SSLv2 and SSLv3 protocols from a bridged
configuration, and they exclude the `NULL`, `anon`, `EXPORT`, `DES`, `MD5` and
`RC4` cipher suites only while `quarkus.tls.cipher-suites` is unset. A weak
protocol or cipher suite that you configure explicitly is used as configured.
+
+A value that the JVM does not recognise is rejected rather than ignored,
failing the creation of the SSL context. This includes OpenSSL style cipher
suite names such as `ECDHE-RSA-AES128-GCM-SHA256`, which Vert.x accepts when
`quarkus.tls.<name>.ssl-engine` is set to `openssl`. Use the JSSE names, for
example `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`, for a configuration that Camel
components consume.
+
+[id="extensions-tls-registry-usage-options-that-cannot-be-bridged"]
+==== Options That Cannot Be Bridged
+
+Some `quarkus.tls.*` options have no equivalent in `SSLContextParameters`,
because they are applied by Vert.x rather than by the JSSE `SSLContext`:
+
+[cols="1,3"]
+|===
+|Option |Notes
+
+|`certificate-revocation-list`
+|Not carried over. Camel components using a bridged bean do not check
certificate revocation and accept a revoked certificate that the rest of the
application rejects. A warning is logged at startup when this option is set.
+
+|`hostname-verification-algorithm`
+|Not carried over. Configure hostname verification on the consuming Camel
component or endpoint instead. A warning is logged at startup when this option
is set.
+
+|`key-store.sni`
+|Not carried over. Server name indication is a Vert.x transport concern.
+
+|`alpn`
+|Not carried over. Protocol negotiation is handled by the consuming component.
+
+|`pqc-enforcement-policy`
+|Not carried over. Use `quarkus.tls.<name>.key-exchange-groups`, which is, to
constrain the groups Camel offers.
+|===
+
+These options continue to apply to Quarkus's own TLS consumers as normal. Only
the Camel bridge is affected.
+
[id="extensions-tls-registry-usage-certificate-reload"]
=== Certificate Reload
diff --git a/extensions/tls-registry/runtime/src/main/doc/usage.adoc
b/extensions/tls-registry/runtime/src/main/doc/usage.adoc
index 9cf61d22c1..aa7dd393ac 100644
--- a/extensions/tls-registry/runtime/src/main/doc/usage.adoc
+++ b/extensions/tls-registry/runtime/src/main/doc/usage.adoc
@@ -80,6 +80,49 @@ from("timer:tick")
.to("https://api.example.com?useGlobalSslContextParameters=true");
----
+=== Protocols And Cipher Suites
+
+The protocols, cipher suites and key exchange groups set on a Quarkus TLS
configuration are carried over to the `SSLContextParameters` bean and enforced
on every `SSLEngine` and socket factory Camel derives from it:
+
+[source,properties]
+----
+quarkus.tls.protocols=TLSv1.3,TLSv1.2
+quarkus.tls.cipher-suites=TLS_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+quarkus.tls.key-exchange-groups=x25519,secp384r1
+----
+
+IMPORTANT: `quarkus.tls.protocols` defaults to `TLSv1.3`. Camel components
consuming a bridged bean therefore negotiate TLSv1.3 only unless you widen the
property, matching the behaviour of every other consumer of the same Quarkus
TLS configuration. Set `quarkus.tls.protocols=TLSv1.3,TLSv1.2` if you need to
talk to endpoints that do not support TLSv1.3.
+
+WARNING: Camel applies a configured list verbatim, in preference to its own
default exclusion filters. Because `quarkus.tls.protocols` always carries a
value, those filters never exclude the SSLv2 and SSLv3 protocols from a bridged
configuration, and they exclude the `NULL`, `anon`, `EXPORT`, `DES`, `MD5` and
`RC4` cipher suites only while `quarkus.tls.cipher-suites` is unset. A weak
protocol or cipher suite that you configure explicitly is used as configured.
+
+A value that the JVM does not recognise is rejected rather than ignored,
failing the creation of the SSL context. This includes OpenSSL style cipher
suite names such as `ECDHE-RSA-AES128-GCM-SHA256`, which Vert.x accepts when
`quarkus.tls.<name>.ssl-engine` is set to `openssl`. Use the JSSE names, for
example `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`, for a configuration that Camel
components consume.
+
+==== Options That Cannot Be Bridged
+
+Some `quarkus.tls.*` options have no equivalent in `SSLContextParameters`,
because they are applied by Vert.x rather than by the JSSE `SSLContext`:
+
+[cols="1,3"]
+|===
+|Option |Notes
+
+|`certificate-revocation-list`
+|Not carried over. Camel components using a bridged bean do not check
certificate revocation and accept a revoked certificate that the rest of the
application rejects. A warning is logged at startup when this option is set.
+
+|`hostname-verification-algorithm`
+|Not carried over. Configure hostname verification on the consuming Camel
component or endpoint instead. A warning is logged at startup when this option
is set.
+
+|`key-store.sni`
+|Not carried over. Server name indication is a Vert.x transport concern.
+
+|`alpn`
+|Not carried over. Protocol negotiation is handled by the consuming component.
+
+|`pqc-enforcement-policy`
+|Not carried over. Use `quarkus.tls.<name>.key-exchange-groups`, which is, to
constrain the groups Camel offers.
+|===
+
+These options continue to apply to Quarkus's own TLS consumers as normal. Only
the Camel bridge is affected.
+
=== Certificate Reload
The extension automatically observes certificate reload events from Quarkus
TLS registry.
diff --git
a/extensions/tls-registry/runtime/src/main/java/org/apache/camel/quarkus/core/tls/TlsConfigurationConverter.java
b/extensions/tls-registry/runtime/src/main/java/org/apache/camel/quarkus/core/tls/TlsConfigurationConverter.java
index 83fa202fb1..e8fb3bf576 100644
---
a/extensions/tls-registry/runtime/src/main/java/org/apache/camel/quarkus/core/tls/TlsConfigurationConverter.java
+++
b/extensions/tls-registry/runtime/src/main/java/org/apache/camel/quarkus/core/tls/TlsConfigurationConverter.java
@@ -19,20 +19,31 @@ package org.apache.camel.quarkus.core.tls;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
import javax.net.ssl.SSLContext;
import io.quarkus.tls.TlsConfiguration;
+import io.vertx.core.net.SSLOptions;
import org.apache.camel.CamelContext;
+import org.apache.camel.support.jsse.CipherSuitesParameters;
import org.apache.camel.support.jsse.KeyManagersParameters;
import org.apache.camel.support.jsse.KeyStoreParameters;
+import org.apache.camel.support.jsse.NamedGroupsParameters;
import org.apache.camel.support.jsse.SSLContextParameters;
+import org.apache.camel.support.jsse.SecureSocketProtocolsParameters;
import org.apache.camel.support.jsse.TrustManagersParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Converts Quarkus TlsConfiguration to Camel SSLContextParameters.
*/
final class TlsConfigurationConverter {
+ private static final Logger LOG =
LoggerFactory.getLogger(TlsConfigurationConverter.class);
+
private TlsConfigurationConverter() {
// Utility class
}
@@ -48,23 +59,54 @@ final class TlsConfigurationConverter {
*
* - Loading keystores and truststores (JKS, PKCS12, PEM)
* - Configuring key and trust managers
- * - Setting cipher suites and protocols
* - Handling certificate reloading
*
+ * The {@code protocols}, {@code cipher-suites} and {@code
key-exchange-groups} configured via
+ * {@code quarkus.tls.*} are copied onto the returned SSLContextParameters
and enforced on every SSLEngine and
+ * socket factory derived from its SSLContext. Quarkus keeps them on the
Vert.x {@link SSLOptions} side and
+ * never applies them to the SSLContext itself, so without this they would
silently not apply to Camel
+ * components.
+ *
+ * Camel applies an explicitly configured list verbatim, in preference to
its own default exclusion filters. Since
+ * {@code quarkus.tls.protocols} always carries a value, those default
filters never constrain the protocols of a
+ * bridged configuration, and they constrain its cipher suites only while
{@code quarkus.tls.cipher-suites} is
+ * unset. A value JSSE does not recognise is rejected rather than dropped.
+ *
+ * A certificate revocation list, {@code hostname-verification-algorithm},
SNI, ALPN and
+ * {@code pqc-enforcement-policy} have no equivalent in
SSLContextParameters. They remain the responsibility of
+ * the consuming Camel component, and a warning is logged for the two that
weaken verification.
+ *
* @param tlsConfig the Quarkus TLS configuration
* @param name the configuration name (for logging)
* @return SSLContextParameters that delegates to Quarkus's TLS
configuration
*/
static SSLContextParameters convert(TlsConfiguration tlsConfig, String
name) {
- return new SSLContextParameters() {
+ SSLContextParameters parameters = new SSLContextParameters() {
@Override
public SSLContext createSSLContext(CamelContext camelContext)
throws GeneralSecurityException, IOException {
+ final SSLContext delegate;
try {
- return tlsConfig.createSSLContext();
+ delegate = tlsConfig.createSSLContext();
} catch (Exception e) {
throw new GeneralSecurityException(
"Failed to create SSLContext from Quarkus TLS
configuration '" + name + "'", e);
}
+
+ if (camelContext != null) {
+ setCamelContext(camelContext);
+ }
+ configureSSLContext(delegate);
+
+ // Quarkus builds the SSLContext from key and trust material
only. Decorate it the same way
+ // SSLContextParameters.createSSLContext does, so that the
transport policy carried by this instance
+ // is applied to every SSLEngine, SSLSocketFactory and
SSLServerSocketFactory derived from it. A
+ // plain JSSE SSLContext cannot carry those pins on its own.
+ return new SSLContextDecorator(
+ new SSLContextSpiDecorator(
+ delegate,
+ getSSLEngineConfigurers(delegate),
+ getSSLSocketFactoryConfigurers(delegate),
+
getSSLServerSocketFactoryConfigurers(delegate)));
}
@Override
@@ -122,5 +164,57 @@ final class TlsConfigurationConverter {
return tmp;
}
};
+
+ applyTransportPolicy(parameters, tlsConfig, name);
+
+ return parameters;
+ }
+
+ /**
+ * Copy the transport policy from the Quarkus TLS configuration onto the
Camel SSLContextParameters, so that it
+ * is enforced on contexts created from it and consumers reading the
parameters directly observe the operator's
+ * policy. Warn about the configured options that cannot be carried over
and that weaken verification if the
+ * operator assumes otherwise.
+ */
+ private static void applyTransportPolicy(SSLContextParameters parameters,
TlsConfiguration tlsConfig, String name) {
+ SSLOptions sslOptions = tlsConfig.getSSLOptions();
+ if (sslOptions != null) {
+ Set<String> protocols =
sslOptions.getEnabledSecureTransportProtocols();
+ if (protocols != null && !protocols.isEmpty()) {
+ SecureSocketProtocolsParameters protocolsParameters = new
SecureSocketProtocolsParameters();
+ protocolsParameters.setSecureSocketProtocol(new
ArrayList<>(protocols));
+ parameters.setSecureSocketProtocols(protocolsParameters);
+ LOG.debug("Quarkus TLS configuration '{}' restricts Camel to
secure socket protocols {}", name, protocols);
+ }
+
+ Set<String> cipherSuites = sslOptions.getEnabledCipherSuites();
+ if (cipherSuites != null && !cipherSuites.isEmpty()) {
+ CipherSuitesParameters cipherSuitesParameters = new
CipherSuitesParameters();
+ cipherSuitesParameters.setCipherSuite(new
ArrayList<>(cipherSuites));
+ parameters.setCipherSuites(cipherSuitesParameters);
+ LOG.debug("Quarkus TLS configuration '{}' restricts Camel to
cipher suites {}", name, cipherSuites);
+ }
+
+ List<String> keyExchangeGroups = sslOptions.getKeyExchangeGroups();
+ if (keyExchangeGroups != null && !keyExchangeGroups.isEmpty()) {
+ NamedGroupsParameters namedGroups = new
NamedGroupsParameters();
+ namedGroups.setNamedGroup(new ArrayList<>(keyExchangeGroups));
+ parameters.setNamedGroups(namedGroups);
+ LOG.debug("Quarkus TLS configuration '{}' restricts Camel to
key exchange groups {}", name,
+ keyExchangeGroups);
+ }
+
+ if (!sslOptions.getCrlValues().isEmpty() ||
!sslOptions.getCrlPaths().isEmpty()) {
+ LOG.warn("Quarkus TLS configuration '{}' configures a
certificate revocation list, which cannot be "
+ + "carried over to Camel SSLContextParameters. Camel
components using this configuration do "
+ + "not check certificate revocation.", name);
+ }
+ }
+
+ tlsConfig.getHostnameVerificationAlgorithm().ifPresent(algorithm ->
LOG.warn(
+ "Quarkus TLS configuration '{}' sets
hostname-verification-algorithm={}, which cannot be carried over "
+ + "to Camel SSLContextParameters. Hostname
verification must be configured on the consuming "
+ + "Camel component or endpoint.",
+ name, algorithm));
}
}
diff --git
a/integration-tests/tls-registry/src/main/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryResource.java
b/integration-tests/tls-registry/src/main/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryResource.java
index 3fb04018ec..5a43662095 100644
---
a/integration-tests/tls-registry/src/main/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryResource.java
+++
b/integration-tests/tls-registry/src/main/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryResource.java
@@ -16,9 +16,12 @@
*/
package org.apache.camel.quarkus.core.tls.it;
+import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import javax.net.ssl.SSLEngine;
+
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
@@ -68,6 +71,27 @@ public class TlsRegistryResource {
return context.getSSLContextParameters() != null;
}
+ /**
+ * Exposes the protocol and cipher suite policy actually enforced on an
SSLEngine derived from a registered
+ * SSLContextParameters bean. Without the SSLContext decoration applied by
TlsConfigurationConverter these
+ * would be the JVM defaults rather than the quarkus.tls.* policy.
+ */
+ @Path("/ssl-policy/{beanName}")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Map<String, List<String>> sslPolicy(@PathParam("beanName") String
beanName) throws Exception {
+ SSLContextParameters parameters =
context.getRegistry().lookupByNameAndType(beanName, SSLContextParameters.class);
+ SSLEngine engine =
parameters.createSSLContext(context).createSSLEngine();
+ // Named groups are read from the parameters rather than the engine:
SSLParameters.getNamedGroups is Java 20+
+ // and this project compiles against 17. Camel applies them through
the same engine configurers as the
+ // protocols and cipher suites asserted above.
+ return Map.of(
+ "protocols", List.of(engine.getEnabledProtocols()),
+ "cipherSuites", List.of(engine.getEnabledCipherSuites()),
+ "namedGroups", parameters.getNamedGroups() == null
+ ? List.of() :
parameters.getNamedGroups().getNamedGroup());
+ }
+
@Path("/ping")
@GET
@Produces(MediaType.TEXT_PLAIN)
diff --git
a/integration-tests/tls-registry/src/test/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryTransportPolicyIT.java
b/integration-tests/tls-registry/src/test/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryTransportPolicyIT.java
new file mode 100644
index 0000000000..23786b2aac
--- /dev/null
+++
b/integration-tests/tls-registry/src/test/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryTransportPolicyIT.java
@@ -0,0 +1,23 @@
+/*
+ * 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.quarkus.core.tls.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+class TlsRegistryTransportPolicyIT extends TlsRegistryTransportPolicyTest {
+}
diff --git
a/integration-tests/tls-registry/src/test/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryTransportPolicyTest.java
b/integration-tests/tls-registry/src/test/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryTransportPolicyTest.java
new file mode 100644
index 0000000000..250fa9e465
--- /dev/null
+++
b/integration-tests/tls-registry/src/test/java/org/apache/camel/quarkus/core/tls/it/TlsRegistryTransportPolicyTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.quarkus.core.tls.it;
+
+import java.util.List;
+import java.util.Map;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.QuarkusTestProfile;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.RestAssured;
+import io.restassured.common.mapper.TypeRef;
+import io.smallrye.certs.Format;
+import io.smallrye.certs.junit5.Certificate;
+import org.apache.camel.quarkus.test.support.certificate.TestCertificates;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verifies that the protocol and cipher suite policy configured via {@code
quarkus.tls.*} is enforced on
+ * SSLContextParameters beans produced by the TLS registry bridge. Quarkus
keeps that policy on the Vert.x SSLOptions
+ * and never applies it to the SSLContext it builds, so the bridge has to
carry it across itself.
+ */
+@TestCertificates(certificates = {
+ @Certificate(name = "tls-test", formats = { Format.PKCS12, Format.PEM
}, password = "changeit")
+})
+@QuarkusTest
+@TestProfile(TlsRegistryTransportPolicyTest.TransportPolicyProfile.class)
+class TlsRegistryTransportPolicyTest {
+
+ private static final String TLS_12_CIPHER_SUITE =
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
+ private static final String KEY_EXCHANGE_GROUP = "secp384r1";
+
+ @Test
+ void configuredProtocolsAndCipherSuitesAreEnforced() {
+ Map<String, List<String>> policy = sslPolicy("restricted");
+
+ assertEquals(List.of("TLSv1.2"), policy.get("protocols"),
+ "Only the protocol configured via
quarkus.tls.restricted.protocols should be enabled");
+ assertEquals(List.of(TLS_12_CIPHER_SUITE), policy.get("cipherSuites"),
+ "Only the cipher suite configured via
quarkus.tls.restricted.cipher-suites should be enabled");
+ }
+
+ @Test
+ void quarkusProtocolDefaultIsApplied() {
+ Map<String, List<String>> policy =
sslPolicy("defaultSslContextParameters");
+
+ // quarkus.tls.protocols defaults to TLSv1.3, so Camel consumers of
the bridged bean negotiate exactly what
+ // the rest of the Quarkus application negotiates rather than the
wider JVM default set
+ assertEquals(List.of("TLSv1.3"), policy.get("protocols"));
+ }
+
+ @Test
+ void configuredKeyExchangeGroupsAreCarriedOver() {
+ assertEquals(List.of(KEY_EXCHANGE_GROUP),
sslPolicy("restricted").get("namedGroups"),
+ "quarkus.tls.restricted.key-exchange-groups should be carried
over as Camel named groups");
+ }
+
+ /**
+ * Camel's default cipher suite exclusions only apply while no explicit
list is configured, since an explicit list
+ * takes precedence over the filters. This covers that unset case; a
configured list is applied verbatim.
+ */
+ @Test
+ void camelDefaultCipherSuiteFiltersApplyWhenNoListIsConfigured() {
+ List<String> cipherSuites =
sslPolicy("defaultSslContextParameters").get("cipherSuites");
+
+ assertFalse(cipherSuites.isEmpty());
+ assertTrue(cipherSuites.stream().noneMatch(suite ->
suite.contains("_NULL_")
+ || suite.contains("_anon_")
+ || suite.contains("_EXPORT_")
+ || suite.contains("_DES_")
+ || suite.endsWith("MD5")
+ || suite.contains("RC4")),
+ "Camel's default cipher suite exclusions should apply to
bridged beans: " + cipherSuites);
+ }
+
+ private static Map<String, List<String>> sslPolicy(String beanName) {
+ return RestAssured.given()
+ .get("/tls-registry/ssl-policy/" + beanName)
+ .then()
+ .statusCode(200)
+ .extract().as(new TypeRef<Map<String, List<String>>>() {
+ });
+ }
+
+ public static class TransportPolicyProfile implements QuarkusTestProfile {
+ @Override
+ public Map<String, String> getConfigOverrides() {
+ return Map.ofEntries(
+ Map.entry("quarkus.camel.tls-registry.enabled", "true"),
+
Map.entry("quarkus.camel.tls-registry.quarkus-default-as-global", "false"),
+ Map.entry("quarkus.tls.key-store.p12.path",
"target/certs/tls-test-keystore.p12"),
+ Map.entry("quarkus.tls.key-store.p12.password",
"changeit"),
+ Map.entry("quarkus.tls.restricted.key-store.p12.path",
"target/certs/tls-test-keystore.p12"),
+ Map.entry("quarkus.tls.restricted.key-store.p12.password",
"changeit"),
+ Map.entry("quarkus.tls.restricted.protocols", "TLSv1.2"),
+ Map.entry("quarkus.tls.restricted.cipher-suites",
TLS_12_CIPHER_SUITE),
+ Map.entry("quarkus.tls.restricted.key-exchange-groups",
KEY_EXCHANGE_GROUP));
+ }
+ }
+}