HBASE-20004 Client is not able to execute REST queries in a secure cluster

Signed-off-by: Ashish Singhi <ashishsinghi@apache.org>
This commit is contained in:
Ashish Singhi 2018-05-10 22:47:44 +05:30
parent 61f96b6ffa
commit 32b114e86b
4 changed files with 25 additions and 10 deletions

View File

@ -31,8 +31,10 @@ public final class HttpServerUtil {
/** /**
* Add constraints to a Jetty Context to disallow undesirable Http methods. * Add constraints to a Jetty Context to disallow undesirable Http methods.
* @param ctxHandler The context to modify * @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(); Constraint c = new Constraint();
c.setAuthenticate(true); c.setAuthenticate(true);
@ -41,13 +43,17 @@ public final class HttpServerUtil {
cmt.setMethod("TRACE"); cmt.setMethod("TRACE");
cmt.setPathSpec("/*"); cmt.setPathSpec("/*");
ConstraintMapping cmo = new ConstraintMapping();
cmo.setConstraint(c);
cmo.setMethod("OPTIONS");
cmo.setPathSpec("/*");
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler(); 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); ctxHandler.setSecurityHandler(securityHandler);
} }

View File

@ -95,6 +95,10 @@ public class RESTServer implements Constants {
private static final String PATH_SPEC_ANY = "/*"; 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) { private static void printUsageAndExit(Options options, int exitCode) {
HelpFormatter formatter = new HelpFormatter(); HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("hbase rest start", "", options, formatter.printHelp("hbase rest start", "", options,
@ -343,7 +347,8 @@ public class RESTServer implements Constants {
ctxHandler.addFilter(filter, PATH_SPEC_ANY, EnumSet.of(DispatcherType.REQUEST)); ctxHandler.addFilter(filter, PATH_SPEC_ANY, EnumSet.of(DispatcherType.REQUEST));
} }
addCSRFFilter(ctxHandler, conf); 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. // Put up info server.
int port = conf.getInt("hbase.rest.info.port", 8085); int port = conf.getInt("hbase.rest.info.port", 8085);

View File

@ -93,7 +93,7 @@ public class HBaseRESTTestingUtility {
conf.set(RESTServer.REST_CSRF_BROWSER_USERAGENTS_REGEX_KEY, ".*"); conf.set(RESTServer.REST_CSRF_BROWSER_USERAGENTS_REGEX_KEY, ".*");
RESTServer.addCSRFFilter(ctxHandler, conf); RESTServer.addCSRFFilter(ctxHandler, conf);
HttpServerUtil.constrainHttpMethods(ctxHandler); HttpServerUtil.constrainHttpMethods(ctxHandler, true);
// start the server // start the server
server.start(); server.start();

View File

@ -223,6 +223,9 @@ public class ThriftServerRunner implements Runnable {
private final JvmPauseMonitor pauseMonitor; private final JvmPauseMonitor pauseMonitor;
static String THRIFT_HTTP_ALLOW_OPTIONS_METHOD = "hbase.thrift.http.allow.options.method";
private static boolean THRIFT_HTTP_ALLOW_OPTIONS_METHOD_DEFAULT = false;
/** An enum of server implementation selections */ /** An enum of server implementation selections */
public enum ImplType { public enum ImplType {
HS_HA("hsha", true, THsHaServer.class, true), HS_HA("hsha", true, THsHaServer.class, true),
@ -455,7 +458,8 @@ public class ThriftServerRunner implements Runnable {
// Context handler // Context handler
ServletContextHandler ctxHandler = new ServletContextHandler(httpServer, "/", ServletContextHandler.SESSIONS); ServletContextHandler ctxHandler = new ServletContextHandler(httpServer, "/", ServletContextHandler.SESSIONS);
ctxHandler.addServlet(new ServletHolder(thriftHttpServlet), "/*"); ctxHandler.addServlet(new ServletHolder(thriftHttpServlet), "/*");
HttpServerUtil.constrainHttpMethods(ctxHandler); HttpServerUtil.constrainHttpMethods(ctxHandler,
conf.getBoolean(THRIFT_HTTP_ALLOW_OPTIONS_METHOD, THRIFT_HTTP_ALLOW_OPTIONS_METHOD_DEFAULT));
// set up Jetty and run the embedded server // set up Jetty and run the embedded server
HttpConfiguration httpConfig = new HttpConfiguration(); HttpConfiguration httpConfig = new HttpConfiguration();