diff --git a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java index 71186d5ff5f..bfcaf7d4fa3 100644 --- a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java +++ b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java @@ -129,6 +129,7 @@ import org.mortbay.jetty.Server; import org.mortbay.jetty.nio.SelectChannelConnector; import org.mortbay.jetty.servlet.Context; import org.mortbay.jetty.servlet.ServletHolder; +import org.mortbay.jetty.webapp.WebAppContext; import org.mortbay.thread.QueuedThreadPool; import com.google.common.base.Joiner; @@ -421,8 +422,9 @@ public class ThriftServerRunner implements Runnable { httpServer = new Server(); // Context handler - Context context = new Context(httpServer, "/", Context.SESSIONS); + Context context = new WebAppContext(); context.setContextPath("/"); + context.setResourceBase("hbase-webapps/"); String httpPath = "/*"; httpServer.setHandler(context); context.addServlet(new ServletHolder(thriftHttpServlet), httpPath); diff --git a/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftHttpServer.java b/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftHttpServer.java index ed91a29aaaa..c5b305de86e 100644 --- a/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftHttpServer.java +++ b/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftHttpServer.java @@ -18,6 +18,7 @@ */ package org.apache.hadoop.hbase.thrift; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; @@ -152,6 +153,46 @@ public class TestThriftHttpServer { runThriftServer(0); } + @Test + public void testThriftServerHttpTraceForbiddenWhenOptionsDisabled() throws Exception { + // HTTP TRACE method should be disabled for security + // See https://www.owasp.org/index.php/Cross_Site_Tracing + checkHttpMethods("TRACE", HttpURLConnection.HTTP_FORBIDDEN); + } + + @Test + public void testThriftServerHttpTraceForbiddenWhenOptionsEnabled() throws Exception { + // HTTP TRACE method should be disabled for security + // See https://www.owasp.org/index.php/Cross_Site_Tracing + TEST_UTIL.getConfiguration().setBoolean(ThriftServerRunner.THRIFT_HTTP_ALLOW_OPTIONS_METHOD, + true); + checkHttpMethods("TRACE", HttpURLConnection.HTTP_FORBIDDEN); + } + + @Test + public void testThriftServerHttpOptionsForbiddenWhenOptionsDisabled() throws Exception { + // HTTP OPTIONS method should be disabled by default, so we make sure + // hbase.thrift.http.allow.options.method is not set anywhere in the config + TEST_UTIL.getConfiguration().unset(ThriftServerRunner.THRIFT_HTTP_ALLOW_OPTIONS_METHOD); + checkHttpMethods("OPTIONS", HttpURLConnection.HTTP_FORBIDDEN); + } + + @Test + public void testThriftServerHttpOptionsOkWhenOptionsEnabled() throws Exception { + TEST_UTIL.getConfiguration().setBoolean(ThriftServerRunner.THRIFT_HTTP_ALLOW_OPTIONS_METHOD, + true); + checkHttpMethods("OPTIONS", HttpURLConnection.HTTP_OK); + } + + private void waitThriftServerStartup() throws Exception{ + // wait up to 10s for the server to start + for (int i = 0; i < 100 + && ( thriftServer.serverRunner == null || thriftServer.serverRunner.httpServer == + null); i++) { + Thread.sleep(100); + } + } + private void runThriftServer(int customHeaderSize) throws Exception { List args = new ArrayList(); port = HBaseTestingUtility.randomFreePort(); @@ -162,16 +203,10 @@ public class TestThriftHttpServer { thriftServer = new ThriftServer(TEST_UTIL.getConfiguration()); startHttpServerThread(args.toArray(new String[args.size()])); - // wait up to 10s for the server to start - for (int i = 0; i < 100 - && ( thriftServer.serverRunner == null || thriftServer.serverRunner.httpServer == - null); i++) { - Thread.sleep(100); - } + waitThriftServerStartup(); String url = "http://"+ HConstants.LOCALHOST + ":" + port; try { - checkHttpMethods(url); talkToThriftServer(url, customHeaderSize); } catch (Exception ex) { clientSideException = ex; @@ -189,13 +224,20 @@ public class TestThriftHttpServer { } } - private void checkHttpMethods(String url) throws Exception { - // HTTP TRACE method should be disabled for security - // See https://www.owasp.org/index.php/Cross_Site_Tracing - HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); - conn.setRequestMethod("TRACE"); - conn.connect(); - Assert.assertEquals(HttpURLConnection.HTTP_FORBIDDEN, conn.getResponseCode()); + private void checkHttpMethods(String httpRequestMethod, + int httpExpectedResponse) throws Exception { + port = HBaseTestingUtility.randomFreePort(); + thriftServer = new ThriftServer(TEST_UTIL.getConfiguration()); + try { + startHttpServerThread(new String[] { "-port", String.valueOf(port), "start" }); + waitThriftServerStartup(); + final URL url = new URL("http://"+ HConstants.LOCALHOST + ":" + port); + final HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + httpConn.setRequestMethod(httpRequestMethod); + assertEquals(httpExpectedResponse, httpConn.getResponseCode()); + } finally { + stopHttpServerThread(); + } } private static volatile boolean tableCreated = false;