From 6d10dae80b00f9e4fc2cc3bd493d2db6b6b84c60 Mon Sep 17 00:00:00 2001 From: Ashish Singhi Date: Mon, 7 May 2018 17:48:16 +0530 Subject: [PATCH] HBASE-20004 Client is not able to execute REST queries in a secure cluster --- .../apache/hadoop/hbase/http/HttpServerUtil.java | 22 ++++++++++++++-------- .../org/apache/hadoop/hbase/rest/RESTServer.java | 7 ++++++- .../hadoop/hbase/rest/HBaseRESTTestingUtility.java | 2 +- .../hadoop/hbase/thrift/ThriftServerRunner.java | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServerUtil.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServerUtil.java index 777ced009b..5213047f6a 100644 --- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServerUtil.java +++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServerUtil.java @@ -31,8 +31,10 @@ public final class HttpServerUtil { /** * Add constraints to a Jetty Context to disallow undesirable Http methods. * @param ctxHandler The context to modify + * @param allowOptionsMethod if true then OPTIONS method will not be set in constraint mapping */ - public static void constrainHttpMethods(ServletContextHandler ctxHandler) { + public static void constrainHttpMethods(ServletContextHandler ctxHandler, + boolean allowOptionsMethod) { Constraint c = new Constraint(); c.setAuthenticate(true); @@ -40,14 +42,18 @@ public final class HttpServerUtil { cmt.setConstraint(c); cmt.setMethod("TRACE"); cmt.setPathSpec("/*"); - - ConstraintMapping cmo = new ConstraintMapping(); - cmo.setConstraint(c); - cmo.setMethod("OPTIONS"); - cmo.setPathSpec("/*"); - + ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler(); - securityHandler.setConstraintMappings(new ConstraintMapping[]{ cmt, cmo }); + + if (!allowOptionsMethod) { + ConstraintMapping cmo = new ConstraintMapping(); + cmo.setConstraint(c); + cmo.setMethod("OPTIONS"); + cmo.setPathSpec("/*"); + securityHandler.setConstraintMappings(new ConstraintMapping[] { cmt, cmo }); + } else { + securityHandler.setConstraintMappings(new ConstraintMapping[] { cmt }); + } ctxHandler.setSecurityHandler(securityHandler); } diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java index 591eae9f02..5368a712b4 100644 --- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java +++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java @@ -94,6 +94,10 @@ public class RESTServer implements Constants { static String REST_CSRF_METHODS_TO_IGNORE_DEFAULT = "GET,OPTIONS,HEAD,TRACE"; private static final String PATH_SPEC_ANY = "/*"; + + static String REST_HTTP_ALLOW_OPTIONS_METHOD = "hbase.rest.http.allow.options.method"; + // HTTP OPTIONS method is commonly used in REST APIs for negotiation. So it is enabled by default. + private static boolean REST_HTTP_ALLOW_OPTIONS_METHOD_DEFAULT = true; private static void printUsageAndExit(Options options, int exitCode) { HelpFormatter formatter = new HelpFormatter(); @@ -341,7 +345,8 @@ public class RESTServer implements Constants { ctxHandler.addFilter(filter, PATH_SPEC_ANY, EnumSet.of(DispatcherType.REQUEST)); } addCSRFFilter(ctxHandler, conf); - HttpServerUtil.constrainHttpMethods(ctxHandler); + HttpServerUtil.constrainHttpMethods(ctxHandler, servlet.getConfiguration() + .getBoolean(REST_HTTP_ALLOW_OPTIONS_METHOD, REST_HTTP_ALLOW_OPTIONS_METHOD_DEFAULT)); // Put up info server. int port = conf.getInt("hbase.rest.info.port", 8085); diff --git a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java index 273010a334..38c734df0e 100644 --- a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java +++ b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java @@ -93,7 +93,7 @@ public class HBaseRESTTestingUtility { conf.set(RESTServer.REST_CSRF_BROWSER_USERAGENTS_REGEX_KEY, ".*"); RESTServer.addCSRFFilter(ctxHandler, conf); - HttpServerUtil.constrainHttpMethods(ctxHandler); + HttpServerUtil.constrainHttpMethods(ctxHandler, true); // start the server server.start(); 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 1db9256bd6..2ba9d86c7b 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 @@ -458,7 +458,7 @@ public class ThriftServerRunner implements Runnable { ServletContextHandler ctxHandler = new ServletContextHandler(httpServer, "/", ServletContextHandler.SESSIONS); ctxHandler.addServlet(new ServletHolder(thriftHttpServlet), "/*"); - HttpServerUtil.constrainHttpMethods(ctxHandler); + HttpServerUtil.constrainHttpMethods(ctxHandler, false); // set up Jetty and run the embedded server HttpConfiguration httpConfig = new HttpConfiguration(); -- 2.15.1.windows.2