You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by dd...@apache.org on 2013/12/19 19:05:15 UTC
svn commit: r1552385 - in /hbase/trunk:
hbase-common/src/main/resources/hbase-default.xml
hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServlet.java
hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServletContainer.java
Author: ddas
Date: Thu Dec 19 18:05:15 2013
New Revision: 1552385
URL: http://svn.apache.org/r1552385
Log:
HBASE-9866. Support the mode where REST server authorizes proxy users
Modified:
hbase/trunk/hbase-common/src/main/resources/hbase-default.xml
hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServlet.java
hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServletContainer.java
Modified: hbase/trunk/hbase-common/src/main/resources/hbase-default.xml
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-common/src/main/resources/hbase-default.xml?rev=1552385&r1=1552384&r2=1552385&view=diff
==============================================================================
--- hbase/trunk/hbase-common/src/main/resources/hbase-default.xml (original)
+++ hbase/trunk/hbase-common/src/main/resources/hbase-default.xml Thu Dec 19 18:05:15 2013
@@ -828,6 +828,11 @@ possible configurations would overwhelm
The thread pool always has at least these number of threads so
the REST server is ready to serve incoming requests.</description>
</property>
+ <property>
+ <name>hbase.rest.support.proxyuser</name>
+ <value>false</value>
+ <description>Enables running the REST server to support proxy-user mode.</description>
+ </property>
<property skipInDoc="true">
<name>hbase.defaults.for.version</name>
<value>@@@VERSION@@@</value>
Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServlet.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServlet.java?rev=1552385&r1=1552384&r2=1552385&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServlet.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServlet.java Thu Dec 19 18:05:15 2013
@@ -56,14 +56,17 @@ public class RESTServlet implements Cons
static final String CLEANUP_INTERVAL = "hbase.rest.connection.cleanup-interval";
static final String MAX_IDLETIME = "hbase.rest.connection.max-idletime";
- static final String NULL_USERNAME = "--NULL--";
-
- private final ThreadLocal<String> effectiveUser = new ThreadLocal<String>() {
- protected String initialValue() {
- return NULL_USERNAME;
+ private final ThreadLocal<UserGroupInformation> effectiveUser =
+ new ThreadLocal<UserGroupInformation>() {
+ protected UserGroupInformation initialValue() {
+ return realUser;
}
};
+ UserGroupInformation getRealUser() {
+ return realUser;
+ }
+
// A chore to clean up idle connections.
private final Chore connectionCleaner;
private final Stoppable stoppable;
@@ -192,7 +195,7 @@ public class RESTServlet implements Cons
HBaseAdmin getAdmin() throws IOException {
ConnectionInfo connInfo = getCurrentConnection();
if (connInfo.admin == null) {
- Lock lock = locker.acquireLock(effectiveUser.get());
+ Lock lock = locker.acquireLock(effectiveUser.get().getUserName());
try {
if (connInfo.admin == null) {
connInfo.admin = new HBaseAdmin(connInfo.connection);
@@ -229,23 +232,19 @@ public class RESTServlet implements Cons
return getConfiguration().getBoolean("hbase.rest.readonly", false);
}
- void setEffectiveUser(String effectiveUser) {
+ void setEffectiveUser(UserGroupInformation effectiveUser) {
this.effectiveUser.set(effectiveUser);
}
private ConnectionInfo getCurrentConnection() throws IOException {
- String userName = effectiveUser.get();
+ String userName = effectiveUser.get().getUserName();
ConnectionInfo connInfo = connections.get(userName);
if (connInfo == null || !connInfo.updateAccessTime()) {
Lock lock = locker.acquireLock(userName);
try {
connInfo = connections.get(userName);
if (connInfo == null) {
- UserGroupInformation ugi = realUser;
- if (!userName.equals(NULL_USERNAME)) {
- ugi = UserGroupInformation.createProxyUser(userName, realUser);
- }
- User user = userProvider.create(ugi);
+ User user = userProvider.create(effectiveUser.get());
HConnection conn = HConnectionManager.createConnection(conf, user);
connInfo = new ConnectionInfo(conn, userName);
connections.put(userName, connInfo);
Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServletContainer.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServletContainer.java?rev=1552385&r1=1552384&r2=1552385&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServletContainer.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RESTServletContainer.java Thu Dec 19 18:05:15 2013
@@ -28,6 +28,11 @@ import org.apache.hadoop.classification.
import com.sun.jersey.spi.container.servlet.ServletContainer;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authorize.AuthorizationException;
+import org.apache.hadoop.security.authorize.ProxyUsers;
+import org.apache.hadoop.conf.Configuration;
+
/**
* REST servlet container. It is used to get the remote request user
* without going through @HttpContext, so that we can minimize code changes.
@@ -44,7 +49,29 @@ public class RESTServletContainer extend
@Override
public void service(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException, IOException {
- RESTServlet.getInstance().setEffectiveUser(request.getRemoteUser());
+ final String doAsUserFromQuery = request.getParameter("doAs");
+ Configuration conf = RESTServlet.getInstance().getConfiguration();
+ final boolean proxyConfigured = conf.getBoolean("hbase.rest.support.proxyuser", false);
+ if (doAsUserFromQuery != null && !proxyConfigured) {
+ throw new ServletException("Support for proxyuser is not configured");
+ }
+ UserGroupInformation ugi = RESTServlet.getInstance().getRealUser();
+ if (doAsUserFromQuery != null) {
+ // create and attempt to authorize a proxy user (the client is attempting
+ // to do proxy user)
+ ugi = UserGroupInformation.createProxyUser(doAsUserFromQuery, ugi);
+ // validate the proxy user authorization
+ try {
+ ProxyUsers.authorize(ugi, request.getRemoteAddr(), conf);
+ } catch(AuthorizationException e) {
+ throw new ServletException(e.getMessage());
+ }
+ } else {
+ // the REST server would send the request without validating the proxy
+ // user authorization
+ ugi = UserGroupInformation.createProxyUser(request.getRemoteUser(), ugi);
+ }
+ RESTServlet.getInstance().setEffectiveUser(ugi);
super.service(request, response);
}
}