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]