This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 7718b036428a CAMEL-23158: Expose PQC named groups in 
SSLConfigurationProperties (#21868)
7718b036428a is described below

commit 7718b036428aba5df54c444bb20e50678d207fb9
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Mar 9 14:25:47 2026 +0100

    CAMEL-23158: Expose PQC named groups in SSLConfigurationProperties (#21868)
    
    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 +
 .../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 +++++++++++++++++++++
 7 files changed, 276 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/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();
+    }
 }

Reply via email to