HDFS-7420. Delegate permission checks to FSDirectory. Contributed by Haohui Mai.

This commit is contained in:
Haohui Mai 2014-11-21 11:01:14 -08:00
parent e9db0aa35c
commit b395f58e85
4 changed files with 95 additions and 30 deletions

View File

@ -126,6 +126,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

View File

@ -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 ?
@ -3333,4 +3343,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();
}
}
}
} }

View File

@ -392,7 +392,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;
@ -766,7 +765,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
@ -6470,30 +6464,17 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
String path, boolean doCheckOwner, FsAction ancestorAccess, String path, boolean doCheckOwner, FsAction ancestorAccess,
FsAction parentAccess, FsAction access, FsAction subAccess) FsAction parentAccess, FsAction access, FsAction subAccess)
throws AccessControlException, UnresolvedLinkException { throws AccessControlException, UnresolvedLinkException {
checkPermission(pc, path, doCheckOwner, ancestorAccess, checkPermission(pc, path, doCheckOwner, ancestorAccess,
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();
}
}
} }
/** /**

View File

@ -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() {