HBASE-9866. Support the mode where REST server authorizes proxy users

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1552385 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Devaraj Das 2013-12-19 18:05:15 +00:00
parent 9f496164d6
commit 5ef080e8a7
3 changed files with 45 additions and 14 deletions

View File

@ -828,6 +828,11 @@ possible configurations would overwhelm and obscure the important.
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>

View File

@ -56,14 +56,17 @@ public class RESTServlet implements Constants {
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 Constants {
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 Constants {
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);

View File

@ -28,6 +28,11 @@ import org.apache.hadoop.classification.InterfaceAudience;
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 extends ServletContainer {
@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);
}
}