HDFS-16259. Catch and re-throw sub-classes of AccessControlException thrown by any permission provider plugins (eg Ranger) (#3598)
This commit is contained in:
parent
618fea27d2
commit
2f35cc36cd
|
@ -273,31 +273,41 @@ public class FSPermissionChecker implements AccessControlEnforcer {
|
||||||
AccessControlEnforcer enforcer = getAccessControlEnforcer();
|
AccessControlEnforcer enforcer = getAccessControlEnforcer();
|
||||||
|
|
||||||
String opType = operationType.get();
|
String opType = operationType.get();
|
||||||
if (this.authorizeWithContext && opType != null) {
|
try {
|
||||||
INodeAttributeProvider.AuthorizationContext.Builder builder =
|
if (this.authorizeWithContext && opType != null) {
|
||||||
new INodeAttributeProvider.AuthorizationContext.Builder();
|
INodeAttributeProvider.AuthorizationContext.Builder builder =
|
||||||
builder.fsOwner(fsOwner).
|
new INodeAttributeProvider.AuthorizationContext.Builder();
|
||||||
supergroup(supergroup).
|
builder.fsOwner(fsOwner).
|
||||||
callerUgi(callerUgi).
|
supergroup(supergroup).
|
||||||
inodeAttrs(inodeAttrs).
|
callerUgi(callerUgi).
|
||||||
inodes(inodes).
|
inodeAttrs(inodeAttrs).
|
||||||
pathByNameArr(components).
|
inodes(inodes).
|
||||||
snapshotId(snapshotId).
|
pathByNameArr(components).
|
||||||
path(path).
|
snapshotId(snapshotId).
|
||||||
ancestorIndex(ancestorIndex).
|
path(path).
|
||||||
doCheckOwner(doCheckOwner).
|
ancestorIndex(ancestorIndex).
|
||||||
ancestorAccess(ancestorAccess).
|
doCheckOwner(doCheckOwner).
|
||||||
parentAccess(parentAccess).
|
ancestorAccess(ancestorAccess).
|
||||||
access(access).
|
parentAccess(parentAccess).
|
||||||
subAccess(subAccess).
|
access(access).
|
||||||
ignoreEmptyDir(ignoreEmptyDir).
|
subAccess(subAccess).
|
||||||
operationName(opType).
|
ignoreEmptyDir(ignoreEmptyDir).
|
||||||
callerContext(CallerContext.getCurrent());
|
operationName(opType).
|
||||||
enforcer.checkPermissionWithContext(builder.build());
|
callerContext(CallerContext.getCurrent());
|
||||||
} else {
|
enforcer.checkPermissionWithContext(builder.build());
|
||||||
enforcer.checkPermission(fsOwner, supergroup, callerUgi, inodeAttrs,
|
} else {
|
||||||
inodes, components, snapshotId, path, ancestorIndex, doCheckOwner,
|
enforcer.checkPermission(fsOwner, supergroup, callerUgi, inodeAttrs,
|
||||||
ancestorAccess, parentAccess, access, subAccess, ignoreEmptyDir);
|
inodes, components, snapshotId, path, ancestorIndex, doCheckOwner,
|
||||||
|
ancestorAccess, parentAccess, access, subAccess, ignoreEmptyDir);
|
||||||
|
}
|
||||||
|
} catch (AccessControlException ace) {
|
||||||
|
Class<?> exceptionClass = ace.getClass();
|
||||||
|
if (exceptionClass.equals(AccessControlException.class)
|
||||||
|
|| exceptionClass.equals(TraverseAccessControlException.class)) {
|
||||||
|
throw ace;
|
||||||
|
}
|
||||||
|
// Only form a new ACE for subclasses which come from external enforcers
|
||||||
|
throw new AccessControlException(ace);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
public class TestINodeAttributeProvider {
|
public class TestINodeAttributeProvider {
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
LoggerFactory.getLogger(TestINodeAttributeProvider.class);
|
LoggerFactory.getLogger(TestINodeAttributeProvider.class);
|
||||||
|
@ -57,6 +59,15 @@ public class TestINodeAttributeProvider {
|
||||||
private static final short HDFS_PERMISSION = 0777;
|
private static final short HDFS_PERMISSION = 0777;
|
||||||
private static final short PROVIDER_PERMISSION = 0770;
|
private static final short PROVIDER_PERMISSION = 0770;
|
||||||
private static boolean runPermissionCheck = false;
|
private static boolean runPermissionCheck = false;
|
||||||
|
private static boolean shouldThrowAccessException = false;
|
||||||
|
|
||||||
|
public static class MyAuthorizationProviderAccessException
|
||||||
|
extends AccessControlException {
|
||||||
|
|
||||||
|
public MyAuthorizationProviderAccessException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public static class MyAuthorizationProvider extends INodeAttributeProvider {
|
public static class MyAuthorizationProvider extends INodeAttributeProvider {
|
||||||
|
|
||||||
|
@ -82,6 +93,9 @@ public class TestINodeAttributeProvider {
|
||||||
ancestorAccess, parentAccess, access, subAccess, ignoreEmptyDir);
|
ancestorAccess, parentAccess, access, subAccess, ignoreEmptyDir);
|
||||||
}
|
}
|
||||||
CALLED.add("checkPermission|" + ancestorAccess + "|" + parentAccess + "|" + access);
|
CALLED.add("checkPermission|" + ancestorAccess + "|" + parentAccess + "|" + access);
|
||||||
|
if (shouldThrowAccessException) {
|
||||||
|
throw new MyAuthorizationProviderAccessException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -96,6 +110,9 @@ public class TestINodeAttributeProvider {
|
||||||
CALLED.add("checkPermission|" + authzContext.getAncestorAccess()
|
CALLED.add("checkPermission|" + authzContext.getAncestorAccess()
|
||||||
+ "|" + authzContext.getParentAccess() + "|" + authzContext
|
+ "|" + authzContext.getParentAccess() + "|" + authzContext
|
||||||
.getAccess());
|
.getAccess());
|
||||||
|
if (shouldThrowAccessException) {
|
||||||
|
throw new MyAuthorizationProviderAccessException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +255,7 @@ public class TestINodeAttributeProvider {
|
||||||
miniDFS = null;
|
miniDFS = null;
|
||||||
}
|
}
|
||||||
runPermissionCheck = false;
|
runPermissionCheck = false;
|
||||||
|
shouldThrowAccessException = false;
|
||||||
Assert.assertTrue(CALLED.contains("stop"));
|
Assert.assertTrue(CALLED.contains("stop"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +475,44 @@ public class TestINodeAttributeProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// HDFS-16529 - Ensure enforcer AccessControlException subclass are caught
|
||||||
|
// and re-thrown as plain ACE exceptions.
|
||||||
|
public void testSubClassedAccessControlExceptions() throws Exception {
|
||||||
|
FileSystem fs = FileSystem.get(miniDFS.getConfiguration(0));
|
||||||
|
shouldThrowAccessException = true;
|
||||||
|
final Path userPath = new Path("/user");
|
||||||
|
final Path authz = new Path("/user/authz");
|
||||||
|
final Path authzChild = new Path("/user/authz/child2");
|
||||||
|
|
||||||
|
fs.mkdirs(userPath);
|
||||||
|
fs.setPermission(userPath, new FsPermission(HDFS_PERMISSION));
|
||||||
|
fs.mkdirs(authz);
|
||||||
|
fs.setPermission(authz, new FsPermission(HDFS_PERMISSION));
|
||||||
|
fs.mkdirs(authzChild);
|
||||||
|
fs.setPermission(authzChild, new FsPermission(HDFS_PERMISSION));
|
||||||
|
UserGroupInformation ugi = UserGroupInformation.createUserForTesting("u1",
|
||||||
|
new String[]{"g1"});
|
||||||
|
ugi.doAs(new PrivilegedExceptionAction<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void run() throws Exception {
|
||||||
|
FileSystem fs = FileSystem.get(miniDFS.getConfiguration(0));
|
||||||
|
try {
|
||||||
|
fs.access(authzChild, FsAction.ALL);
|
||||||
|
fail("Exception should be thrown");
|
||||||
|
// The DFS Client will get a RemoteException containing an
|
||||||
|
// AccessControlException (ACE). If the ACE is a subclass of ACE then
|
||||||
|
// the client does not unwrap it correctly. The change in HDFS-16529
|
||||||
|
// is to ensure ACE is always thrown rather than a sub class to avoid
|
||||||
|
// this issue.
|
||||||
|
} catch (AccessControlException ace) {
|
||||||
|
Assert.assertEquals(AccessControlException.class, ace.getClass());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
// HDFS-15165 - ContentSummary calls should use the provider permissions(if
|
// HDFS-15165 - ContentSummary calls should use the provider permissions(if
|
||||||
|
|
Loading…
Reference in New Issue