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

yqm pushed a commit to branch 35.0.0
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/35.0.0 by this push:
     new 8b341dd4e46 Optionally apply TLSServerConfig to bound 
SSLContextFactory.Server (#18610)
8b341dd4e46 is described below

commit 8b341dd4e46987fa1e89002d09c0830e03a450cc
Author: jtuglu1 <[email protected]>
AuthorDate: Thu Oct 9 11:06:46 2025 -0700

    Optionally apply TLSServerConfig to bound SSLContextFactory.Server (#18610)
    
    Custom-bound SSL providers may want to still use the `TLSServerConfig` 
values provided in the config. Currently the behavior skips applying these 
configs if there is an existing binding of SslContextFactory.Server.
    
    This adds a flag `druid.server.https.forceApplyConfig` to indicate that the 
`TLSServerConfig` values should be applied irrespective of whether a 
preexisting `SslContextFactory.Server` binding exists.
---
 docs/operations/tls-support.md                     |   1 +
 .../server/initialization/TLSServerConfig.java     | 197 +++++++++++++++++++++
 .../initialization/jetty/JettyServerModule.java    |  11 +-
 .../server/initialization/JettyCertRenewTest.java  |  95 ++--------
 .../druid/server/initialization/JettyTest.java     |  81 ++-------
 .../jetty/JettyServerModuleTest.java               | 185 +++++++++++++++++++
 6 files changed, 417 insertions(+), 153 deletions(-)

diff --git a/docs/operations/tls-support.md b/docs/operations/tls-support.md
index 994f5f27441..23dc1332448 100644
--- a/docs/operations/tls-support.md
+++ b/docs/operations/tls-support.md
@@ -51,6 +51,7 @@ values for the configs below, among others provided by Java 
implementation.
 |`druid.server.https.keyStorePassword`|The [Password 
Provider](../operations/password-provider.md) or String password for the Key 
Store.|none|yes|
 |`druid.server.https.reloadSslContext`| Should Druid server detect Key Store 
file change and reload.|false|no|
 |`druid.server.https.reloadSslContextSeconds`| How frequently should Druid 
server scan for Key Store file change.|60|yes|
+|`druid.server.https.forceApplyConfig`|Whether to apply TLS server configs 
even if an existing `SslContextFactory.Server` instance is bound.|false|no|
 
 The following table contains configuration options related to client 
certificate authentication.
 
diff --git 
a/server/src/main/java/org/apache/druid/server/initialization/TLSServerConfig.java
 
b/server/src/main/java/org/apache/druid/server/initialization/TLSServerConfig.java
index 497d714a38b..a6f0da019b2 100644
--- 
a/server/src/main/java/org/apache/druid/server/initialization/TLSServerConfig.java
+++ 
b/server/src/main/java/org/apache/druid/server/initialization/TLSServerConfig.java
@@ -21,6 +21,7 @@ package org.apache.druid.server.initialization;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import org.apache.druid.metadata.PasswordProvider;
+import org.apache.druid.server.initialization.jetty.JettyServerModule;
 
 import java.util.List;
 
@@ -86,6 +87,9 @@ public class TLSServerConfig
   @JsonProperty
   private int reloadSslContextSeconds = 60;
 
+  @JsonProperty
+  private boolean forceApplyConfig = false;
+
   public String getKeyStorePath()
   {
     return keyStorePath;
@@ -186,6 +190,15 @@ public class TLSServerConfig
     return reloadSslContext;
   }
 
+  /**
+   * Whether to apply TLS server configs even if an existing {@code 
SslContextFactory.Server} instance is bound.
+   * See {@link JettyServerModule#makeAndInitializeServer}.
+   */
+  public boolean isForceApplyConfig()
+  {
+    return forceApplyConfig;
+  }
+
   @Override
   public String toString()
   {
@@ -207,6 +220,190 @@ public class TLSServerConfig
            ", crlPath='" + crlPath + '\'' +
            ", reloadSslContext='" + reloadSslContext + '\'' +
            ", reloadSslContextSeconds='" + reloadSslContextSeconds + '\'' +
+           ", forceApplyConfig=" + forceApplyConfig +
            '}';
   }
+
+  public static Builder builder()
+  {
+    return new Builder();
+  }
+
+  public static class Builder
+  {
+    private String keyStorePath;
+    private String keyStoreType;
+    private String certAlias;
+    private PasswordProvider keyStorePasswordProvider;
+    private PasswordProvider keyManagerPasswordProvider;
+    private String keyManagerFactoryAlgorithm;
+    private List<String> includeCipherSuites;
+    private List<String> excludeCipherSuites;
+    private List<String> includeProtocols;
+    private List<String> excludeProtocols;
+    private boolean requireClientCertificate = false;
+    private boolean requestClientCertificate = false;
+    private String trustStoreType;
+    private String trustStorePath;
+    private String trustStoreAlgorithm;
+    private PasswordProvider trustStorePasswordProvider;
+    private boolean validateHostnames = true;
+    private String crlPath;
+    private boolean reloadSslContext = false;
+    private int reloadSslContextSeconds = 60;
+    private boolean forceApplyConfig = false;
+
+    public Builder keyStorePath(String keyStorePath)
+    {
+      this.keyStorePath = keyStorePath;
+      return this;
+    }
+
+    public Builder keyStoreType(String keyStoreType)
+    {
+      this.keyStoreType = keyStoreType;
+      return this;
+    }
+
+    public Builder certAlias(String certAlias)
+    {
+      this.certAlias = certAlias;
+      return this;
+    }
+
+    public Builder keyStorePasswordProvider(PasswordProvider 
keyStorePasswordProvider)
+    {
+      this.keyStorePasswordProvider = keyStorePasswordProvider;
+      return this;
+    }
+
+    public Builder keyManagerPasswordProvider(PasswordProvider 
keyManagerPasswordProvider)
+    {
+      this.keyManagerPasswordProvider = keyManagerPasswordProvider;
+      return this;
+    }
+
+    public Builder keyManagerFactoryAlgorithm(String 
keyManagerFactoryAlgorithm)
+    {
+      this.keyManagerFactoryAlgorithm = keyManagerFactoryAlgorithm;
+      return this;
+    }
+
+    public Builder includeCipherSuites(List<String> includeCipherSuites)
+    {
+      this.includeCipherSuites = includeCipherSuites;
+      return this;
+    }
+
+    public Builder excludeCipherSuites(List<String> excludeCipherSuites)
+    {
+      this.excludeCipherSuites = excludeCipherSuites;
+      return this;
+    }
+
+    public Builder includeProtocols(List<String> includeProtocols)
+    {
+      this.includeProtocols = includeProtocols;
+      return this;
+    }
+
+    public Builder excludeProtocols(List<String> excludeProtocols)
+    {
+      this.excludeProtocols = excludeProtocols;
+      return this;
+    }
+
+    public Builder requireClientCertificate(boolean requireClientCertificate)
+    {
+      this.requireClientCertificate = requireClientCertificate;
+      return this;
+    }
+
+    public Builder requestClientCertificate(boolean requestClientCertificate)
+    {
+      this.requestClientCertificate = requestClientCertificate;
+      return this;
+    }
+
+    public Builder trustStoreType(String trustStoreType)
+    {
+      this.trustStoreType = trustStoreType;
+      return this;
+    }
+
+    public Builder trustStorePath(String trustStorePath)
+    {
+      this.trustStorePath = trustStorePath;
+      return this;
+    }
+
+    public Builder trustStoreAlgorithm(String trustStoreAlgorithm)
+    {
+      this.trustStoreAlgorithm = trustStoreAlgorithm;
+      return this;
+    }
+
+    public Builder trustStorePasswordProvider(PasswordProvider 
trustStorePasswordProvider)
+    {
+      this.trustStorePasswordProvider = trustStorePasswordProvider;
+      return this;
+    }
+
+    public Builder validateHostnames(boolean validateHostnames)
+    {
+      this.validateHostnames = validateHostnames;
+      return this;
+    }
+
+    public Builder crlPath(String crlPath)
+    {
+      this.crlPath = crlPath;
+      return this;
+    }
+
+    public Builder reloadSslContext(boolean reloadSslContext)
+    {
+      this.reloadSslContext = reloadSslContext;
+      return this;
+    }
+
+    public Builder reloadSslContextSeconds(int reloadSslContextSeconds)
+    {
+      this.reloadSslContextSeconds = reloadSslContextSeconds;
+      return this;
+    }
+
+    public Builder forceApplyConfig(boolean forceApplyConfig)
+    {
+      this.forceApplyConfig = forceApplyConfig;
+      return this;
+    }
+
+    public TLSServerConfig build()
+    {
+      TLSServerConfig config = new TLSServerConfig();
+      config.keyStorePath = this.keyStorePath;
+      config.keyStoreType = this.keyStoreType;
+      config.certAlias = this.certAlias;
+      config.keyStorePasswordProvider = this.keyStorePasswordProvider;
+      config.keyManagerPasswordProvider = this.keyManagerPasswordProvider;
+      config.keyManagerFactoryAlgorithm = this.keyManagerFactoryAlgorithm;
+      config.includeCipherSuites = this.includeCipherSuites;
+      config.excludeCipherSuites = this.excludeCipherSuites;
+      config.includeProtocols = this.includeProtocols;
+      config.excludeProtocols = this.excludeProtocols;
+      config.requireClientCertificate = this.requireClientCertificate;
+      config.requestClientCertificate = this.requestClientCertificate;
+      config.trustStoreType = this.trustStoreType;
+      config.trustStorePath = this.trustStorePath;
+      config.trustStoreAlgorithm = this.trustStoreAlgorithm;
+      config.trustStorePasswordProvider = this.trustStorePasswordProvider;
+      config.validateHostnames = this.validateHostnames;
+      config.crlPath = this.crlPath;
+      config.reloadSslContext = this.reloadSslContext;
+      config.reloadSslContextSeconds = this.reloadSslContextSeconds;
+      config.forceApplyConfig = this.forceApplyConfig;
+      return config;
+    }
+  }
 }
diff --git 
a/server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java
 
b/server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java
index b2e767a8b97..28d02166ee9 100644
--- 
a/server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java
+++ 
b/server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java
@@ -242,10 +242,13 @@ public class JettyServerModule extends JerseyServletModule
 
     if (node.isEnableTlsPort()) {
       log.info("Creating https connector with port [%d]", node.getTlsPort());
-      if (sslContextFactoryBinding == null) {
-        // Never trust all certificates by default
-        sslContextFactory = new 
IdentityCheckOverrideSslContextFactory(tlsServerConfig, certificateChecker);
+      boolean hasBinding = sslContextFactoryBinding != null;
+      sslContextFactory = hasBinding
+                          ? sslContextFactoryBinding.getProvider().get()
+                          : new 
IdentityCheckOverrideSslContextFactory(tlsServerConfig, certificateChecker);
 
+      // Never trust all certificates by default
+      if (!hasBinding || tlsServerConfig.isForceApplyConfig()) {
         sslContextFactory.setKeyStorePath(tlsServerConfig.getKeyStorePath());
         sslContextFactory.setKeyStoreType(tlsServerConfig.getKeyStoreType());
         
sslContextFactory.setKeyStorePassword(tlsServerConfig.getKeyStorePasswordProvider().getPassword());
@@ -303,8 +306,6 @@ public class JettyServerModule extends JerseyServletModule
             );
           }
         }
-      } else {
-        sslContextFactory = sslContextFactoryBinding.getProvider().get();
       }
 
       final HttpConfiguration httpsConfiguration = new HttpConfiguration();
diff --git 
a/server/src/test/java/org/apache/druid/server/initialization/JettyCertRenewTest.java
 
b/server/src/test/java/org/apache/druid/server/initialization/JettyCertRenewTest.java
index 031bdac1ee5..6f29d1c0036 100644
--- 
a/server/src/test/java/org/apache/druid/server/initialization/JettyCertRenewTest.java
+++ 
b/server/src/test/java/org/apache/druid/server/initialization/JettyCertRenewTest.java
@@ -115,86 +115,21 @@ public class JettyCertRenewTest extends BaseJettyTest
       File trustStore = new 
File(JettyCertRenewTest.class.getClassLoader().getResource("truststore.jks").getFile());
       tmpTrustStore = Files.copy(trustStore.toPath(), new 
File(folder.newFolder(), "truststore.jks").toPath());
       pp = () -> "druid123";
-      tlsConfig = new TLSServerConfig()
-      {
-        @Override
-        public String getKeyStorePath()
-        {
-          return tmpKeyStore.toString();
-        }
-
-        @Override
-        public String getKeyStoreType()
-        {
-          return "jks";
-        }
-
-        @Override
-        public PasswordProvider getKeyStorePasswordProvider()
-        {
-          return pp;
-        }
-
-        @Override
-        public PasswordProvider getKeyManagerPasswordProvider()
-        {
-          return pp;
-        }
-
-        @Override
-        public String getTrustStorePath()
-        {
-          return tmpTrustStore.toString();
-        }
-
-        @Override
-        public String getTrustStoreAlgorithm()
-        {
-          return "PKIX";
-        }
-
-        @Override
-        public PasswordProvider getTrustStorePasswordProvider()
-        {
-          return pp;
-        }
-
-        @Override
-        public String getCertAlias()
-        {
-          return "druid";
-        }
-
-        @Override
-        public boolean isRequireClientCertificate()
-        {
-          return false;
-        }
-
-        @Override
-        public boolean isRequestClientCertificate()
-        {
-          return false;
-        }
-
-        @Override
-        public boolean isValidateHostnames()
-        {
-          return false;
-        }
-
-        @Override
-        public boolean isReloadSslContext()
-        {
-          return true;
-        }
-
-        @Override
-        public int getReloadSslContextSeconds()
-        {
-          return 1;
-        }
-      };
+      tlsConfig = TLSServerConfig.builder()
+          .keyStorePath(tmpKeyStore.toString())
+          .keyStoreType("jks")
+          .keyStorePasswordProvider(pp)
+          .keyManagerPasswordProvider(pp)
+          .trustStorePath(tmpTrustStore.toString())
+          .trustStoreAlgorithm("PKIX")
+          .trustStorePasswordProvider(pp)
+          .certAlias("druid")
+          .requireClientCertificate(false)
+          .requestClientCertificate(false)
+          .validateHostnames(false)
+          .reloadSslContext(true)
+          .reloadSslContextSeconds(1)
+          .build();
     }
     catch (IOException e) {
       throw new RuntimeException(e);
diff --git 
a/server/src/test/java/org/apache/druid/server/initialization/JettyTest.java 
b/server/src/test/java/org/apache/druid/server/initialization/JettyTest.java
index 2185685f54a..d2f3c5078bc 100644
--- a/server/src/test/java/org/apache/druid/server/initialization/JettyTest.java
+++ b/server/src/test/java/org/apache/druid/server/initialization/JettyTest.java
@@ -123,74 +123,19 @@ public class JettyTest extends BaseJettyTest
       File trustStore = new 
File(JettyTest.class.getClassLoader().getResource("truststore.jks").getFile());
       Path tmpTrustStore = Files.copy(trustStore.toPath(), new 
File(folder.newFolder(), "truststore.jks").toPath());
       PasswordProvider pp = () -> "druid123";
-      tlsConfig = new TLSServerConfig()
-      {
-        @Override
-        public String getKeyStorePath()
-        {
-          return tmpKeyStore.toString();
-        }
-
-        @Override
-        public String getKeyStoreType()
-        {
-          return "jks";
-        }
-
-        @Override
-        public PasswordProvider getKeyStorePasswordProvider()
-        {
-          return pp;
-        }
-
-        @Override
-        public PasswordProvider getKeyManagerPasswordProvider()
-        {
-          return pp;
-        }
-
-        @Override
-        public String getTrustStorePath()
-        {
-          return tmpTrustStore.toString();
-        }
-
-        @Override
-        public String getTrustStoreAlgorithm()
-        {
-          return "PKIX";
-        }
-
-        @Override
-        public PasswordProvider getTrustStorePasswordProvider()
-        {
-          return pp;
-        }
-
-        @Override
-        public String getCertAlias()
-        {
-          return "druid";
-        }
-
-        @Override
-        public boolean isRequireClientCertificate()
-        {
-          return false;
-        }
-
-        @Override
-        public boolean isRequestClientCertificate()
-        {
-          return false;
-        }
-
-        @Override
-        public boolean isValidateHostnames()
-        {
-          return false;
-        }
-      };
+      tlsConfig = TLSServerConfig.builder()
+          .keyStorePath(tmpKeyStore.toString())
+          .keyStoreType("jks")
+          .keyStorePasswordProvider(pp)
+          .keyManagerPasswordProvider(pp)
+          .trustStorePath(tmpTrustStore.toString())
+          .trustStoreAlgorithm("PKIX")
+          .trustStorePasswordProvider(pp)
+          .certAlias("druid")
+          .requireClientCertificate(false)
+          .requestClientCertificate(false)
+          .validateHostnames(false)
+          .build();
 
       sslConfig =
           HttpClientConfig.builder()
diff --git 
a/server/src/test/java/org/apache/druid/server/initialization/jetty/JettyServerModuleTest.java
 
b/server/src/test/java/org/apache/druid/server/initialization/jetty/JettyServerModuleTest.java
index dee9cf097f8..a0bb48af699 100644
--- 
a/server/src/test/java/org/apache/druid/server/initialization/jetty/JettyServerModuleTest.java
+++ 
b/server/src/test/java/org/apache/druid/server/initialization/jetty/JettyServerModuleTest.java
@@ -19,11 +19,26 @@
 
 package org.apache.druid.server.initialization.jetty;
 
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import org.apache.druid.java.util.common.lifecycle.Lifecycle;
 import org.apache.druid.java.util.metrics.StubServiceEmitter;
+import org.apache.druid.metadata.PasswordProvider;
+import org.apache.druid.server.DruidNode;
+import org.apache.druid.server.initialization.ServerConfig;
+import org.apache.druid.server.initialization.TLSServerConfig;
+import org.apache.druid.server.security.TLSCertificateChecker;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.junit.Assert;
 import org.junit.Test;
 import org.mockito.Mockito;
 
+import java.util.Arrays;
+import java.util.List;
+
 public class JettyServerModuleTest
 {
   @Test
@@ -53,4 +68,174 @@ public class JettyServerModuleTest
     serviceEmitter.verifyValue("jetty/threadPool/queueSize", 50);
     serviceEmitter.verifyValue("jetty/threadPool/busy", 60);
   }
+
+  @Test
+  public void test_isEnableTlsPort_withoutBinding()
+  {
+    String keystorePath = 
JettyServerModuleTest.class.getClassLoader().getResource("server.jks").getFile();
+
+    PasswordProvider pp = Mockito.mock(PasswordProvider.class);
+    Mockito.when(pp.getPassword()).thenReturn("druid123");
+
+    TLSServerConfig tlsServerConfig = TLSServerConfig.builder()
+                                                     
.keyStorePath(keystorePath)
+                                                     .keyStoreType("jks")
+                                                     
.keyStorePasswordProvider(pp)
+                                                     .certAlias("druid")
+                                                     
.includeCipherSuites(List.of(
+                                                         
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"))
+                                                     
.includeProtocols(Arrays.asList("TLSv1.2", "TLSv1.3"))
+                                                     
.requireClientCertificate(false)
+                                                     
.requestClientCertificate(false)
+                                                     .build();
+
+    DruidNode node = new DruidNode("test", "localhost", false, 8080, 8443, 
true, true);
+    ServerConfig serverConfig = new ServerConfig();
+    Lifecycle lifecycle = new Lifecycle();
+    Injector injector = Mockito.mock(Injector.class);
+    TLSCertificateChecker certificateChecker = 
Mockito.mock(TLSCertificateChecker.class);
+
+    JettyServerInitializer initializer = 
Mockito.mock(JettyServerInitializer.class);
+    
Mockito.when(injector.getInstance(JettyServerInitializer.class)).thenReturn(initializer);
+
+    Server server = JettyServerModule.makeAndInitializeServer(
+        injector,
+        lifecycle,
+        node,
+        serverConfig,
+        tlsServerConfig,
+        null,
+        certificateChecker
+    );
+
+    Assert.assertNotNull(server);
+  }
+
+  @Test
+  public void test_isEnableTlsPort_withBinding_forceApplyConfig_isTrue()
+  {
+    String keystorePath = 
JettyServerModuleTest.class.getClassLoader().getResource("server.jks").getFile();
+
+    PasswordProvider pp = Mockito.mock(PasswordProvider.class);
+    Mockito.when(pp.getPassword()).thenReturn("druid123");
+
+    TLSServerConfig tlsServerConfig = TLSServerConfig.builder()
+                                                     
.keyStorePath(keystorePath)
+                                                     .keyStoreType("jks")
+                                                     
.keyStorePasswordProvider(pp)
+                                                     .certAlias("druid")
+                                                     
.excludeCipherSuites(List.of("TLS_RSA_WITH_NULL_SHA256"))
+                                                     
.excludeProtocols(Arrays.asList("TLSv1", "TLSv1.1"))
+                                                     
.requireClientCertificate(false)
+                                                     
.requestClientCertificate(false)
+                                                     .forceApplyConfig(true) 
// Force config to be applied
+                                                     .build();
+
+    DruidNode node = new DruidNode("test", "localhost", false, 8080, 8443, 
true, true);
+    ServerConfig serverConfig = new ServerConfig();
+    Lifecycle lifecycle = new Lifecycle();
+    Injector injector = Mockito.mock(Injector.class);
+    TLSCertificateChecker certificateChecker = 
Mockito.mock(TLSCertificateChecker.class);
+
+    JettyServerInitializer initializer = 
Mockito.mock(JettyServerInitializer.class);
+    
Mockito.when(injector.getInstance(JettyServerInitializer.class)).thenReturn(initializer);
+
+    // Create a custom SslContextFactory via binding
+    SslContextFactory.Server customSslContextFactory = 
Mockito.mock(SslContextFactory.Server.class);
+
+    @SuppressWarnings("unchecked")
+    Binding<SslContextFactory.Server> sslContextFactoryBinding = 
Mockito.mock(Binding.class);
+    @SuppressWarnings("unchecked")
+    Provider<SslContextFactory.Server> provider = Mockito.mock(Provider.class);
+
+    Mockito.when(sslContextFactoryBinding.getProvider()).thenReturn(provider);
+    Mockito.when(provider.get()).thenReturn(customSslContextFactory);
+
+    Server server = JettyServerModule.makeAndInitializeServer(
+        injector,
+        lifecycle,
+        node,
+        serverConfig,
+        tlsServerConfig,
+        sslContextFactoryBinding,
+        certificateChecker
+    );
+
+    Assert.assertNotNull(server);
+
+    // Verify that custom SSL context factory was used
+    Mockito.verify(provider).get();
+
+    // Verify that TLS config was still applied because forceApplyConfig=true
+    Mockito.verify(customSslContextFactory).setKeyStorePath(keystorePath);
+    Mockito.verify(customSslContextFactory).setKeyStoreType("jks");
+    Mockito.verify(customSslContextFactory).setKeyStorePassword("druid123");
+    Mockito.verify(customSslContextFactory).setCertAlias("druid");
+    
Mockito.verify(customSslContextFactory).setExcludeCipherSuites("TLS_RSA_WITH_NULL_SHA256");
+    Mockito.verify(customSslContextFactory).setExcludeProtocols("TLSv1", 
"TLSv1.1");
+  }
+
+  @Test
+  public void test_isEnableTlsPort_withBinding_forceApplyConfig_isFalse()
+  {
+    String keystorePath = 
JettyServerModuleTest.class.getClassLoader().getResource("server.jks").getFile();
+
+    PasswordProvider pp = Mockito.mock(PasswordProvider.class);
+    Mockito.when(pp.getPassword()).thenReturn("druid123");
+
+    TLSServerConfig tlsServerConfig = TLSServerConfig.builder()
+                                                     
.keyStorePath(keystorePath)
+                                                     .keyStoreType("jks")
+                                                     
.keyStorePasswordProvider(pp)
+                                                     .certAlias("druid")
+                                                     
.excludeCipherSuites(List.of("TLS_RSA_WITH_NULL_SHA256"))
+                                                     
.excludeProtocols(Arrays.asList("TLSv1", "TLSv1.1"))
+                                                     
.requireClientCertificate(false)
+                                                     
.requestClientCertificate(false)
+                                                     .forceApplyConfig(false)
+                                                     .build();
+
+    DruidNode node = new DruidNode("test", "localhost", false, 8080, 8443, 
true, true);
+    ServerConfig serverConfig = new ServerConfig();
+    Lifecycle lifecycle = new Lifecycle();
+    Injector injector = Mockito.mock(Injector.class);
+    TLSCertificateChecker certificateChecker = 
Mockito.mock(TLSCertificateChecker.class);
+
+    JettyServerInitializer initializer = 
Mockito.mock(JettyServerInitializer.class);
+    
Mockito.when(injector.getInstance(JettyServerInitializer.class)).thenReturn(initializer);
+
+    // Create a custom SslContextFactory via binding
+    SslContextFactory.Server customSslContextFactory = 
Mockito.mock(SslContextFactory.Server.class);
+
+    @SuppressWarnings("unchecked")
+    Binding<SslContextFactory.Server> sslContextFactoryBinding = 
Mockito.mock(Binding.class);
+    @SuppressWarnings("unchecked")
+    Provider<SslContextFactory.Server> provider = Mockito.mock(Provider.class);
+
+    Mockito.when(sslContextFactoryBinding.getProvider()).thenReturn(provider);
+    Mockito.when(provider.get()).thenReturn(customSslContextFactory);
+
+    Server server = JettyServerModule.makeAndInitializeServer(
+        injector,
+        lifecycle,
+        node,
+        serverConfig,
+        tlsServerConfig,
+        sslContextFactoryBinding,
+        certificateChecker
+    );
+
+    Assert.assertNotNull(server);
+
+    // Verify that custom SSL context factory was used
+    Mockito.verify(provider).get();
+
+    // Verify that TLS config was not still applied because 
forceApplyConfig=false
+    Mockito.verify(customSslContextFactory, 
Mockito.never()).setKeyStorePath(keystorePath);
+    Mockito.verify(customSslContextFactory, 
Mockito.never()).setKeyStoreType("jks");
+    Mockito.verify(customSslContextFactory, 
Mockito.never()).setKeyStorePassword("druid123");
+    Mockito.verify(customSslContextFactory, 
Mockito.never()).setCertAlias("druid");
+    Mockito.verify(customSslContextFactory, 
Mockito.never()).setExcludeCipherSuites("TLS_RSA_WITH_NULL_SHA256");
+    Mockito.verify(customSslContextFactory, 
Mockito.never()).setExcludeProtocols("TLSv1", "TLSv1.1");
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to