You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by we...@apache.org on 2025/04/18 23:19:57 UTC
(hadoop) branch branch-3.4 updated: HADOOP-19546. Include cipher feature for HttpServer2 and SSLFactory (#7629)
This is an automated email from the ASF dual-hosted git repository.
weichiu pushed a commit to branch branch-3.4
in repository https://gitbox.apache.org/repos/asf/hadoop.git
The following commit(s) were added to refs/heads/branch-3.4 by this push:
new 5173c0e934d HADOOP-19546. Include cipher feature for HttpServer2 and SSLFactory (#7629)
5173c0e934d is described below
commit 5173c0e934d4895d7824c4f44a28374c9bf6f66d
Author: K0K0V0K <10...@users.noreply.github.com>
AuthorDate: Sat Apr 19 01:17:51 2025 +0200
HADOOP-19546. Include cipher feature for HttpServer2 and SSLFactory (#7629)
(cherry picked from commit 7d474d37fe353a5dc05a6bfc4f1a80c5094eda99)
---
.../src/main/conf/ssl-server.xml.example | 20 ++++++++++-
.../java/org/apache/hadoop/http/HttpServer2.java | 18 ++++++++--
.../org/apache/hadoop/security/ssl/SSLFactory.java | 41 +++++++++++-----------
.../java/org/apache/hadoop/util/StringUtils.java | 10 ++++++
.../org/apache/hadoop/http/TestHttpCookieFlag.java | 4 +--
.../org/apache/hadoop/http/TestSSLHttpServer.java | 4 ++-
.../hadoop/http/TestSSLHttpServerConfigs.java | 4 ++-
.../main/java/org/apache/hadoop/hdfs/DFSUtil.java | 4 ++-
.../hadoop/yarn/webapp/util/WebAppUtils.java | 4 ++-
.../yarn/webapp/util/TestWebServiceClient.java | 4 ++-
10 files changed, 83 insertions(+), 30 deletions(-)
diff --git a/hadoop-common-project/hadoop-common/src/main/conf/ssl-server.xml.example b/hadoop-common-project/hadoop-common/src/main/conf/ssl-server.xml.example
index a6820e952d5..cf1aac04d06 100644
--- a/hadoop-common-project/hadoop-common/src/main/conf/ssl-server.xml.example
+++ b/hadoop-common-project/hadoop-common/src/main/conf/ssl-server.xml.example
@@ -82,7 +82,25 @@
SSL_RSA_EXPORT_WITH_RC4_40_MD5,SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
SSL_RSA_WITH_RC4_128_MD5</value>
<description>Optional. The weak security cipher suites that you want excluded
- from SSL communication.</description>
+ from SSL communication.
+ Both ssl.server.include.cipher.list and ssl.server.exclude.cipher.list can be used simultaneously
+ to fine-tune the cipher suites utilized by Hadoop services.
+ If a cipher suite is present in both the inclusion and exclusion lists, it will be denied.
+ </description>
+</property>
+
+<property>
+ <name>ssl.server.include.cipher.list</name>
+ <value>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</value>
+ <description>Optional. If the inclusion list is populated,
+ any cipher not present in the list will not be allowed.
+ Both ssl.server.include.cipher.list and ssl.server.exclude.cipher.list can be used simultaneously
+ to fine-tune the cipher suites utilized by Hadoop services.
+ If a cipher suite is present in both the inclusion and exclusion lists, it will be denied.
+ </description>
</property>
</configuration>
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java
index d4bfa41b21c..161c13e2ef3 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java
@@ -252,6 +252,7 @@ public static class Builder {
new ArrayList<>(Collections.singletonList(
"hadoop.http.authentication."));
private String excludeCiphers;
+ private String includeCiphers;
private boolean xFrameEnabled;
private XFrameOption xFrameOption = XFrameOption.SAMEORIGIN;
@@ -399,6 +400,11 @@ public Builder excludeCiphers(String pExcludeCiphers) {
return this;
}
+ public Builder includeCiphers(String pIncludeCiphers) {
+ this.includeCiphers = pIncludeCiphers;
+ return this;
+ }
+
/**
* Adds the ability to control X_FRAME_OPTIONS on HttpServer2.
* @param xFrameEnabled - True enables X_FRAME_OPTIONS false disables it.
@@ -480,6 +486,7 @@ private void loadSSLConfiguration() throws IOException {
trustStoreType = sslConf.get(SSLFactory.SSL_SERVER_TRUSTSTORE_TYPE,
SSLFactory.SSL_SERVER_TRUSTSTORE_TYPE_DEFAULT);
excludeCiphers = sslConf.get(SSLFactory.SSL_SERVER_EXCLUDE_CIPHER_LIST);
+ includeCiphers = sslConf.get(SSLFactory.SSL_SERVER_INCLUDE_CIPHER_LIST);
}
public HttpServer2 build() throws IOException {
@@ -607,10 +614,17 @@ private ServerConnector createHttpsChannelConnector(
sslContextFactory.setTrustStorePassword(trustStorePassword);
}
}
- if(null != excludeCiphers && !excludeCiphers.isEmpty()) {
+
+ if (StringUtils.hasLength(excludeCiphers)) {
sslContextFactory.setExcludeCipherSuites(
StringUtils.getTrimmedStrings(excludeCiphers));
- LOG.info("Excluded Cipher List:" + excludeCiphers);
+ LOG.info("Excluded Cipher List:{}", excludeCiphers);
+ }
+
+ if (StringUtils.hasLength(includeCiphers)) {
+ sslContextFactory.setIncludeCipherSuites(
+ StringUtils.getTrimmedStrings(includeCiphers));
+ LOG.info("Included Cipher List:{}", includeCiphers);
}
setEnabledProtocols(sslContextFactory);
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ssl/SSLFactory.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ssl/SSLFactory.java
index 5ab38aa7420..eb8d8f6c37a 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ssl/SSLFactory.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ssl/SSLFactory.java
@@ -17,6 +17,7 @@
*/
package org.apache.hadoop.security.ssl;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
@@ -38,10 +39,9 @@
import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.GeneralSecurityException;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Iterator;
import java.util.List;
+import java.util.stream.Stream;
/**
* Factory that creates SSLEngine and SSLSocketFactory instances using
@@ -101,6 +101,9 @@ public enum Mode { CLIENT, SERVER }
public static final String SSL_SERVER_EXCLUDE_CIPHER_LIST =
"ssl.server.exclude.cipher.list";
+ public static final String SSL_SERVER_INCLUDE_CIPHER_LIST =
+ "ssl.server.include.cipher.list";
+
public static final String KEY_MANAGER_SSLCERTIFICATE =
IBM_JAVA ? "ibmX509" :
KeyManagerFactory.getDefaultAlgorithm();
@@ -125,6 +128,7 @@ public enum Mode { CLIENT, SERVER }
private String[] enabledProtocols = null;
private List<String> excludeCiphers;
+ private List<String> includeCiphers;
/**
* Creates an SSLFactory.
@@ -153,9 +157,13 @@ public SSLFactory(Mode mode, Configuration conf) {
SSL_ENABLED_PROTOCOLS_DEFAULT);
excludeCiphers = Arrays.asList(
sslConf.getTrimmedStrings(SSL_SERVER_EXCLUDE_CIPHER_LIST));
+ includeCiphers = Arrays.asList(
+ sslConf.getTrimmedStrings(SSL_SERVER_INCLUDE_CIPHER_LIST));
if (LOG.isDebugEnabled()) {
LOG.debug("will exclude cipher suites: {}",
StringUtils.join(",", excludeCiphers));
+ LOG.debug("will include cipher suites: {}",
+ StringUtils.join(",", includeCiphers));
}
}
@@ -261,30 +269,23 @@ public SSLEngine createSSLEngine()
} else {
sslEngine.setUseClientMode(false);
sslEngine.setNeedClientAuth(requireClientCert);
- disableExcludedCiphers(sslEngine);
+ callSetEnabledCipherSuites(sslEngine);
}
sslEngine.setEnabledProtocols(enabledProtocols);
return sslEngine;
}
- private void disableExcludedCiphers(SSLEngine sslEngine) {
- String[] cipherSuites = sslEngine.getEnabledCipherSuites();
-
- ArrayList<String> defaultEnabledCipherSuites =
- new ArrayList<String>(Arrays.asList(cipherSuites));
- Iterator iterator = excludeCiphers.iterator();
-
- while(iterator.hasNext()) {
- String cipherName = (String)iterator.next();
- if(defaultEnabledCipherSuites.contains(cipherName)) {
- defaultEnabledCipherSuites.remove(cipherName);
- LOG.debug("Disabling cipher suite {}.", cipherName);
- }
+ private void callSetEnabledCipherSuites(SSLEngine sslEngine) {
+ Stream<String> cipherSuites = Arrays.stream(sslEngine.getSupportedCipherSuites());
+ if (CollectionUtils.isNotEmpty(includeCiphers)) {
+ cipherSuites = cipherSuites.filter(s -> includeCiphers.contains(s));
}
-
- cipherSuites = defaultEnabledCipherSuites.toArray(
- new String[defaultEnabledCipherSuites.size()]);
- sslEngine.setEnabledCipherSuites(cipherSuites);
+ if (CollectionUtils.isNotEmpty(excludeCiphers)) {
+ cipherSuites = cipherSuites.filter(s -> !excludeCiphers.contains(s));
+ }
+ String[] enabledCipherSuites = cipherSuites.toArray(String[]::new);
+ LOG.debug("Enabled cipher suites: {}", StringUtils.join(",", enabledCipherSuites));
+ sslEngine.setEnabledCipherSuites(enabledCipherSuites);
}
/**
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java
index 2585729950b..9057871894f 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java
@@ -1354,4 +1354,14 @@ public static String wrap(String str, int wrapLength, String newLineStr,
return wrappedLine.toString();
}
}
+
+ /**
+ * Checks whether the given string is not {@code null} and has a length greater than zero.
+ *
+ * @param str the string to check
+ * @return {@code true} if the string is not {@code null} and not empty; {@code false} otherwise
+ */
+ public static boolean hasLength(String str) {
+ return str != null && !str.isEmpty();
+ }
}
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
index 8a722dff88d..e2d41e67115 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
@@ -104,8 +104,8 @@ public static void setUp() throws Exception {
.trustStore(sslConf.get("ssl.server.truststore.location"),
sslConf.get("ssl.server.truststore.password"),
sslConf.get("ssl.server.truststore.type", "jks"))
- .excludeCiphers(
- sslConf.get("ssl.server.exclude.cipher.list"))
+ .excludeCiphers(sslConf.get("ssl.server.exclude.cipher.list"))
+ .includeCiphers(sslConf.get("ssl.server.include.cipher.list"))
.build();
server.addServlet("echo", "/echo", TestHttpServer.EchoServlet.class);
server.start();
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestSSLHttpServer.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestSSLHttpServer.java
index cc76b4ad6d9..5ffed17b38c 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestSSLHttpServer.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestSSLHttpServer.java
@@ -149,7 +149,9 @@ private static void setupServer(Configuration conf, Configuration sslConf)
sslConf.get(SSL_SERVER_TRUSTSTORE_PROP_PREFIX + ".location"),
sslConf.get(SSL_SERVER_TRUSTSTORE_PROP_PREFIX + ".password"),
sslConf.get(SSL_SERVER_TRUSTSTORE_PROP_PREFIX + ".type", "jks"))
- .excludeCiphers(sslConf.get("ssl.server.exclude.cipher.list")).build();
+ .excludeCiphers(sslConf.get("ssl.server.exclude.cipher.list"))
+ .includeCiphers(sslConf.get("ssl.server.include.cipher.list"))
+ .build();
server.addServlet(SERVLET_NAME_ECHO, SERVLET_PATH_ECHO, EchoServlet.class);
server.addServlet(SERVLET_NAME_LONGHEADER, SERVLET_PATH_LONGHEADER,
LongHeaderServlet.class);
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestSSLHttpServerConfigs.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestSSLHttpServerConfigs.java
index 039fae01957..f5c4c59d861 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestSSLHttpServerConfigs.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestSSLHttpServerConfigs.java
@@ -109,7 +109,9 @@ private HttpServer2 setupServer(String keyStoreKeyPassword,
sslConf.get(SSL_SERVER_TRUSTSTORE_PROP_PREFIX + ".location"),
trustStorePassword,
sslConf.get(SSL_SERVER_TRUSTSTORE_PROP_PREFIX + ".type", "jks"))
- .excludeCiphers(sslConf.get("ssl.server.exclude.cipher.list")).build();
+ .excludeCiphers(sslConf.get("ssl.server.exclude.cipher.list"))
+ .includeCiphers(sslConf.get("ssl.server.include.cipher.list"))
+ .build();
return server;
}
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java
index 3ecb20bc6a2..2c52b58d7cd 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java
@@ -1630,7 +1630,9 @@ public static HttpServer2.Builder loadSslConfToHttpServerBuilder(HttpServer2.Bui
getPassword(sslConf, DFS_SERVER_HTTPS_TRUSTSTORE_PASSWORD_KEY),
sslConf.get("ssl.server.truststore.type", "jks"))
.excludeCiphers(
- sslConf.get("ssl.server.exclude.cipher.list"));
+ sslConf.get("ssl.server.exclude.cipher.list"))
+ .includeCiphers(
+ sslConf.get("ssl.server.include.cipher.list"));
}
/**
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/util/WebAppUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/util/WebAppUtils.java
index ff04ffe47a2..c0d7021f302 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/util/WebAppUtils.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/util/WebAppUtils.java
@@ -492,7 +492,9 @@ public static HttpServer2.Builder loadSslConfiguration(
getPassword(sslConf, WEB_APP_TRUSTSTORE_PASSWORD_KEY),
sslConf.get("ssl.server.truststore.type", "jks"))
.excludeCiphers(
- sslConf.get("ssl.server.exclude.cipher.list"));
+ sslConf.get("ssl.server.exclude.cipher.list"))
+ .includeCiphers(
+ sslConf.get("ssl.server.include.cipher.list"));
}
/**
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/util/TestWebServiceClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/util/TestWebServiceClient.java
index b51dcf88bcb..a5a5e9024dd 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/util/TestWebServiceClient.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/util/TestWebServiceClient.java
@@ -83,7 +83,9 @@ void testCreateClient() throws Exception {
sslConf.get(SSL_SERVER_TRUSTSTORE_PROP_PREFIX + ".location"),
sslConf.get(SSL_SERVER_TRUSTSTORE_PROP_PREFIX + ".password"),
sslConf.get(SSL_SERVER_TRUSTSTORE_PROP_PREFIX + ".type", "jks"))
- .excludeCiphers(sslConf.get("ssl.server.exclude.cipher.list")).build();
+ .excludeCiphers(sslConf.get("ssl.server.exclude.cipher.list"))
+ .includeCiphers(sslConf.get("ssl.server.include.cipher.list"))
+ .build();
server.addServlet(SERVLET_NAME_ECHO, SERVLET_PATH_ECHO, EchoServlet.class);
server.start();
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org