HDFS-7420. Delegate permission checks to FSDirectory. Contributed by Haohui Mai.
This commit is contained in:
parent
3114d4731d
commit
23dacb3892
|
@ -383,6 +383,8 @@ Release 2.7.0 - UNRELEASED
|
||||||
|
|
||||||
HDFS-7415. Move FSNameSystem.resolvePath() to FSDirectory. (wheat9)
|
HDFS-7415. Move FSNameSystem.resolvePath() to FSDirectory. (wheat9)
|
||||||
|
|
||||||
|
HDFS-7420. Delegate permission checks to FSDirectory. (wheat9)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
|
|
@ -52,6 +52,7 @@ import org.apache.hadoop.fs.XAttr;
|
||||||
import org.apache.hadoop.fs.XAttrSetFlag;
|
import org.apache.hadoop.fs.XAttrSetFlag;
|
||||||
import org.apache.hadoop.fs.permission.AclEntry;
|
import org.apache.hadoop.fs.permission.AclEntry;
|
||||||
import org.apache.hadoop.fs.permission.AclStatus;
|
import org.apache.hadoop.fs.permission.AclStatus;
|
||||||
|
import org.apache.hadoop.fs.permission.FsAction;
|
||||||
import org.apache.hadoop.fs.permission.FsPermission;
|
import org.apache.hadoop.fs.permission.FsPermission;
|
||||||
import org.apache.hadoop.fs.permission.PermissionStatus;
|
import org.apache.hadoop.fs.permission.PermissionStatus;
|
||||||
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
||||||
|
@ -96,6 +97,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.apache.hadoop.security.AccessControlException;
|
import org.apache.hadoop.security.AccessControlException;
|
||||||
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Both FSDirectory and FSNamesystem manage the state of the namespace.
|
* Both FSDirectory and FSNamesystem manage the state of the namespace.
|
||||||
|
@ -152,6 +154,8 @@ public class FSDirectory implements Closeable {
|
||||||
private final ReentrantReadWriteLock dirLock;
|
private final ReentrantReadWriteLock dirLock;
|
||||||
|
|
||||||
private final boolean isPermissionEnabled;
|
private final boolean isPermissionEnabled;
|
||||||
|
private final String fsOwnerShortUserName;
|
||||||
|
private final String supergroup;
|
||||||
|
|
||||||
// utility methods to acquire and release read lock and write lock
|
// utility methods to acquire and release read lock and write lock
|
||||||
void readLock() {
|
void readLock() {
|
||||||
|
@ -195,13 +199,19 @@ public class FSDirectory implements Closeable {
|
||||||
*/
|
*/
|
||||||
private final NameCache<ByteArray> nameCache;
|
private final NameCache<ByteArray> nameCache;
|
||||||
|
|
||||||
FSDirectory(FSNamesystem ns, Configuration conf) {
|
FSDirectory(FSNamesystem ns, Configuration conf) throws IOException {
|
||||||
this.dirLock = new ReentrantReadWriteLock(true); // fair
|
this.dirLock = new ReentrantReadWriteLock(true); // fair
|
||||||
rootDir = createRoot(ns);
|
rootDir = createRoot(ns);
|
||||||
inodeMap = INodeMap.newInstance(rootDir);
|
inodeMap = INodeMap.newInstance(rootDir);
|
||||||
this.isPermissionEnabled = conf.getBoolean(
|
this.isPermissionEnabled = conf.getBoolean(
|
||||||
DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY,
|
DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY,
|
||||||
DFSConfigKeys.DFS_PERMISSIONS_ENABLED_DEFAULT);
|
DFSConfigKeys.DFS_PERMISSIONS_ENABLED_DEFAULT);
|
||||||
|
this.fsOwnerShortUserName =
|
||||||
|
UserGroupInformation.getCurrentUser().getShortUserName();
|
||||||
|
this.supergroup = conf.get(
|
||||||
|
DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_KEY,
|
||||||
|
DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_DEFAULT);
|
||||||
|
|
||||||
int configuredLimit = conf.getInt(
|
int configuredLimit = conf.getInt(
|
||||||
DFSConfigKeys.DFS_LIST_LIMIT, DFSConfigKeys.DFS_LIST_LIMIT_DEFAULT);
|
DFSConfigKeys.DFS_LIST_LIMIT, DFSConfigKeys.DFS_LIST_LIMIT_DEFAULT);
|
||||||
this.lsLimit = configuredLimit>0 ?
|
this.lsLimit = configuredLimit>0 ?
|
||||||
|
@ -3331,4 +3341,76 @@ public class FSDirectory implements Closeable {
|
||||||
}
|
}
|
||||||
return inodesInPath;
|
return inodesInPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSPermissionChecker getPermissionChecker()
|
||||||
|
throws AccessControlException {
|
||||||
|
try {
|
||||||
|
return new FSPermissionChecker(fsOwnerShortUserName, supergroup,
|
||||||
|
NameNode.getRemoteUser());
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new AccessControlException(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkOwner(FSPermissionChecker pc, String path)
|
||||||
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
|
checkPermission(pc, path, true, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkPathAccess(FSPermissionChecker pc, String path,
|
||||||
|
FsAction access)
|
||||||
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
|
checkPermission(pc, path, false, null, null, access, null);
|
||||||
|
}
|
||||||
|
void checkParentAccess(
|
||||||
|
FSPermissionChecker pc, String path, FsAction access)
|
||||||
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
|
checkPermission(pc, path, false, null, access, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkAncestorAccess(
|
||||||
|
FSPermissionChecker pc, String path, FsAction access)
|
||||||
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
|
checkPermission(pc, path, false, access, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkTraverse(FSPermissionChecker pc, String path)
|
||||||
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
|
checkPermission(pc, path, false, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether current user have permissions to access the path. For more
|
||||||
|
* details of the parameters, see
|
||||||
|
* {@link FSPermissionChecker#checkPermission}.
|
||||||
|
*/
|
||||||
|
private void checkPermission(
|
||||||
|
FSPermissionChecker pc, String path, boolean doCheckOwner,
|
||||||
|
FsAction ancestorAccess, FsAction parentAccess, FsAction access,
|
||||||
|
FsAction subAccess)
|
||||||
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
|
checkPermission(pc, path, doCheckOwner, ancestorAccess,
|
||||||
|
parentAccess, access, subAccess, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether current user have permissions to access the path. For more
|
||||||
|
* details of the parameters, see
|
||||||
|
* {@link FSPermissionChecker#checkPermission}.
|
||||||
|
*/
|
||||||
|
void checkPermission(
|
||||||
|
FSPermissionChecker pc, String path, boolean doCheckOwner,
|
||||||
|
FsAction ancestorAccess, FsAction parentAccess, FsAction access,
|
||||||
|
FsAction subAccess, boolean ignoreEmptyDir, boolean resolveLink)
|
||||||
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
|
if (!pc.isSuperUser()) {
|
||||||
|
readLock();
|
||||||
|
try {
|
||||||
|
pc.checkPermission(path, this, doCheckOwner, ancestorAccess,
|
||||||
|
parentAccess, access, subAccess, ignoreEmptyDir, resolveLink);
|
||||||
|
} finally {
|
||||||
|
readUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -404,7 +404,6 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
static int BLOCK_DELETION_INCREMENT = 1000;
|
static int BLOCK_DELETION_INCREMENT = 1000;
|
||||||
private final boolean isPermissionEnabled;
|
private final boolean isPermissionEnabled;
|
||||||
private final UserGroupInformation fsOwner;
|
private final UserGroupInformation fsOwner;
|
||||||
private final String fsOwnerShortUserName;
|
|
||||||
private final String supergroup;
|
private final String supergroup;
|
||||||
private final boolean standbyShouldCheckpoint;
|
private final boolean standbyShouldCheckpoint;
|
||||||
|
|
||||||
|
@ -777,7 +776,6 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
DFS_STORAGE_POLICY_ENABLED_DEFAULT);
|
DFS_STORAGE_POLICY_ENABLED_DEFAULT);
|
||||||
|
|
||||||
this.fsOwner = UserGroupInformation.getCurrentUser();
|
this.fsOwner = UserGroupInformation.getCurrentUser();
|
||||||
this.fsOwnerShortUserName = fsOwner.getShortUserName();
|
|
||||||
this.supergroup = conf.get(DFS_PERMISSIONS_SUPERUSERGROUP_KEY,
|
this.supergroup = conf.get(DFS_PERMISSIONS_SUPERUSERGROUP_KEY,
|
||||||
DFS_PERMISSIONS_SUPERUSERGROUP_DEFAULT);
|
DFS_PERMISSIONS_SUPERUSERGROUP_DEFAULT);
|
||||||
this.isPermissionEnabled = conf.getBoolean(DFS_PERMISSIONS_ENABLED_KEY,
|
this.isPermissionEnabled = conf.getBoolean(DFS_PERMISSIONS_ENABLED_KEY,
|
||||||
|
@ -3922,11 +3920,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
|
|
||||||
private FSPermissionChecker getPermissionChecker()
|
private FSPermissionChecker getPermissionChecker()
|
||||||
throws AccessControlException {
|
throws AccessControlException {
|
||||||
try {
|
return dir.getPermissionChecker();
|
||||||
return new FSPermissionChecker(fsOwnerShortUserName, supergroup, getRemoteUser());
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new AccessControlException(ioe);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6411,13 +6405,13 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
|
|
||||||
private void checkOwner(FSPermissionChecker pc, String path)
|
private void checkOwner(FSPermissionChecker pc, String path)
|
||||||
throws AccessControlException, UnresolvedLinkException {
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
checkPermission(pc, path, true, null, null, null, null);
|
dir.checkOwner(pc, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPathAccess(FSPermissionChecker pc,
|
private void checkPathAccess(FSPermissionChecker pc,
|
||||||
String path, FsAction access) throws AccessControlException,
|
String path, FsAction access) throws AccessControlException,
|
||||||
UnresolvedLinkException {
|
UnresolvedLinkException {
|
||||||
checkPermission(pc, path, false, null, null, access, null);
|
dir.checkPathAccess(pc, path, access);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkUnreadableBySuperuser(FSPermissionChecker pc,
|
private void checkUnreadableBySuperuser(FSPermissionChecker pc,
|
||||||
|
@ -6438,18 +6432,18 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
private void checkParentAccess(FSPermissionChecker pc,
|
private void checkParentAccess(FSPermissionChecker pc,
|
||||||
String path, FsAction access) throws AccessControlException,
|
String path, FsAction access) throws AccessControlException,
|
||||||
UnresolvedLinkException {
|
UnresolvedLinkException {
|
||||||
checkPermission(pc, path, false, null, access, null, null);
|
dir.checkParentAccess(pc, path, access);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAncestorAccess(FSPermissionChecker pc,
|
private void checkAncestorAccess(FSPermissionChecker pc,
|
||||||
String path, FsAction access) throws AccessControlException,
|
String path, FsAction access) throws AccessControlException,
|
||||||
UnresolvedLinkException {
|
UnresolvedLinkException {
|
||||||
checkPermission(pc, path, false, access, null, null, null);
|
dir.checkAncestorAccess(pc, path, access);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkTraverse(FSPermissionChecker pc, String path)
|
private void checkTraverse(FSPermissionChecker pc, String path)
|
||||||
throws AccessControlException, UnresolvedLinkException {
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
checkPermission(pc, path, false, null, null, null, null);
|
dir.checkTraverse(pc, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -6474,26 +6468,13 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
parentAccess, access, subAccess, false, true);
|
parentAccess, access, subAccess, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether current user have permissions to access the path. For more
|
|
||||||
* details of the parameters, see
|
|
||||||
* {@link FSPermissionChecker#checkPermission}.
|
|
||||||
*/
|
|
||||||
private void checkPermission(FSPermissionChecker pc,
|
private void checkPermission(FSPermissionChecker pc,
|
||||||
String path, boolean doCheckOwner, FsAction ancestorAccess,
|
String path, boolean doCheckOwner, FsAction ancestorAccess,
|
||||||
FsAction parentAccess, FsAction access, FsAction subAccess,
|
FsAction parentAccess, FsAction access, FsAction subAccess,
|
||||||
boolean ignoreEmptyDir, boolean resolveLink)
|
boolean ignoreEmptyDir, boolean resolveLink)
|
||||||
throws AccessControlException, UnresolvedLinkException {
|
throws AccessControlException, UnresolvedLinkException {
|
||||||
if (!pc.isSuperUser()) {
|
dir.checkPermission(pc, path, doCheckOwner, ancestorAccess, parentAccess,
|
||||||
waitForLoadingFSImage();
|
access, subAccess, ignoreEmptyDir, resolveLink);
|
||||||
readLock();
|
|
||||||
try {
|
|
||||||
pc.checkPermission(path, dir, doCheckOwner, ancestorAccess,
|
|
||||||
parentAccess, access, subAccess, ignoreEmptyDir, resolveLink);
|
|
||||||
} finally {
|
|
||||||
readUnlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class TestFSPermissionChecker {
|
||||||
private INodeDirectory inodeRoot;
|
private INodeDirectory inodeRoot;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() throws IOException {
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
FSNamesystem fsn = mock(FSNamesystem.class);
|
FSNamesystem fsn = mock(FSNamesystem.class);
|
||||||
doAnswer(new Answer() {
|
doAnswer(new Answer() {
|
||||||
|
|
Loading…
Reference in New Issue