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 xy...@apache.org on 2018/05/23 22:56:30 UTC
[38/50] [abbrv] hadoop git commit: HADOOP-15457. Add Security-Related
HTTP Response Header in WEBUIs. (kanwaljeets via rkanter)
HADOOP-15457. Add Security-Related HTTP Response Header in WEBUIs. (kanwaljeets via rkanter)
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/aa23d49f
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/aa23d49f
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/aa23d49f
Branch: refs/heads/HDDS-4
Commit: aa23d49fc8b9c2537529dbdc13512000e2ab295a
Parents: bc6d9d4
Author: Robert Kanter <rk...@apache.org>
Authored: Wed May 23 10:23:17 2018 -0700
Committer: Robert Kanter <rk...@apache.org>
Committed: Wed May 23 10:24:09 2018 -0700
----------------------------------------------------------------------
.../org/apache/hadoop/http/HttpServer2.java | 79 +++++++++++++++-----
.../org/apache/hadoop/http/TestHttpServer.java | 61 +++++++++++++++
2 files changed, 121 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hadoop/blob/aa23d49f/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java
----------------------------------------------------------------------
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 47ca841..c273c78 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
@@ -34,6 +34,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -172,10 +174,16 @@ public final class HttpServer2 implements FilterContainer {
private final SignerSecretProvider secretProvider;
private XFrameOption xFrameOption;
private boolean xFrameOptionIsEnabled;
- private static final String X_FRAME_VALUE = "xFrameOption";
- private static final String X_FRAME_ENABLED = "X_FRAME_ENABLED";
-
-
+ public static final String HTTP_HEADER_PREFIX = "hadoop.http.header.";
+ private static final String HTTP_HEADER_REGEX =
+ "hadoop\\.http\\.header\\.([a-zA-Z\\-_]+)";
+ static final String X_XSS_PROTECTION =
+ "X-XSS-Protection:1; mode=block";
+ static final String X_CONTENT_TYPE_OPTIONS =
+ "X-Content-Type-Options:nosniff";
+ private static final String X_FRAME_OPTIONS = "X-FRAME-OPTIONS";
+ private static final Pattern PATTERN_HTTP_HEADER_REGEX =
+ Pattern.compile(HTTP_HEADER_REGEX);
/**
* Class to construct instances of HTTP server with specific options.
*/
@@ -574,10 +582,7 @@ public final class HttpServer2 implements FilterContainer {
addDefaultApps(contexts, appDir, conf);
webServer.setHandler(handlers);
- Map<String, String> xFrameParams = new HashMap<>();
- xFrameParams.put(X_FRAME_ENABLED,
- String.valueOf(this.xFrameOptionIsEnabled));
- xFrameParams.put(X_FRAME_VALUE, this.xFrameOption.toString());
+ Map<String, String> xFrameParams = setHeaders(conf);
addGlobalFilter("safety", QuotingInputFilter.class.getName(), xFrameParams);
final FilterInitializer[] initializers = getFilterInitializers(conf);
if (initializers != null) {
@@ -1475,9 +1480,11 @@ public final class HttpServer2 implements FilterContainer {
public static class QuotingInputFilter implements Filter {
private FilterConfig config;
+ private Map<String, String> headerMap;
public static class RequestQuoter extends HttpServletRequestWrapper {
private final HttpServletRequest rawRequest;
+
public RequestQuoter(HttpServletRequest rawRequest) {
super(rawRequest);
this.rawRequest = rawRequest;
@@ -1566,6 +1573,7 @@ public final class HttpServer2 implements FilterContainer {
@Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
+ initHttpHeaderMap();
}
@Override
@@ -1593,11 +1601,7 @@ public final class HttpServer2 implements FilterContainer {
} else if (mime.startsWith("application/xml")) {
httpResponse.setContentType("text/xml; charset=utf-8");
}
-
- if(Boolean.valueOf(this.config.getInitParameter(X_FRAME_ENABLED))) {
- httpResponse.addHeader("X-FRAME-OPTIONS",
- this.config.getInitParameter(X_FRAME_VALUE));
- }
+ headerMap.forEach((k, v) -> httpResponse.addHeader(k, v));
chain.doFilter(quoted, httpResponse);
}
@@ -1613,14 +1617,25 @@ public final class HttpServer2 implements FilterContainer {
return (mime == null) ? null : mime;
}
+ private void initHttpHeaderMap() {
+ Enumeration<String> params = this.config.getInitParameterNames();
+ headerMap = new HashMap<>();
+ while (params.hasMoreElements()) {
+ String key = params.nextElement();
+ Matcher m = PATTERN_HTTP_HEADER_REGEX.matcher(key);
+ if (m.matches()) {
+ String headerKey = m.group(1);
+ headerMap.put(headerKey, config.getInitParameter(key));
+ }
+ }
+ }
}
-
- /**
- * The X-FRAME-OPTIONS header in HTTP response to mitigate clickjacking
- * attack.
- */
+ /**
+ * The X-FRAME-OPTIONS header in HTTP response to mitigate clickjacking
+ * attack.
+ */
public enum XFrameOption {
- DENY("DENY") , SAMEORIGIN ("SAMEORIGIN"), ALLOWFROM ("ALLOW-FROM");
+ DENY("DENY"), SAMEORIGIN("SAMEORIGIN"), ALLOWFROM("ALLOW-FROM");
XFrameOption(String name) {
this.name = name;
@@ -1651,4 +1666,30 @@ public final class HttpServer2 implements FilterContainer {
throw new IllegalArgumentException("Unexpected value in xFrameOption.");
}
}
+
+
+ private Map<String, String> setHeaders(Configuration conf) {
+ Map<String, String> xFrameParams = new HashMap<>();
+ Map<String, String> headerConfigMap =
+ conf.getValByRegex(HTTP_HEADER_REGEX);
+
+ xFrameParams.putAll(getDefaultHeaders());
+ if(this.xFrameOptionIsEnabled) {
+ xFrameParams.put(HTTP_HEADER_PREFIX+X_FRAME_OPTIONS,
+ this.xFrameOption.toString());
+ }
+ xFrameParams.putAll(headerConfigMap);
+ return xFrameParams;
+ }
+
+ private Map<String, String> getDefaultHeaders() {
+ Map<String, String> headers = new HashMap<>();
+ String[] splitVal = X_CONTENT_TYPE_OPTIONS.split(":");
+ headers.put(HTTP_HEADER_PREFIX + splitVal[0],
+ splitVal[1]);
+ splitVal = X_XSS_PROTECTION.split(":");
+ headers.put(HTTP_HEADER_PREFIX + splitVal[0],
+ splitVal[1]);
+ return headers;
+ }
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/aa23d49f/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java
index 6c1512e..26b1137 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java
@@ -701,4 +701,65 @@ public class TestHttpServer extends HttpServerFunctionalTest {
ServerConnector listener = (ServerConnector)listeners.get(0);
assertEquals(backlogSize, listener.getAcceptQueueSize());
}
+
+ @Test
+ public void testHttpResponseDefaultHeaders() throws Exception {
+ Configuration conf = new Configuration();
+ HttpServer2 httpServer = createTestServer(conf);
+ try {
+ HttpURLConnection conn = getHttpURLConnection(httpServer);
+ assertEquals(HttpServer2.X_XSS_PROTECTION.split(":")[1],
+ conn.getHeaderField(
+ HttpServer2.X_XSS_PROTECTION.split(":")[0]));
+ assertEquals(HttpServer2.X_CONTENT_TYPE_OPTIONS.split(":")[1],
+ conn.getHeaderField(
+ HttpServer2.X_CONTENT_TYPE_OPTIONS.split(":")[0]));
+ } finally {
+ httpServer.stop();
+ }
+ }
+
+ @Test
+ public void testHttpResponseOverrideDefaultHeaders() throws Exception {
+ Configuration conf = new Configuration();
+ conf.set(HttpServer2.HTTP_HEADER_PREFIX+
+ HttpServer2.X_XSS_PROTECTION.split(":")[0], "customXssValue");
+ HttpServer2 httpServer = createTestServer(conf);
+ try {
+ HttpURLConnection conn = getHttpURLConnection(httpServer);
+ assertEquals("customXssValue",
+ conn.getHeaderField(
+ HttpServer2.X_XSS_PROTECTION.split(":")[0])
+ );
+ assertEquals(HttpServer2.X_CONTENT_TYPE_OPTIONS.split(":")[1],
+ conn.getHeaderField(
+ HttpServer2.X_CONTENT_TYPE_OPTIONS.split(":")[0])
+ );
+ } finally {
+ httpServer.stop();
+ }
+ }
+
+ @Test
+ public void testHttpResponseCustomHeaders() throws Exception {
+ Configuration conf = new Configuration();
+ String key = "customKey";
+ String value = "customValue";
+ conf.set(HttpServer2.HTTP_HEADER_PREFIX+key, value);
+ HttpServer2 httpServer = createTestServer(conf);
+ try {
+ HttpURLConnection conn = getHttpURLConnection(httpServer);
+ assertEquals(HttpServer2.X_XSS_PROTECTION.split(":")[1],
+ conn.getHeaderField(
+ HttpServer2.X_XSS_PROTECTION.split(":")[0]));
+ assertEquals(HttpServer2.X_CONTENT_TYPE_OPTIONS.split(":")[1],
+ conn.getHeaderField(
+ HttpServer2.X_CONTENT_TYPE_OPTIONS.split(":")[0]));
+ assertEquals(value, conn.getHeaderField(
+ key));
+ } finally {
+ httpServer.stop();
+ }
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org