HDFS-10481. HTTPFS server should correctly impersonate as end user to open file. Contributed by Xiao Chen.

This commit is contained in:
Andrew Wang 2016-06-03 17:21:17 -07:00
parent 99a771cd7a
commit 47e0321ee9
1 changed files with 114 additions and 104 deletions

View File

@ -79,6 +79,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.security.AccessControlException; import java.security.AccessControlException;
import java.security.PrivilegedExceptionAction;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
@ -94,6 +95,7 @@ import java.util.Map;
@InterfaceAudience.Private @InterfaceAudience.Private
public class HttpFSServer { public class HttpFSServer {
private static Logger AUDIT_LOG = LoggerFactory.getLogger("httpfsaudit"); private static Logger AUDIT_LOG = LoggerFactory.getLogger("httpfsaudit");
private static final Logger LOG = LoggerFactory.getLogger(HttpFSServer.class);
/** /**
* Executes a {@link FileSystemAccess.FileSystemExecutor} using a filesystem for the effective * Executes a {@link FileSystemAccess.FileSystemExecutor} using a filesystem for the effective
@ -208,21 +210,34 @@ public class HttpFSServer {
case OPEN: { case OPEN: {
//Invoking the command directly using an unmanaged FileSystem that is //Invoking the command directly using an unmanaged FileSystem that is
// released by the FileSystemReleaseFilter // released by the FileSystemReleaseFilter
FSOperations.FSOpen command = new FSOperations.FSOpen(path); final FSOperations.FSOpen command = new FSOperations.FSOpen(path);
FileSystem fs = createFileSystem(user); final FileSystem fs = createFileSystem(user);
InputStream is = command.execute(fs); InputStream is = null;
UserGroupInformation ugi = UserGroupInformation
.createProxyUser(user.getShortUserName(),
UserGroupInformation.getLoginUser());
try {
is = ugi.doAs(new PrivilegedExceptionAction<InputStream>() {
@Override
public InputStream run() throws Exception {
return command.execute(fs);
}
});
} catch (InterruptedException ie) {
LOG.info("Open interrupted.", ie);
Thread.currentThread().interrupt();
}
Long offset = params.get(OffsetParam.NAME, OffsetParam.class); Long offset = params.get(OffsetParam.NAME, OffsetParam.class);
Long len = params.get(LenParam.NAME, LenParam.class); Long len = params.get(LenParam.NAME, LenParam.class);
AUDIT_LOG.info("[{}] offset [{}] len [{}]", AUDIT_LOG.info("[{}] offset [{}] len [{}]",
new Object[]{path, offset, len}); new Object[] { path, offset, len });
InputStreamEntity entity = new InputStreamEntity(is, offset, len); InputStreamEntity entity = new InputStreamEntity(is, offset, len);
response = response =
Response.ok(entity).type(MediaType.APPLICATION_OCTET_STREAM).build(); Response.ok(entity).type(MediaType.APPLICATION_OCTET_STREAM).build();
break; break;
} }
case GETFILESTATUS: { case GETFILESTATUS: {
FSOperations.FSFileStatus command = FSOperations.FSFileStatus command = new FSOperations.FSFileStatus(path);
new FSOperations.FSFileStatus(path);
Map json = fsExecute(user, command); Map json = fsExecute(user, command);
AUDIT_LOG.info("[{}]", path); AUDIT_LOG.info("[{}]", path);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
@ -230,11 +245,10 @@ public class HttpFSServer {
} }
case LISTSTATUS: { case LISTSTATUS: {
String filter = params.get(FilterParam.NAME, FilterParam.class); String filter = params.get(FilterParam.NAME, FilterParam.class);
FSOperations.FSListStatus command = new FSOperations.FSListStatus( FSOperations.FSListStatus command =
path, filter); new FSOperations.FSListStatus(path, filter);
Map json = fsExecute(user, command); Map json = fsExecute(user, command);
AUDIT_LOG.info("[{}] filter [{}]", path, AUDIT_LOG.info("[{}] filter [{}]", path, (filter != null) ? filter : "-");
(filter != null) ? filter : "-");
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
break; break;
} }
@ -281,38 +295,34 @@ public class HttpFSServer {
break; break;
} }
case GETACLSTATUS: { case GETACLSTATUS: {
FSOperations.FSAclStatus command = FSOperations.FSAclStatus command = new FSOperations.FSAclStatus(path);
new FSOperations.FSAclStatus(path);
Map json = fsExecute(user, command); Map json = fsExecute(user, command);
AUDIT_LOG.info("ACL status for [{}]", path); AUDIT_LOG.info("ACL status for [{}]", path);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
break; break;
} }
case GETXATTRS: { case GETXATTRS: {
List<String> xattrNames = params.getValues(XAttrNameParam.NAME, List<String> xattrNames =
XAttrNameParam.class); params.getValues(XAttrNameParam.NAME, XAttrNameParam.class);
XAttrCodec encoding = params.get(XAttrEncodingParam.NAME, XAttrCodec encoding =
XAttrEncodingParam.class); params.get(XAttrEncodingParam.NAME, XAttrEncodingParam.class);
FSOperations.FSGetXAttrs command = new FSOperations.FSGetXAttrs(path, FSOperations.FSGetXAttrs command =
xattrNames, encoding); new FSOperations.FSGetXAttrs(path, xattrNames, encoding);
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes") Map json = fsExecute(user, command);
Map json = fsExecute(user, command);
AUDIT_LOG.info("XAttrs for [{}]", path); AUDIT_LOG.info("XAttrs for [{}]", path);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
break; break;
} }
case LISTXATTRS: { case LISTXATTRS: {
FSOperations.FSListXAttrs command = new FSOperations.FSListXAttrs(path); FSOperations.FSListXAttrs command = new FSOperations.FSListXAttrs(path);
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes") Map json = fsExecute(user, command);
Map json = fsExecute(user, command);
AUDIT_LOG.info("XAttr names for [{}]", path); AUDIT_LOG.info("XAttr names for [{}]", path);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
break; break;
} }
default: { default: {
throw new IOException( throw new IOException(
MessageFormat.format("Invalid HTTP GET operation [{0}]", MessageFormat.format("Invalid HTTP GET operation [{0}]", op.value()));
op.value()));
} }
} }
return response; return response;