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

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 77e48039767 HDDS-16682. Allow enabling HTTPS SNI host check via config 
(#11389)
77e48039767 is described below

commit 77e480397676bb38c23848daf399df1c5473f587
Author: Andrey Yarovoy <[email protected]>
AuthorDate: Tue Oct 6 11:46:19 2026 -0400

    HDDS-16682. Allow enabling HTTPS SNI host check via config (#11389)
---
 .../org/apache/hadoop/ozone/OzoneConfigKeys.java   |  3 +++
 .../common/src/main/resources/ozone-default.xml    | 16 ++++++++++++
 .../hadoop/hdds/server/http/HttpServer2.java       |  9 +++++--
 .../hdds/server/http/TestHttpServer2SSL.java       | 30 ++++++++++++++++++++--
 4 files changed, 54 insertions(+), 4 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java
index ab735c23940..e9f283269db 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java
@@ -569,6 +569,9 @@ public final class OzoneConfigKeys {
       "ozone.http.policy";
   public static final String OZONE_HTTP_POLICY_DEFAULT =
       HttpConfig.Policy.HTTP_ONLY.name();
+  public static final String OZONE_HTTP_SNI_HOST_CHECK_ENABLED =
+      "ozone.http.sni.host.check.enabled";
+  public static final boolean OZONE_HTTP_SNI_HOST_CHECK_ENABLED_DEFAULT = 
false;
   public static final String  OZONE_SSL_ENABLED_PROTOCOLS = 
"ozone.ssl.enabled.protocols";
   public static final String  OZONE_SERVER_HTTPS_KEYSTORE_RESOURCE_KEY =
       "ozone.https.server.keystore.resource";
diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml 
b/hadoop-hdds/common/src/main/resources/ozone-default.xml
index b021ea8c473..ec3ec030b76 100644
--- a/hadoop-hdds/common/src/main/resources/ozone-default.xml
+++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml
@@ -3846,6 +3846,22 @@
       - HTTP_AND_HTTPS : Service is provided both on http and https
     </description>
   </property>
+  <property>
+    <name>ozone.http.sni.host.check.enabled</name>
+    <value>false</value>
+    <tag>OZONE, SECURITY, MANAGEMENT</tag>
+    <description>
+      Whether the HTTPS endpoints of Ozone daemons require the request's Host 
header
+      (or TLS SNI name) to be covered by the certificate the server serves. 
When this
+      is false, a request whose name the certificate does not cover is still 
served
+      with that certificate, which is how the HTTPS endpoints behaved before 
the Jetty
+      12 upgrade. Enabling the check rejects such a request with 400 "Invalid 
SNI", so
+      it requires the server certificate to carry every name clients connect 
with as a
+      SubjectAlternativeName - including an iPAddress entry for every address 
clients
+      reach by IP literal, because such a request sends no SNI at all, and 
entries for
+      any load balancer, virtual IP or DNS alias in front of the daemon.
+    </description>
+  </property>
   <property>
     <name>ozone.https.client.need-auth</name>
     <tag>OZONE, SECURITY, MANAGEMENT</tag>
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/http/HttpServer2.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/http/HttpServer2.java
index b8b2b2bb182..775e1bc1cf9 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/http/HttpServer2.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/http/HttpServer2.java
@@ -626,8 +626,13 @@ private ServerConnector createHttpsChannelConnector(
       // IP literal (which send no SNI) or to localhost/VIP/alias names absent
       // from the keystore certificate. Jetty 9.4 only ran that check when the
       // client's SNI matched a certificate, so such requests were served with
-      // the default certificate. Disable the check to preserve that behaviour.
-      httpConfig.addCustomizer(new SecureRequestCustomizer(false));
+      // the default certificate. The check is off by default to preserve that
+      // behaviour, and opt-in for deployments whose certificate covers every
+      // name clients use.
+      boolean sniHostCheck = conf.getBoolean(
+          OzoneConfigKeys.OZONE_HTTP_SNI_HOST_CHECK_ENABLED,
+          OzoneConfigKeys.OZONE_HTTP_SNI_HOST_CHECK_ENABLED_DEFAULT);
+      httpConfig.addCustomizer(new SecureRequestCustomizer(sniHostCheck));
       ServerConnector conn = createHttpChannelConnector(server, httpConfig);
 
       SslContextFactory.Server sslContextFactory =
diff --git 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/http/TestHttpServer2SSL.java
 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/http/TestHttpServer2SSL.java
index 693807f4933..31451584822 100644
--- 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/http/TestHttpServer2SSL.java
+++ 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/http/TestHttpServer2SSL.java
@@ -43,6 +43,7 @@
 import javax.net.ssl.TrustManagerFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.OzoneConfigKeys;
 import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
 import org.apache.hadoop.security.ssl.SSLFactory;
 import org.eclipse.jetty.server.ServerConnector;
@@ -183,8 +184,9 @@ public void testDefaultConfigAcceptsConnection() throws 
Exception {
    * CN=localhost with no SubjectAlternativeName, so the "localhost" name it
    * covers is served, but the 127.0.0.1 IP literal it does not cover -- which,
    * being an IP address, carries no SNI -- would be rejected under that 
default.
-   * HttpServer2 disables the check to preserve Jetty 9.4 behaviour (which 
served
-   * such requests with the default certificate), so both are served with 200.
+   * HttpServer2 leaves the check disabled by default to preserve Jetty 9.4
+   * behaviour (which served such requests with the default certificate), so 
both
+   * are served with 200.
    */
   @Test
   public void testIpLiteralServedWithNonMatchingCertificate() throws Exception 
{
@@ -205,6 +207,30 @@ public void 
testIpLiteralServedWithNonMatchingCertificate() throws Exception {
     }
   }
 
+  /**
+   * The mirror of {@link #testIpLiteralServedWithNonMatchingCertificate()}: 
with
+   * the SNI host check enabled, the same IP literal the CN=localhost test
+   * certificate does not cover is rejected with 400 "Invalid SNI", while the 
name
+   * it does cover is still served.
+   */
+  @Test
+  public void testIpLiteralRejectedWhenSniHostCheckEnabled() throws Exception {
+    OzoneConfiguration serverConf = new OzoneConfiguration(conf);
+    serverConf.setBoolean(OzoneConfigKeys.OZONE_HTTP_SNI_HOST_CHECK_ENABLED, 
true);
+    HttpServer2 server = buildServer(serverConf, null, null, null);
+    server.start();
+    try {
+      InetSocketAddress addr = server.getConnectorAddress(0);
+      SSLSocketFactory factory = createSocketFactory(null, null);
+      assertEquals(HttpURLConnection.HTTP_OK,
+          connectWithFactory(factory, "localhost", addr));
+      assertEquals(HttpURLConnection.HTTP_BAD_REQUEST,
+          connectWithFactory(factory, "127.0.0.1", addr));
+    } finally {
+      server.stop();
+    }
+  }
+
   @Test
   public void testEnabledProtocolAppliedWhenConfigUnset() throws Exception {
     OzoneConfiguration serverConf = new OzoneConfiguration(conf);


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

Reply via email to