From 23c0200ceff429119737f3be45d8e1eb92003dce Mon Sep 17 00:00:00 2001 From: capistrant Date: Fri, 10 Oct 2025 09:23:11 -0500 Subject: [PATCH 1/3] all operator to ignore SNI host checking if they must --- .../server/initialization/ServerConfig.java | 19 ++++++++++++++++--- .../jetty/CliIndexerServerModule.java | 3 ++- .../jetty/JettyServerModule.java | 8 +++++++- .../initialization/ServerConfigTest.java | 5 ++++- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/org/apache/druid/server/initialization/ServerConfig.java b/server/src/main/java/org/apache/druid/server/initialization/ServerConfig.java index 45a2df48dfa0..a7206ca9cf7e 100644 --- a/server/src/main/java/org/apache/druid/server/initialization/ServerConfig.java +++ b/server/src/main/java/org/apache/druid/server/initialization/ServerConfig.java @@ -84,7 +84,8 @@ public ServerConfig( @NotNull ErrorResponseTransformStrategy errorResponseTransformStrategy, @Nullable String contentSecurityPolicy, boolean enableHSTS, - @Nullable UriCompliance uriCompliance + @Nullable UriCompliance uriCompliance, + boolean enforceStrictSNIHostChecking ) { this.numThreads = numThreads; @@ -109,6 +110,7 @@ public ServerConfig( this.contentSecurityPolicy = contentSecurityPolicy; this.enableHSTS = enableHSTS; this.uriCompliance = uriCompliance != null ? uriCompliance : UriCompliance.LEGACY; + this.enforceStrictSNIHostChecking = enforceStrictSNIHostChecking; } public ServerConfig() @@ -212,6 +214,9 @@ public ServerConfig(boolean enableQueryRequestsQueuing) @JsonProperty private boolean showDetailedJettyErrors = true; + @JsonProperty + private boolean enforceStrictSNIHostChecking = true; + public int getNumThreads() { return numThreads; @@ -328,6 +333,11 @@ public UriCompliance getUriCompliance() return uriCompliance; } + public boolean isEnforceStrictSNIHostChecking() + { + return enforceStrictSNIHostChecking; + } + @Override public boolean equals(Object o) { @@ -360,7 +370,8 @@ public boolean equals(Object o) Objects.equals(contentSecurityPolicy, that.getContentSecurityPolicy()) && enableHSTS == that.enableHSTS && enableQueryRequestsQueuing == that.enableQueryRequestsQueuing && - Objects.equals(uriCompliance, that.uriCompliance); + Objects.equals(uriCompliance, that.uriCompliance) && + enforceStrictSNIHostChecking == that.enforceStrictSNIHostChecking; } @Override @@ -389,7 +400,8 @@ public int hashCode() contentSecurityPolicy, enableHSTS, enableQueryRequestsQueuing, - uriCompliance + uriCompliance, + enforceStrictSNIHostChecking ); } @@ -420,6 +432,7 @@ public String toString() ", enableHSTS=" + enableHSTS + ", enableQueryRequestsQueuing=" + enableQueryRequestsQueuing + ", uriCompliance=" + uriCompliance + + ", enforceStrictSNIHostChecking=" + enforceStrictSNIHostChecking + '}'; } diff --git a/server/src/main/java/org/apache/druid/server/initialization/jetty/CliIndexerServerModule.java b/server/src/main/java/org/apache/druid/server/initialization/jetty/CliIndexerServerModule.java index 4782211da492..76fd422b32ad 100644 --- a/server/src/main/java/org/apache/druid/server/initialization/jetty/CliIndexerServerModule.java +++ b/server/src/main/java/org/apache/druid/server/initialization/jetty/CliIndexerServerModule.java @@ -167,7 +167,8 @@ public ServerConfig makeAdjustedServerConfig(ServerConfig oldConfig) oldConfig.getErrorResponseTransformStrategy(), oldConfig.getContentSecurityPolicy(), oldConfig.isEnableHSTS(), - oldConfig.getUriCompliance() + oldConfig.getUriCompliance(), + oldConfig.isEnforceStrictSNIHostChecking() ); } } 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 28d02166ee95..5d8ee33bf96f 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 @@ -315,7 +315,13 @@ static Server makeAndInitializeServer( } httpsConfiguration.setSecureScheme("https"); httpsConfiguration.setSecurePort(node.getTlsPort()); - httpsConfiguration.addCustomizer(new SecureRequestCustomizer()); + + // see https://github.com/jetty/jetty.project/pull/5398 + // This new strict enforcement can break some clients. Allow turning it off via config if necessary + final SecureRequestCustomizer secureRequestCustomizer = new SecureRequestCustomizer(); + secureRequestCustomizer.setSniHostCheck(config.isEnforceStrictSNIHostChecking()); + + httpsConfiguration.addCustomizer(secureRequestCustomizer); httpsConfiguration.setRequestHeaderSize(config.getMaxRequestHeaderSize()); httpsConfiguration.setSendServerVersion(false); final ServerConnector connector = new ServerConnector( diff --git a/server/src/test/java/org/apache/druid/initialization/ServerConfigTest.java b/server/src/test/java/org/apache/druid/initialization/ServerConfigTest.java index 913c7f6109af..a6947be39d5e 100644 --- a/server/src/test/java/org/apache/druid/initialization/ServerConfigTest.java +++ b/server/src/test/java/org/apache/druid/initialization/ServerConfigTest.java @@ -45,6 +45,7 @@ public void testSerde() throws Exception Assert.assertFalse(defaultConfig2.isEnableForwardedRequestCustomizer()); Assert.assertFalse(defaultConfig2.isEnableHSTS()); Assert.assertEquals(UriCompliance.LEGACY, defaultConfig.getUriCompliance()); + Assert.assertEquals(true, defaultConfig.isEnforceStrictSNIHostChecking()); ServerConfig modifiedConfig = new ServerConfig( 999, @@ -68,7 +69,8 @@ public void testSerde() throws Exception new AllowedRegexErrorResponseTransformStrategy(ImmutableList.of(".*")), "my-cool-policy", true, - UriCompliance.RFC3986 + UriCompliance.RFC3986, + false ); String modifiedConfigJson = OBJECT_MAPPER.writeValueAsString(modifiedConfig); ServerConfig modifiedConfig2 = OBJECT_MAPPER.readValue(modifiedConfigJson, ServerConfig.class); @@ -83,6 +85,7 @@ public void testSerde() throws Exception Assert.assertEquals("my-cool-policy", modifiedConfig2.getContentSecurityPolicy()); Assert.assertTrue(modifiedConfig2.isEnableHSTS()); Assert.assertEquals(UriCompliance.RFC3986, modifiedConfig2.getUriCompliance()); + Assert.assertFalse(modifiedConfig2.isEnforceStrictSNIHostChecking()); } @Test From ae5f77edd3d2735fe212889cf74d6dfb6db95056 Mon Sep 17 00:00:00 2001 From: capistrant Date: Fri, 10 Oct 2025 09:25:54 -0500 Subject: [PATCH 2/3] document new config --- docs/configuration/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configuration/index.md b/docs/configuration/index.md index 3198f6529f49..55be9754b0d3 100644 --- a/docs/configuration/index.md +++ b/docs/configuration/index.md @@ -1505,6 +1505,7 @@ Druid uses Jetty to serve HTTP requests. |`druid.server.http.allowedHttpMethods`|List of HTTP methods that should be allowed in addition to the ones required by Druid APIs. Druid APIs require GET, PUT, POST, and DELETE, which are always allowed. This option is not useful unless you have installed an extension that needs these additional HTTP methods or that adds functionality related to CORS. None of Druid's bundled extensions require these methods.|`[]`| |`druid.server.http.contentSecurityPolicy`|Content-Security-Policy header value to set on each non-POST response. Setting this property to an empty string, or omitting it, both result in the default `frame-ancestors: none` being set.|`frame-ancestors 'none'`| |`druid.server.http.uriCompliance`|Jetty `UriCompliance` mode for Druid's embedded Jetty servers. To modify, override this config with the string representation of any `UriCompliance` mode that [Jetty supports](https://javadoc.jetty.org/jetty-12/org/eclipse/jetty/http/UriCompliance.html).|LEGACY| +|`druid.server.http.enforceStrictSNIHostChecking`| If enabled, the Jetty server will enforce strict SNI host checking. This means that if a client connects to the server using TLS but does not provide an SNI hostname, or provides an SNI hostname that does not match the server's configured hostname, a request will get a 400 response. Setting this to false is not recommended in production.|true| #### Indexer processing resources From 135eb6ceff4e6adce34bd2e0b148b12136d7bca7 Mon Sep 17 00:00:00 2001 From: capistrant Date: Fri, 10 Oct 2025 09:48:43 -0500 Subject: [PATCH 3/3] Add SNI to dictionary --- website/.spelling | 1 + 1 file changed, 1 insertion(+) diff --git a/website/.spelling b/website/.spelling index 82711ff84421..7aefe34bcba1 100644 --- a/website/.spelling +++ b/website/.spelling @@ -227,6 +227,7 @@ S3 SAS SDK SIGAR +SNI SPNEGO Splunk SqlInputSource