This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch task-41 in repository https://gitbox.apache.org/repos/asf/camel.git
commit ce547ffcea962ecbea247e530805ee49a32d1b79 Author: Andrea Cosentino <[email protected]> AuthorDate: Mon Mar 9 13:06:21 2026 +0100 CAMEL-23154: Expose PQC named groups in SSLConfigurationProperties Allow users to configure TLS named groups (key exchange algorithms) through camel.ssl.* properties, enabling post-quantum hybrid key exchange (e.g. X25519MLKEM768) via application.properties or fluent API. Changes: - Add namedGroups, namedGroupsInclude, namedGroupsExclude properties to SSLConfigurationProperties with getters, setters, and fluent API - Wire property-to-SSLContextParameters mapping in BaseMainSupport, converting comma-separated strings to NamedGroupsParameters and FilterParameters (follows existing cipherSuites pattern) - Update SSLConfigurationPropertiesConfigurer (generated) with the three new properties - Add 4 new tests in MainSSLTest covering property-based and fluent configuration of both explicit named groups and include/exclude filters - Update main.adoc documentation (20 -> 23 SSL options) - Update camel-main-configuration-metadata.json catalog entries Signed-off-by: Andrea Cosentino <[email protected]> --- .../main/camel-main-configuration-metadata.json | 3 + .../apache/camel/catalog/schemas/camel-spring.xsd | 11 ++ .../org/apache/camel/core/xml/util/jsse/jaxb.index | 1 + .../main/SSLConfigurationPropertiesConfigurer.java | 21 ++++ .../camel-main-configuration-metadata.json | 3 + core/camel-main/src/main/docs/main.adoc | 5 +- .../org/apache/camel/main/BaseMainSupport.java | 22 ++++ .../camel/main/SSLConfigurationProperties.java | 89 ++++++++++++++ .../java/org/apache/camel/main/MainSSLTest.java | 134 +++++++++++++++++++++ 9 files changed, 288 insertions(+), 1 deletion(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json index 4907b8539795..5e5d6ba74821 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json @@ -343,6 +343,9 @@ { "name": "camel.ssl.keystorePassword", "required": false, "description": "Sets the SSL Keystore password.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.keyStoreProvider", "required": false, "description": "To use a specific provider for creating KeyStore. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.keyStoreType", "required": false, "description": "The type of the key store to load. See https:\/\/docs.oracle.com\/en\/java\/javase\/17\/docs\/specs\/security\/standard-names.html", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, + { "name": "camel.ssl.namedGroups", "required": false, "description": "List of TLS\/SSL named groups (key exchange groups). Multiple names can be separated by comma. Named groups control which key exchange algorithms are available during the TLS handshake, including post-quantum hybrid groups such as X25519MLKEM768.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, + { "name": "camel.ssl.namedGroupsExclude", "required": false, "description": "Filters TLS\/SSL named groups. This filter is used for excluding named groups that match the naming pattern. Multiple names can be separated by comma. Notice that if the namedGroups option has been configured then the include\/exclude filters are not in use.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, + { "name": "camel.ssl.namedGroupsInclude", "required": false, "description": "Filters TLS\/SSL named groups. This filter is used for including named groups that match the naming pattern. Multiple names can be separated by comma. Notice that if the namedGroups option has been configured then the include\/exclude filters are not in use.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.provider", "required": false, "description": "To use a specific provider for creating SSLContext. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.secureRandomAlgorithm", "required": false, "description": "Algorithm name used for creating the SecureRandom. See https:\/\/docs.oracle.com\/en\/java\/javase\/17\/docs\/specs\/security\/standard-names.html", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.secureRandomProvider", "required": false, "description": "To use a specific provider for creating SecureRandom. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd index 9dda3d0ef604..235f087ea21e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd @@ -3477,6 +3477,11 @@ configuration. <xs:element maxOccurs="unbounded" minOccurs="0" name="exclude" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> + <xs:complexType name="namedGroupsParameters"> + <xs:sequence> + <xs:element maxOccurs="unbounded" minOccurs="0" name="namedGroup" nillable="true" type="xs:string"/> + </xs:sequence> + </xs:complexType> <xs:complexType name="sniHostNames"> <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="sniHostName" type="xs:string"/> @@ -18046,6 +18051,8 @@ converter. The default logging level is DEBUG. Default value: DEBUG <xs:element minOccurs="0" name="cipherSuitesFilter" type="tns:filterParameters"/> <xs:element minOccurs="0" name="secureSocketProtocols" type="tns:secureSocketProtocolsParameters"/> <xs:element minOccurs="0" name="secureSocketProtocolsFilter" type="tns:filterParameters"/> + <xs:element minOccurs="0" name="namedGroups" type="tns:namedGroupsParameters"/> + <xs:element minOccurs="0" name="namedGroupsFilter" type="tns:filterParameters"/> <xs:element minOccurs="0" name="sniHostNames" type="tns:sniHostNames"/> </xs:all> <xs:attribute name="sessionTimeout" type="xs:string"/> @@ -18060,6 +18067,8 @@ converter. The default logging level is DEBUG. Default value: DEBUG <xs:element minOccurs="0" name="cipherSuitesFilter" type="tns:filterParameters"/> <xs:element minOccurs="0" name="secureSocketProtocols" type="tns:secureSocketProtocolsParameters"/> <xs:element minOccurs="0" name="secureSocketProtocolsFilter" type="tns:filterParameters"/> + <xs:element minOccurs="0" name="namedGroups" type="tns:namedGroupsParameters"/> + <xs:element minOccurs="0" name="namedGroupsFilter" type="tns:filterParameters"/> <xs:element minOccurs="0" name="keyManagers" type="tns:keyManagersParametersFactoryBean"/> <xs:element minOccurs="0" name="trustManagers" type="tns:trustManagersParametersFactoryBean"/> <xs:element minOccurs="0" name="secureRandom" type="tns:secureRandomParametersFactoryBean"/> @@ -18130,6 +18139,8 @@ An optional certificate alias to use. This is useful when the keystore has multi <xs:element minOccurs="0" name="cipherSuitesFilter" type="tns:filterParameters"/> <xs:element minOccurs="0" name="secureSocketProtocols" type="tns:secureSocketProtocolsParameters"/> <xs:element minOccurs="0" name="secureSocketProtocolsFilter" type="tns:filterParameters"/> + <xs:element minOccurs="0" name="namedGroups" type="tns:namedGroupsParameters"/> + <xs:element minOccurs="0" name="namedGroupsFilter" type="tns:filterParameters"/> </xs:all> <xs:attribute name="sessionTimeout" type="xs:string"/> <xs:attribute name="clientAuthentication" type="xs:string"/> diff --git a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/util/jsse/jaxb.index b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/util/jsse/jaxb.index index 8d84387108de..ecefb19403b1 100644 --- a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/util/jsse/jaxb.index +++ b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/util/jsse/jaxb.index @@ -1,5 +1,6 @@ # Generated by camel build tools - do NOT edit this file! CipherSuitesParametersDefinition FilterParametersDefinition +NamedGroupsParametersDefinition SNIHostNamesDefinition SecureSocketProtocolsParametersDefinition diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/SSLConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/SSLConfigurationPropertiesConfigurer.java index f4d7fa454da8..bd5547568b98 100644 --- a/core/camel-main/src/generated/java/org/apache/camel/main/SSLConfigurationPropertiesConfigurer.java +++ b/core/camel-main/src/generated/java/org/apache/camel/main/SSLConfigurationPropertiesConfigurer.java @@ -34,6 +34,9 @@ public class SSLConfigurationPropertiesConfigurer extends org.apache.camel.suppo map.put("KeyStoreProvider", java.lang.String.class); map.put("KeyStoreType", java.lang.String.class); map.put("KeystorePassword", java.lang.String.class); + map.put("NamedGroups", java.lang.String.class); + map.put("NamedGroupsExclude", java.lang.String.class); + map.put("NamedGroupsInclude", java.lang.String.class); map.put("Provider", java.lang.String.class); map.put("SecureRandomAlgorithm", java.lang.String.class); map.put("SecureRandomProvider", java.lang.String.class); @@ -72,6 +75,12 @@ public class SSLConfigurationPropertiesConfigurer extends org.apache.camel.suppo case "keyStoreType": target.setKeyStoreType(property(camelContext, java.lang.String.class, value)); return true; case "keystorepassword": case "keystorePassword": target.setKeystorePassword(property(camelContext, java.lang.String.class, value)); return true; + case "namedgroups": + case "namedGroups": target.setNamedGroups(property(camelContext, java.lang.String.class, value)); return true; + case "namedgroupsexclude": + case "namedGroupsExclude": target.setNamedGroupsExclude(property(camelContext, java.lang.String.class, value)); return true; + case "namedgroupsinclude": + case "namedGroupsInclude": target.setNamedGroupsInclude(property(camelContext, java.lang.String.class, value)); return true; case "provider": target.setProvider(property(camelContext, java.lang.String.class, value)); return true; case "securerandomalgorithm": case "secureRandomAlgorithm": target.setSecureRandomAlgorithm(property(camelContext, java.lang.String.class, value)); return true; @@ -122,6 +131,12 @@ public class SSLConfigurationPropertiesConfigurer extends org.apache.camel.suppo case "keyStoreType": return java.lang.String.class; case "keystorepassword": case "keystorePassword": return java.lang.String.class; + case "namedgroups": + case "namedGroups": return java.lang.String.class; + case "namedgroupsexclude": + case "namedGroupsExclude": return java.lang.String.class; + case "namedgroupsinclude": + case "namedGroupsInclude": return java.lang.String.class; case "provider": return java.lang.String.class; case "securerandomalgorithm": case "secureRandomAlgorithm": return java.lang.String.class; @@ -168,6 +183,12 @@ public class SSLConfigurationPropertiesConfigurer extends org.apache.camel.suppo case "keyStoreType": return target.getKeyStoreType(); case "keystorepassword": case "keystorePassword": return target.getKeystorePassword(); + case "namedgroups": + case "namedGroups": return target.getNamedGroups(); + case "namedgroupsexclude": + case "namedGroupsExclude": return target.getNamedGroupsExclude(); + case "namedgroupsinclude": + case "namedGroupsInclude": return target.getNamedGroupsInclude(); case "provider": return target.getProvider(); case "securerandomalgorithm": case "secureRandomAlgorithm": return target.getSecureRandomAlgorithm(); diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json index 4907b8539795..5e5d6ba74821 100644 --- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json @@ -343,6 +343,9 @@ { "name": "camel.ssl.keystorePassword", "required": false, "description": "Sets the SSL Keystore password.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.keyStoreProvider", "required": false, "description": "To use a specific provider for creating KeyStore. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.keyStoreType", "required": false, "description": "The type of the key store to load. See https:\/\/docs.oracle.com\/en\/java\/javase\/17\/docs\/specs\/security\/standard-names.html", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, + { "name": "camel.ssl.namedGroups", "required": false, "description": "List of TLS\/SSL named groups (key exchange groups). Multiple names can be separated by comma. Named groups control which key exchange algorithms are available during the TLS handshake, including post-quantum hybrid groups such as X25519MLKEM768.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, + { "name": "camel.ssl.namedGroupsExclude", "required": false, "description": "Filters TLS\/SSL named groups. This filter is used for excluding named groups that match the naming pattern. Multiple names can be separated by comma. Notice that if the namedGroups option has been configured then the include\/exclude filters are not in use.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, + { "name": "camel.ssl.namedGroupsInclude", "required": false, "description": "Filters TLS\/SSL named groups. This filter is used for including named groups that match the naming pattern. Multiple names can be separated by comma. Notice that if the namedGroups option has been configured then the include\/exclude filters are not in use.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.provider", "required": false, "description": "To use a specific provider for creating SSLContext. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.secureRandomAlgorithm", "required": false, "description": "Algorithm name used for creating the SecureRandom. See https:\/\/docs.oracle.com\/en\/java\/javase\/17\/docs\/specs\/security\/standard-names.html", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.ssl.secureRandomProvider", "required": false, "description": "To use a specific provider for creating SecureRandom. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol.", "sourceType": "org.apache.camel.main.SSLConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc index 2d71b3062514..9d52d82ad48b 100644 --- a/core/camel-main/src/main/docs/main.adoc +++ b/core/camel-main/src/main/docs/main.adoc @@ -299,7 +299,7 @@ The camel.trace supports 14 options, which are listed below. === Camel SSL configurations -The camel.ssl supports 20 options, which are listed below. +The camel.ssl supports 23 options, which are listed below. [width="100%",cols="2,5,^1,2",options="header"] |=== @@ -316,6 +316,9 @@ The camel.ssl supports 20 options, which are listed below. | *camel.ssl.keystorePassword* | Sets the SSL Keystore password. | | String | *camel.ssl.keyStoreProvider* | To use a specific provider for creating KeyStore. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol. | | String | *camel.ssl.keyStoreType* | The type of the key store to load. See \https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html | | String +| *camel.ssl.namedGroups* | List of TLS/SSL named groups (key exchange groups). Multiple names can be separated by comma. Named groups control which key exchange algorithms are available during the TLS handshake, including post-quantum hybrid groups such as X25519MLKEM768. | | String +| *camel.ssl.namedGroupsExclude* | Filters TLS/SSL named groups. This filter is used for excluding named groups that match the naming pattern. Multiple names can be separated by comma. Notice that if the namedGroups option has been configured then the include/exclude filters are not in use. | | String +| *camel.ssl.namedGroupsInclude* | Filters TLS/SSL named groups. This filter is used for including named groups that match the naming pattern. Multiple names can be separated by comma. Notice that if the namedGroups option has been configured then the include/exclude filters are not in use. | | String | *camel.ssl.provider* | To use a specific provider for creating SSLContext. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol. | | String | *camel.ssl.secureRandom{zwsp}Algorithm* | Algorithm name used for creating the SecureRandom. See \https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html | | String | *camel.ssl.secureRandomProvider* | To use a specific provider for creating SecureRandom. The list of available providers returned by java.security.Security.getProviders() or null to use the highest priority provider implementing the secure socket protocol. | | String diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java index 451174cda706..05b3ec116032 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java @@ -97,6 +97,7 @@ import org.apache.camel.support.jsse.CipherSuitesParameters; import org.apache.camel.support.jsse.FilterParameters; 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.SSLContextServerParameters; import org.apache.camel.support.jsse.SecureRandomParameters; @@ -2198,6 +2199,27 @@ public abstract class BaseMainSupport extends BaseService { } sslContextParameters.setCipherSuitesFilter(fp); } + if (sslConfig.getNamedGroups() != null) { + NamedGroupsParameters ngp = new NamedGroupsParameters(); + for (String g : sslConfig.getNamedGroups().split(",")) { + ngp.addNamedGroup(g); + } + sslContextParameters.setNamedGroups(ngp); + } + if (sslConfig.getNamedGroupsInclude() != null || sslConfig.getNamedGroupsExclude() != null) { + FilterParameters fp = new FilterParameters(); + if (sslConfig.getNamedGroupsInclude() != null) { + for (String g : sslConfig.getNamedGroupsInclude().split(",")) { + fp.addInclude(g); + } + } + if (sslConfig.getNamedGroupsExclude() != null) { + for (String g : sslConfig.getNamedGroupsExclude().split(",")) { + fp.addExclude(g); + } + } + sslContextParameters.setNamedGroupsFilter(fp); + } sslContextParameters.setKeyManagers(kmp); sslContextParameters.setTrustManagers(tmp); sslContextParameters.setServerParameters(scsp); diff --git a/core/camel-main/src/main/java/org/apache/camel/main/SSLConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/SSLConfigurationProperties.java index eba5faf8abdc..4d6395d14120 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/SSLConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/SSLConfigurationProperties.java @@ -44,6 +44,12 @@ public class SSLConfigurationProperties implements BootstrapCloseable { private String cipherSuitesInclude; @Metadata(label = "advanced") private String cipherSuitesExclude; + @Metadata(label = "advanced") + private String namedGroups; + @Metadata(label = "advanced") + private String namedGroupsInclude; + @Metadata(label = "advanced") + private String namedGroupsExclude; @Metadata private String keyStore; @Metadata(label = "advanced") @@ -185,6 +191,52 @@ public class SSLConfigurationProperties implements BootstrapCloseable { this.cipherSuitesExclude = cipherSuitesExclude; } + public String getNamedGroups() { + return namedGroups; + } + + /** + * List of TLS/SSL named groups (key exchange groups). Multiple names can be separated by comma. + * <p> + * Named groups control which key exchange algorithms are available during the TLS handshake, including post-quantum + * hybrid groups such as X25519MLKEM768. + */ + public void setNamedGroups(String namedGroups) { + this.namedGroups = namedGroups; + } + + public String getNamedGroupsInclude() { + return namedGroupsInclude; + } + + /** + * Filters TLS/SSL named groups. + * <p> + * This filter is used for including named groups that match the naming pattern. Multiple names can be separated by + * comma. + * <p> + * Notice that if the namedGroups option has been configured then the include/exclude filters are not in use. + */ + public void setNamedGroupsInclude(String namedGroupsInclude) { + this.namedGroupsInclude = namedGroupsInclude; + } + + public String getNamedGroupsExclude() { + return namedGroupsExclude; + } + + /** + * Filters TLS/SSL named groups. + * <p> + * This filter is used for excluding named groups that match the naming pattern. Multiple names can be separated by + * comma. + * <p> + * Notice that if the namedGroups option has been configured then the include/exclude filters are not in use. + */ + public void setNamedGroupsExclude(String namedGroupsExclude) { + this.namedGroupsExclude = namedGroupsExclude; + } + public String getKeyStore() { return keyStore; } @@ -425,6 +477,43 @@ public class SSLConfigurationProperties implements BootstrapCloseable { return this; } + /** + * List of TLS/SSL named groups (key exchange groups). Multiple names can be separated by comma. + * <p> + * Named groups control which key exchange algorithms are available during the TLS handshake, including post-quantum + * hybrid groups such as X25519MLKEM768. + */ + public SSLConfigurationProperties withNamedGroups(String namedGroups) { + this.namedGroups = namedGroups; + return this; + } + + /** + * Filters TLS/SSL named groups. + * <p> + * This filter is used for including named groups that match the naming pattern. Multiple names can be separated by + * comma. + * <p> + * Notice that if the namedGroups option has been configured then the include/exclude filters are not in use. + */ + public SSLConfigurationProperties withNamedGroupsInclude(String namedGroupsInclude) { + this.namedGroupsInclude = namedGroupsInclude; + return this; + } + + /** + * Filters TLS/SSL named groups. + * <p> + * This filter is used for excluding named groups that match the naming pattern. Multiple names can be separated by + * comma. + * <p> + * Notice that if the namedGroups option has been configured then the include/exclude filters are not in use. + */ + public SSLConfigurationProperties withNamedGroupsExclude(String namedGroupsExclude) { + this.namedGroupsExclude = namedGroupsExclude; + return this; + } + /** * The keystore to load. * diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainSSLTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainSSLTest.java index 9a7e34965b84..50353a31899a 100644 --- a/core/camel-main/src/test/java/org/apache/camel/main/MainSSLTest.java +++ b/core/camel-main/src/test/java/org/apache/camel/main/MainSSLTest.java @@ -16,10 +16,14 @@ */ package org.apache.camel.main; +import java.util.List; + import org.apache.camel.CamelContext; import org.apache.camel.support.jsse.ClientAuthentication; +import org.apache.camel.support.jsse.FilterParameters; 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.SSLContextServerParameters; import org.apache.camel.support.jsse.TrustAllTrustManager; @@ -28,6 +32,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; public class MainSSLTest { @@ -156,4 +161,133 @@ public class MainSSLTest { main.stop(); } + + @Test + public void testMainSSLNamedGroups() { + Main main = new Main(); + + main.addInitialProperty("camel.ssl.enabled", "true"); + main.addInitialProperty("camel.ssl.keyStore", "server.jks"); + main.addInitialProperty("camel.ssl.keystorePassword", "security"); + main.addInitialProperty("camel.ssl.namedGroups", "X25519MLKEM768,X25519,secp256r1"); + + main.start(); + + CamelContext context = main.getCamelContext(); + assertNotNull(context); + + SSLContextParameters sslParams = context.getSSLContextParameters(); + assertNotNull(sslParams); + + NamedGroupsParameters ngp = sslParams.getNamedGroups(); + assertNotNull(ngp); + + List<String> groups = ngp.getNamedGroup(); + Assertions.assertEquals(3, groups.size()); + Assertions.assertEquals("X25519MLKEM768", groups.get(0)); + Assertions.assertEquals("X25519", groups.get(1)); + Assertions.assertEquals("secp256r1", groups.get(2)); + + // when explicit named groups are set, filter should be null + assertNull(sslParams.getNamedGroupsFilter()); + + main.stop(); + } + + @Test + public void testMainSSLNamedGroupsFluent() { + Main main = new Main(); + + main.configure().sslConfig() + .withEnabled(true) + .withKeyStore("server.jks") + .withKeystorePassword("security") + .withNamedGroups("X25519MLKEM768,X25519,secp256r1,secp384r1"); + + main.start(); + + CamelContext context = main.getCamelContext(); + assertNotNull(context); + + SSLContextParameters sslParams = context.getSSLContextParameters(); + assertNotNull(sslParams); + + NamedGroupsParameters ngp = sslParams.getNamedGroups(); + assertNotNull(ngp); + + List<String> groups = ngp.getNamedGroup(); + Assertions.assertEquals(4, groups.size()); + Assertions.assertEquals("X25519MLKEM768", groups.get(0)); + Assertions.assertEquals("secp384r1", groups.get(3)); + + main.stop(); + } + + @Test + public void testMainSSLNamedGroupsFilter() { + Main main = new Main(); + + main.addInitialProperty("camel.ssl.enabled", "true"); + main.addInitialProperty("camel.ssl.keyStore", "server.jks"); + main.addInitialProperty("camel.ssl.keystorePassword", "security"); + main.addInitialProperty("camel.ssl.namedGroupsInclude", "X25519.*,secp.*"); + main.addInitialProperty("camel.ssl.namedGroupsExclude", "secp521r1"); + + main.start(); + + CamelContext context = main.getCamelContext(); + assertNotNull(context); + + SSLContextParameters sslParams = context.getSSLContextParameters(); + assertNotNull(sslParams); + + // when filters are used, explicit named groups should be null + assertNull(sslParams.getNamedGroups()); + + FilterParameters fp = sslParams.getNamedGroupsFilter(); + assertNotNull(fp); + + List<String> includes = fp.getInclude(); + Assertions.assertEquals(2, includes.size()); + Assertions.assertEquals("X25519.*", includes.get(0)); + Assertions.assertEquals("secp.*", includes.get(1)); + + List<String> excludes = fp.getExclude(); + Assertions.assertEquals(1, excludes.size()); + Assertions.assertEquals("secp521r1", excludes.get(0)); + + main.stop(); + } + + @Test + public void testMainSSLNamedGroupsFilterFluent() { + Main main = new Main(); + + main.configure().sslConfig() + .withEnabled(true) + .withKeyStore("server.jks") + .withKeystorePassword("security") + .withNamedGroupsInclude("X25519.*") + .withNamedGroupsExclude("secp521r1"); + + main.start(); + + CamelContext context = main.getCamelContext(); + assertNotNull(context); + + SSLContextParameters sslParams = context.getSSLContextParameters(); + assertNotNull(sslParams); + + assertNull(sslParams.getNamedGroups()); + + FilterParameters fp = sslParams.getNamedGroupsFilter(); + assertNotNull(fp); + + Assertions.assertEquals(1, fp.getInclude().size()); + Assertions.assertEquals("X25519.*", fp.getInclude().get(0)); + Assertions.assertEquals(1, fp.getExclude().size()); + Assertions.assertEquals("secp521r1", fp.getExclude().get(0)); + + main.stop(); + } }
