HDFS-10481. HTTPFS server should correctly impersonate as end user to open file. Contributed by Xiao Chen.
This commit is contained in:
parent
99a771cd7a
commit
47e0321ee9
|
@ -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
|
||||||
|
@ -205,115 +207,123 @@ public class HttpFSServer {
|
||||||
MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name());
|
MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name());
|
||||||
MDC.put("hostname", request.getRemoteAddr());
|
MDC.put("hostname", request.getRemoteAddr());
|
||||||
switch (op.value()) {
|
switch (op.value()) {
|
||||||
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;
|
||||||
Long offset = params.get(OffsetParam.NAME, OffsetParam.class);
|
UserGroupInformation ugi = UserGroupInformation
|
||||||
Long len = params.get(LenParam.NAME, LenParam.class);
|
.createProxyUser(user.getShortUserName(),
|
||||||
AUDIT_LOG.info("[{}] offset [{}] len [{}]",
|
UserGroupInformation.getLoginUser());
|
||||||
new Object[]{path, offset, len});
|
try {
|
||||||
InputStreamEntity entity = new InputStreamEntity(is, offset, len);
|
is = ugi.doAs(new PrivilegedExceptionAction<InputStream>() {
|
||||||
response =
|
@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 len = params.get(LenParam.NAME, LenParam.class);
|
||||||
|
AUDIT_LOG.info("[{}] offset [{}] len [{}]",
|
||||||
|
new Object[] { path, offset, len });
|
||||||
|
InputStreamEntity entity = new InputStreamEntity(is, offset, len);
|
||||||
|
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();
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case LISTSTATUS: {
|
||||||
case LISTSTATUS: {
|
String filter = params.get(FilterParam.NAME, FilterParam.class);
|
||||||
String filter = params.get(FilterParam.NAME, FilterParam.class);
|
FSOperations.FSListStatus command =
|
||||||
FSOperations.FSListStatus command = new FSOperations.FSListStatus(
|
new FSOperations.FSListStatus(path, filter);
|
||||||
path, filter);
|
Map json = fsExecute(user, command);
|
||||||
Map json = fsExecute(user, command);
|
AUDIT_LOG.info("[{}] filter [{}]", path, (filter != null) ? filter : "-");
|
||||||
AUDIT_LOG.info("[{}] filter [{}]", path,
|
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
||||||
(filter != null) ? filter : "-");
|
break;
|
||||||
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
}
|
||||||
break;
|
case GETHOMEDIRECTORY: {
|
||||||
}
|
enforceRootPath(op.value(), path);
|
||||||
case GETHOMEDIRECTORY: {
|
FSOperations.FSHomeDir command = new FSOperations.FSHomeDir();
|
||||||
enforceRootPath(op.value(), path);
|
JSONObject json = fsExecute(user, command);
|
||||||
FSOperations.FSHomeDir command = new FSOperations.FSHomeDir();
|
AUDIT_LOG.info("");
|
||||||
JSONObject json = fsExecute(user, command);
|
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
||||||
AUDIT_LOG.info("");
|
break;
|
||||||
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
}
|
||||||
break;
|
case INSTRUMENTATION: {
|
||||||
}
|
enforceRootPath(op.value(), path);
|
||||||
case INSTRUMENTATION: {
|
Groups groups = HttpFSServerWebApp.get().get(Groups.class);
|
||||||
enforceRootPath(op.value(), path);
|
List<String> userGroups = groups.getGroups(user.getShortUserName());
|
||||||
Groups groups = HttpFSServerWebApp.get().get(Groups.class);
|
if (!userGroups.contains(HttpFSServerWebApp.get().getAdminGroup())) {
|
||||||
List<String> userGroups = groups.getGroups(user.getShortUserName());
|
throw new AccessControlException(
|
||||||
if (!userGroups.contains(HttpFSServerWebApp.get().getAdminGroup())) {
|
|
||||||
throw new AccessControlException(
|
|
||||||
"User not in HttpFSServer admin group");
|
"User not in HttpFSServer admin group");
|
||||||
}
|
}
|
||||||
Instrumentation instrumentation =
|
Instrumentation instrumentation =
|
||||||
HttpFSServerWebApp.get().get(Instrumentation.class);
|
HttpFSServerWebApp.get().get(Instrumentation.class);
|
||||||
Map snapshot = instrumentation.getSnapshot();
|
Map snapshot = instrumentation.getSnapshot();
|
||||||
response = Response.ok(snapshot).build();
|
response = Response.ok(snapshot).build();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GETCONTENTSUMMARY: {
|
case GETCONTENTSUMMARY: {
|
||||||
FSOperations.FSContentSummary command =
|
FSOperations.FSContentSummary command =
|
||||||
new FSOperations.FSContentSummary(path);
|
new FSOperations.FSContentSummary(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();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GETFILECHECKSUM: {
|
case GETFILECHECKSUM: {
|
||||||
FSOperations.FSFileChecksum command =
|
FSOperations.FSFileChecksum command =
|
||||||
new FSOperations.FSFileChecksum(path);
|
new FSOperations.FSFileChecksum(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();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GETFILEBLOCKLOCATIONS: {
|
case GETFILEBLOCKLOCATIONS: {
|
||||||
response = Response.status(Response.Status.BAD_REQUEST).build();
|
response = Response.status(Response.Status.BAD_REQUEST).build();
|
||||||
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 =
|
||||||
List<String> xattrNames = params.getValues(XAttrNameParam.NAME,
|
params.getValues(XAttrNameParam.NAME, XAttrNameParam.class);
|
||||||
XAttrNameParam.class);
|
XAttrCodec encoding =
|
||||||
XAttrCodec encoding = params.get(XAttrEncodingParam.NAME,
|
params.get(XAttrEncodingParam.NAME, XAttrEncodingParam.class);
|
||||||
XAttrEncodingParam.class);
|
FSOperations.FSGetXAttrs command =
|
||||||
FSOperations.FSGetXAttrs command = new FSOperations.FSGetXAttrs(path,
|
new FSOperations.FSGetXAttrs(path, xattrNames, encoding);
|
||||||
xattrNames, encoding);
|
@SuppressWarnings("rawtypes") Map json = fsExecute(user, command);
|
||||||
@SuppressWarnings("rawtypes")
|
AUDIT_LOG.info("XAttrs for [{}]", path);
|
||||||
Map json = fsExecute(user, command);
|
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
||||||
AUDIT_LOG.info("XAttrs for [{}]", path);
|
break;
|
||||||
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
}
|
||||||
break;
|
case LISTXATTRS: {
|
||||||
}
|
FSOperations.FSListXAttrs command = new FSOperations.FSListXAttrs(path);
|
||||||
case LISTXATTRS: {
|
@SuppressWarnings("rawtypes") Map json = fsExecute(user, command);
|
||||||
FSOperations.FSListXAttrs command = new FSOperations.FSListXAttrs(path);
|
AUDIT_LOG.info("XAttr names for [{}]", path);
|
||||||
@SuppressWarnings("rawtypes")
|
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
||||||
Map json = fsExecute(user, command);
|
break;
|
||||||
AUDIT_LOG.info("XAttr names for [{}]", path);
|
}
|
||||||
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
default: {
|
||||||
break;
|
throw new IOException(
|
||||||
}
|
MessageFormat.format("Invalid HTTP GET operation [{0}]", op.value()));
|
||||||
default: {
|
}
|
||||||
throw new IOException(
|
|
||||||
MessageFormat.format("Invalid HTTP GET operation [{0}]",
|
|
||||||
op.value()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue