DRILL-7562: Support HTTP Basic authentication for REST API calls
This can greatly simplify the development of HTTP clients, as well as
use from the command line using curl/wget, since you don't have to
deal with storing the session cookie.
closes #1972
diff --git a/distribution/src/main/resources/drill-override-example.conf b/distribution/src/main/resources/drill-override-example.conf
index e72396c..0c04175 100644
--- a/distribution/src/main/resources/drill-override-example.conf
+++ b/distribution/src/main/resources/drill-override-example.conf
@@ -103,8 +103,8 @@
},
auth: {
# Http Auth mechanisms to configure. If not provided but user.auth is enabled
- # then default value is FORM.
- mechanisms: ["FORM", "SPNEGO"],
+ # then default value is ["FORM"].
+ mechanisms: ["BASIC", "FORM", "SPNEGO"],
# Spnego principal to be used by WebServer when Spnego authentication is enabled.
spnego.principal: "HTTP://<localhost>"
# Location to keytab file for above spnego principal
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/DrillHttpConstraintSecurityHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/DrillHttpConstraintSecurityHandler.java
index 8ba6ddf..99ca966 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/DrillHttpConstraintSecurityHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/DrillHttpConstraintSecurityHandler.java
@@ -17,6 +17,7 @@
*/
package org.apache.drill.exec.server.rest.auth;
+import org.apache.drill.exec.rpc.security.plain.PlainFactory;
import org.apache.drill.shaded.guava.com.google.common.collect.ImmutableSet;
import org.apache.drill.common.exceptions.DrillException;
import org.apache.drill.exec.server.DrillbitContext;
@@ -38,24 +39,33 @@
**/
public abstract class DrillHttpConstraintSecurityHandler extends ConstraintSecurityHandler {
- @Override
- public void doStart() throws Exception {
- super.doStart();
+ @Override
+ public void doStart() throws Exception {
+ super.doStart();
+ }
+
+ @Override
+ public void doStop() throws Exception {
+ super.doStop();
+ }
+
+ public abstract void doSetup(DrillbitContext dbContext) throws DrillException;
+
+ public void setup(LoginAuthenticator authenticator, LoginService loginService) {
+ final Set<String> knownRoles = ImmutableSet.of(AUTHENTICATED_ROLE, ADMIN_ROLE);
+ setConstraintMappings(Collections.<ConstraintMapping>emptyList(), knownRoles);
+ setAuthenticator(authenticator);
+ setLoginService(loginService);
+ }
+
+ protected void requireAuthProvider(DrillbitContext dbContext, String name) throws DrillException {
+ // Check if PAMAuthenticator is available or not which is required for FORM authentication
+ if (!dbContext.getAuthProvider().containsFactory(PlainFactory.SIMPLE_NAME)) {
+ throw new DrillException(String.format("%1$s auth mechanism was configured but %2$s mechanism is not enabled to provide an " +
+ "authenticator. Please configure user authentication with %2$s mechanism and authenticator to use " +
+ "%1$s authentication", getImplName(), name));
}
+ }
- @Override
- public void doStop() throws Exception {
- super.doStop();
- }
-
- public abstract void doSetup(DrillbitContext dbContext) throws DrillException;
-
- public void setup(LoginAuthenticator authenticator, LoginService loginService) {
- final Set<String> knownRoles = ImmutableSet.of(AUTHENTICATED_ROLE, ADMIN_ROLE);
- setConstraintMappings(Collections.<ConstraintMapping>emptyList(), knownRoles);
- setAuthenticator(authenticator);
- setLoginService(loginService);
- }
-
- public abstract String getImplName();
+ public abstract String getImplName();
}
\ No newline at end of file
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/DrillHttpSecurityHandlerProvider.java b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/DrillHttpSecurityHandlerProvider.java
index e95a057..e3087ca 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/DrillHttpSecurityHandlerProvider.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/DrillHttpSecurityHandlerProvider.java
@@ -27,6 +27,7 @@
import org.apache.drill.exec.rpc.security.AuthStringUtil;
import org.apache.drill.exec.server.DrillbitContext;
import org.apache.drill.exec.server.rest.WebServerConstants;
+import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.authentication.SessionAuthentication;
import org.eclipse.jetty.server.Handler;
@@ -139,10 +140,14 @@
if (isSpnegoEnabled() && (!isFormEnabled() || uri.equals(WebServerConstants.SPENGO_LOGIN_RESOURCE_PATH))) {
securityHandler = securityHandlers.get(Constraint.__SPNEGO_AUTH);
securityHandler.handle(target, baseRequest, request, response);
+ } else if(isBasicEnabled() && request.getHeader(HttpHeader.AUTHORIZATION.asString()) != null) {
+ securityHandler = securityHandlers.get(Constraint.__BASIC_AUTH);
+ securityHandler.handle(target, baseRequest, request, response);
} else if (isFormEnabled()) {
securityHandler = securityHandlers.get(Constraint.__FORM_AUTH);
securityHandler.handle(target, baseRequest, request, response);
}
+
}
// If user has logged in, use the corresponding handler to handle the request
else {
@@ -175,6 +180,10 @@
return securityHandlers.containsKey(Constraint.__FORM_AUTH);
}
+ public boolean isBasicEnabled() {
+ return securityHandlers.containsKey(Constraint.__BASIC_AUTH);
+ }
+
/**
* Return's list of configured mechanisms for HTTP authentication. For backward
* compatibility if authentication is enabled it will include FORM mechanism by default.
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/FormSecurityHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/FormSecurityHandler.java
index 2c19d41..8169a40 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/FormSecurityHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/FormSecurityHandler.java
@@ -33,15 +33,10 @@
@Override
public void doSetup(DrillbitContext dbContext) throws DrillException {
- // Check if PAMAuthenticator is available or not which is required for FORM authentication
- if (!dbContext.getAuthProvider().containsFactory(PlainFactory.SIMPLE_NAME)) {
- throw new DrillException("FORM mechanism was configured but PLAIN mechanism is not enabled to provide an " +
- "authenticator. Please configure user authentication with PLAIN mechanism and authenticator to use " +
- "FORM authentication");
- }
+ requireAuthProvider(dbContext, PlainFactory.SIMPLE_NAME);
setup(new FormAuthenticator(WebServerConstants.FORM_LOGIN_RESOURCE_PATH,
- WebServerConstants.FORM_LOGIN_RESOURCE_PATH, true), new DrillRestLoginService(dbContext));
+ WebServerConstants.FORM_LOGIN_RESOURCE_PATH, true), new DrillRestLoginService(dbContext));
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/HttpBasicAuthSecurityHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/HttpBasicAuthSecurityHandler.java
new file mode 100644
index 0000000..2657186
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/auth/HttpBasicAuthSecurityHandler.java
@@ -0,0 +1,43 @@
+/*
+ * 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.drill.exec.server.rest.auth;
+
+import org.apache.drill.common.exceptions.DrillException;
+import org.apache.drill.exec.rpc.security.plain.PlainFactory;
+import org.apache.drill.exec.server.DrillbitContext;
+import org.eclipse.jetty.security.authentication.BasicAuthenticator;
+import org.eclipse.jetty.util.security.Constraint;
+
+/**
+ * Implement HTTP Basic authentication for REST API access
+ */
+public class HttpBasicAuthSecurityHandler extends DrillHttpConstraintSecurityHandler {
+ @Override
+ public String getImplName() {
+ return Constraint.__BASIC_AUTH;
+ }
+
+ @Override
+ public void doSetup(DrillbitContext dbContext) throws DrillException {
+
+ requireAuthProvider(dbContext, PlainFactory.SIMPLE_NAME);
+
+ setup(new BasicAuthenticator(), new DrillRestLoginService(dbContext));
+ }
+
+}