use of org.apache.hadoop.fs.permission.FsAction in project hadoop by apache.
the class FileUtil method setPermission.
/**
* Set permissions to the required value. Uses the java primitives instead
* of forking if group == other.
* @param f the file to change
* @param permission the new permissions
* @throws IOException
*/
public static void setPermission(File f, FsPermission permission) throws IOException {
FsAction user = permission.getUserAction();
FsAction group = permission.getGroupAction();
FsAction other = permission.getOtherAction();
// or if the native is available or on Windows
if (group != other || NativeIO.isAvailable() || Shell.WINDOWS) {
execSetPermission(f, permission);
return;
}
boolean rv = true;
// read perms
rv = f.setReadable(group.implies(FsAction.READ), false);
checkReturnValue(rv, f, permission);
if (group.implies(FsAction.READ) != user.implies(FsAction.READ)) {
rv = f.setReadable(user.implies(FsAction.READ), true);
checkReturnValue(rv, f, permission);
}
// write perms
rv = f.setWritable(group.implies(FsAction.WRITE), false);
checkReturnValue(rv, f, permission);
if (group.implies(FsAction.WRITE) != user.implies(FsAction.WRITE)) {
rv = f.setWritable(user.implies(FsAction.WRITE), true);
checkReturnValue(rv, f, permission);
}
// exec perms
rv = f.setExecutable(group.implies(FsAction.EXECUTE), false);
checkReturnValue(rv, f, permission);
if (group.implies(FsAction.EXECUTE) != user.implies(FsAction.EXECUTE)) {
rv = f.setExecutable(user.implies(FsAction.EXECUTE), true);
checkReturnValue(rv, f, permission);
}
}
use of org.apache.hadoop.fs.permission.FsAction in project hadoop by apache.
the class AclStorage method copyINodeDefaultAcl.
/**
* If a default ACL is defined on a parent directory, then copies that default
* ACL to a newly created child file or directory.
*
* @param child INode newly created child
*/
public static boolean copyINodeDefaultAcl(INode child) {
INodeDirectory parent = child.getParent();
AclFeature parentAclFeature = parent.getAclFeature();
if (parentAclFeature == null || !(child.isFile() || child.isDirectory())) {
return false;
}
// Split parent's entries into access vs. default.
List<AclEntry> featureEntries = getEntriesFromAclFeature(parent.getAclFeature());
ScopedAclEntries scopedEntries = new ScopedAclEntries(featureEntries);
List<AclEntry> parentDefaultEntries = scopedEntries.getDefaultEntries();
// The parent may have an access ACL but no default ACL. If so, exit.
if (parentDefaultEntries.isEmpty()) {
return false;
}
// Pre-allocate list size for access entries to copy from parent.
List<AclEntry> accessEntries = Lists.newArrayListWithCapacity(parentDefaultEntries.size());
FsPermission childPerm = child.getFsPermission();
// Copy each default ACL entry from parent to new child's access ACL.
boolean parentDefaultIsMinimal = AclUtil.isMinimalAcl(parentDefaultEntries);
for (AclEntry entry : parentDefaultEntries) {
AclEntryType type = entry.getType();
String name = entry.getName();
AclEntry.Builder builder = new AclEntry.Builder().setScope(AclEntryScope.ACCESS).setType(type).setName(name);
// The child's initial permission bits are treated as the mode parameter,
// which can filter copied permission values for owner, mask and other.
final FsAction permission;
if (type == AclEntryType.USER && name == null) {
permission = entry.getPermission().and(childPerm.getUserAction());
} else if (type == AclEntryType.GROUP && parentDefaultIsMinimal) {
// This only happens if the default ACL is a minimal ACL: exactly 3
// entries corresponding to owner, group and other. In this case,
// filter the group permissions.
permission = entry.getPermission().and(childPerm.getGroupAction());
} else if (type == AclEntryType.MASK) {
// Group bits from mode parameter filter permission of mask entry.
permission = entry.getPermission().and(childPerm.getGroupAction());
} else if (type == AclEntryType.OTHER) {
permission = entry.getPermission().and(childPerm.getOtherAction());
} else {
permission = entry.getPermission();
}
builder.setPermission(permission);
accessEntries.add(builder.build());
}
// A new directory also receives a copy of the parent's default ACL.
List<AclEntry> defaultEntries = child.isDirectory() ? parentDefaultEntries : Collections.<AclEntry>emptyList();
final FsPermission newPerm;
if (!AclUtil.isMinimalAcl(accessEntries) || !defaultEntries.isEmpty()) {
// Save the new ACL to the child.
child.addAclFeature(createAclFeature(accessEntries, defaultEntries));
newPerm = createFsPermissionForExtendedAcl(accessEntries, childPerm);
} else {
// The child is receiving a minimal ACL.
newPerm = createFsPermissionForMinimalAcl(accessEntries, childPerm);
}
child.setPermission(newPerm);
return true;
}
use of org.apache.hadoop.fs.permission.FsAction in project hadoop by apache.
the class AclTransformation method calculateMasks.
/**
* Calculates mask entries required for the ACL. Mask calculation is performed
* separately for each scope: access and default. This method is responsible
* for handling the following cases of mask calculation:
* 1. Throws an exception if the caller attempts to remove the mask entry of an
* existing ACL that requires it. If the ACL has any named entries, then a
* mask entry is required.
* 2. If the caller supplied a mask in the ACL spec, use it.
* 3. If the caller did not supply a mask, but there are ACL entry changes in
* this scope, then automatically calculate a new mask. The permissions of
* the new mask are the union of the permissions on the group entry and all
* named entries.
*
* @param aclBuilder ArrayList<AclEntry> containing entries to build
* @param providedMask EnumMap<AclEntryScope, AclEntry> mapping each scope to
* the mask entry that was provided for that scope (if provided)
* @param maskDirty EnumSet<AclEntryScope> which contains a scope if the mask
* entry is dirty (added or deleted) in that scope
* @param scopeDirty EnumSet<AclEntryScope> which contains a scope if any entry
* is dirty (added or deleted) in that scope
* @throws AclException if validation fails
*/
private static void calculateMasks(List<AclEntry> aclBuilder, EnumMap<AclEntryScope, AclEntry> providedMask, EnumSet<AclEntryScope> maskDirty, EnumSet<AclEntryScope> scopeDirty) throws AclException {
EnumSet<AclEntryScope> scopeFound = EnumSet.noneOf(AclEntryScope.class);
EnumMap<AclEntryScope, FsAction> unionPerms = Maps.newEnumMap(AclEntryScope.class);
EnumSet<AclEntryScope> maskNeeded = EnumSet.noneOf(AclEntryScope.class);
// union of group class permissions in each scope.
for (AclEntry entry : aclBuilder) {
scopeFound.add(entry.getScope());
if (entry.getType() == GROUP || entry.getName() != null) {
FsAction scopeUnionPerms = Objects.firstNonNull(unionPerms.get(entry.getScope()), FsAction.NONE);
unionPerms.put(entry.getScope(), scopeUnionPerms.or(entry.getPermission()));
}
if (entry.getName() != null) {
maskNeeded.add(entry.getScope());
}
}
// Add mask entry if needed in each scope.
for (AclEntryScope scope : scopeFound) {
if (!providedMask.containsKey(scope) && maskNeeded.contains(scope) && maskDirty.contains(scope)) {
// Caller explicitly removed mask entry, but it's required.
throw new AclException("Invalid ACL: mask is required and cannot be deleted.");
} else if (providedMask.containsKey(scope) && (!scopeDirty.contains(scope) || maskDirty.contains(scope))) {
// Caller explicitly provided new mask, or we are preserving the existing
// mask in an unchanged scope.
aclBuilder.add(providedMask.get(scope));
} else if (maskNeeded.contains(scope) || providedMask.containsKey(scope)) {
// Otherwise, if there are maskable entries present, or the ACL
// previously had a mask, then recalculate a mask automatically.
aclBuilder.add(new AclEntry.Builder().setScope(scope).setType(MASK).setPermission(unionPerms.get(scope)).build());
}
}
}
use of org.apache.hadoop.fs.permission.FsAction in project hadoop by apache.
the class FSPermissionChecker method hasAclPermission.
/**
* Checks requested access against an Access Control List. This method relies
* on finding the ACL data in the relevant portions of {@link FsPermission} and
* {@link AclFeature} as implemented in the logic of {@link AclStorage}. This
* method also relies on receiving the ACL entries in sorted order. This is
* assumed to be true, because the ACL modification methods in
* {@link AclTransformation} sort the resulting entries.
*
* More specifically, this method depends on these invariants in an ACL:
* - The list must be sorted.
* - Each entry in the list must be unique by scope + type + name.
* - There is exactly one each of the unnamed user/group/other entries.
* - The mask entry must not have a name.
* - The other entry must not have a name.
* - Default entries may be present, but they are ignored during enforcement.
*
* @param inode INodeAttributes accessed inode
* @param snapshotId int snapshot ID
* @param access FsAction requested permission
* @param mode FsPermission mode from inode
* @param aclFeature AclFeature of inode
* @throws AccessControlException if the ACL denies permission
*/
private boolean hasAclPermission(INodeAttributes inode, FsAction access, FsPermission mode, AclFeature aclFeature) {
boolean foundMatch = false;
// Use owner entry from permission bits if user is owner.
if (getUser().equals(inode.getUserName())) {
if (mode.getUserAction().implies(access)) {
return true;
}
foundMatch = true;
}
// Check named user and group entries if user was not denied by owner entry.
if (!foundMatch) {
for (int pos = 0, entry; pos < aclFeature.getEntriesSize(); pos++) {
entry = aclFeature.getEntryAt(pos);
if (AclEntryStatusFormat.getScope(entry) == AclEntryScope.DEFAULT) {
break;
}
AclEntryType type = AclEntryStatusFormat.getType(entry);
String name = AclEntryStatusFormat.getName(entry);
if (type == AclEntryType.USER) {
// matches name.
if (getUser().equals(name)) {
FsAction masked = AclEntryStatusFormat.getPermission(entry).and(mode.getGroupAction());
if (masked.implies(access)) {
return true;
}
foundMatch = true;
break;
}
} else if (type == AclEntryType.GROUP) {
// Use group entry (unnamed or named) with mask from permission bits
// applied if user is a member and entry grants access. If user is a
// member of multiple groups that have entries that grant access, then
// it doesn't matter which is chosen, so exit early after first match.
String group = name == null ? inode.getGroupName() : name;
if (isMemberOfGroup(group)) {
FsAction masked = AclEntryStatusFormat.getPermission(entry).and(mode.getGroupAction());
if (masked.implies(access)) {
return true;
}
foundMatch = true;
}
}
}
}
// Use other entry if user was not denied by an earlier match.
return !foundMatch && mode.getOtherAction().implies(access);
}
use of org.apache.hadoop.fs.permission.FsAction in project hadoop by apache.
the class TestSnapshot method genRandomPermission.
/**
* @return A random FsPermission
*/
private FsPermission genRandomPermission() {
// randomly select between "rwx" and "rw-"
FsAction u = random.nextBoolean() ? FsAction.ALL : FsAction.READ_WRITE;
FsAction g = random.nextBoolean() ? FsAction.ALL : FsAction.READ_WRITE;
FsAction o = random.nextBoolean() ? FsAction.ALL : FsAction.READ_WRITE;
return new FsPermission(u, g, o);
}
Aggregations