+ * http://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.apache.hadoop.hdfs.server.datanode.web; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hdfs.DFSConfigKeys; +import org.apache.hadoop.hdfs.HdfsConfiguration; +import org.apache.hadoop.hdfs.MiniDFSCluster; +import org.apache.hadoop.hdfs.server.datanode.DataNode; +import org.apache.hadoop.http.HttpServer2; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Test that X-Frame-Options works correctly with DatanodeHTTPServer. + */ +public class TestDatanodeHttpXFrame { + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void testDataNodeXFrameOptionsEnabled() throws Exception { + boolean xFrameEnabled = true; + MiniDFSCluster cluster = createCluster(xFrameEnabled, null); + HttpURLConnection conn = getConn(cluster); + String xfoHeader = conn.getHeaderField("X-FRAME-OPTIONS"); + Assert.assertTrue("X-FRAME-OPTIONS is absent in the header", + xfoHeader != null); + Assert.assertTrue(xfoHeader.endsWith(HttpServer2.XFrameOption + .SAMEORIGIN.toString())); + } + + @Test + public void testNameNodeXFrameOptionsDisabled() throws Exception { + boolean xFrameEnabled = false; + MiniDFSCluster cluster = createCluster(xFrameEnabled, null); + HttpURLConnection conn = getConn(cluster); + String xfoHeader = conn.getHeaderField("X-FRAME-OPTIONS"); + Assert.assertTrue("unexpected X-FRAME-OPTION in header", xfoHeader == null); + } + + @Test + public void testDataNodeXFramewithInvalidOptions() throws Exception { + exception.expect(IllegalArgumentException.class); + createCluster(false, "Hadoop"); + } + + private MiniDFSCluster createCluster(boolean enabled, String + value) throws IOException { + Configuration conf = new HdfsConfiguration(); + conf.setBoolean(DFSConfigKeys.DFS_XFRAME_OPTION_ENABLED, enabled); + if (value != null) { + conf.set(DFSConfigKeys.DFS_XFRAME_OPTION_VALUE, value); + } + MiniDFSCluster cluster = + new MiniDFSCluster.Builder(conf).numDataNodes(1).build(); + cluster.waitActive(); + return cluster; + } + + private HttpURLConnection getConn(MiniDFSCluster cluster) + throws IOException { + DataNode datanode = cluster.getDataNodes().get(0); + URL newURL = new URL("http://localhost:" + datanode.getInfoPort()); + HttpURLConnection conn = (HttpURLConnection) newURL.openConnection(); + conn.connect(); + return conn; + } +} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameNodeHttpServerXFrame.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameNodeHttpServerXFrame.java new file mode 100644 index 00000000000..947e95120a1 --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameNodeHttpServerXFrame.java @@ -0,0 +1,97 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * http://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.apache.hadoop.hdfs.server.namenode; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hdfs.DFSConfigKeys; +import org.apache.hadoop.hdfs.HdfsConfiguration; +import org.apache.hadoop.http.HttpServer2; +import org.apache.hadoop.net.NetUtils; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * A class to test the XFrameoptions of Namenode HTTP Server. We are not reusing + * the TestNameNodeHTTPServer since it is a parameterized class and these + * following tests will run multiple times doing the same thing, if we had the + * code in that classs. + */ +public class TestNameNodeHttpServerXFrame { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + public static URL getServerURL(HttpServer2 server) + throws MalformedURLException { + Assert.assertNotNull("No server", server); + return new URL("http://" + + NetUtils.getHostPortString(server.getConnectorAddress(0))); + } + + @Test + public void testNameNodeXFrameOptionsEnabled() throws Exception { + HttpURLConnection conn = createServerwithXFrame(true, null); + String xfoHeader = conn.getHeaderField("X-FRAME-OPTIONS"); + Assert.assertTrue("X-FRAME-OPTIONS is absent in the header", + xfoHeader != null); + Assert.assertTrue(xfoHeader.endsWith(HttpServer2.XFrameOption + .SAMEORIGIN.toString())); + } + + @Test + public void testNameNodeXFrameOptionsDisabled() throws Exception { + HttpURLConnection conn = createServerwithXFrame(false, null); + String xfoHeader = conn.getHeaderField("X-FRAME-OPTIONS"); + Assert.assertTrue("unexpected X-FRAME-OPTION in header", xfoHeader == null); + } + + @Test + public void testNameNodeXFrameOptionsIllegalOption() throws Exception { + exception.expect(IllegalArgumentException.class); + createServerwithXFrame(true, "hadoop"); + } + + private HttpURLConnection createServerwithXFrame(boolean enabled, String + value) throws IOException { + Configuration conf = new HdfsConfiguration(); + conf.set(DFSConfigKeys.DFS_NAMENODE_HTTPS_ADDRESS_KEY, "localhost:0"); + conf.setBoolean(DFSConfigKeys.DFS_XFRAME_OPTION_ENABLED, enabled); + if (value != null) { + conf.set(DFSConfigKeys.DFS_XFRAME_OPTION_VALUE, value); + + } + InetSocketAddress addr = InetSocketAddress.createUnresolved("localhost", 0); + NameNodeHttpServer server = null; + + server = new NameNodeHttpServer(conf, null, addr); + server.start(); + + URL url = getServerURL(server.getHttpServer()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.connect(); + return conn; + } +}