use of alluxio.security.authorization.DefaultAccessControlList in project alluxio by Alluxio.
the class ProtoUtils method fromProto.
/**
* @param acl the protobuf representation
* @return {@link AccessControlList}
*/
public static AccessControlList fromProto(Acl.AccessControlList acl) {
AccessControlList ret;
if (acl.hasIsDefault() && acl.getIsDefault()) {
ret = new DefaultAccessControlList();
} else {
ret = new AccessControlList();
}
ret.setOwningUser(acl.getOwningUser().intern());
ret.setOwningGroup(acl.getOwningGroup().intern());
if (acl.getIsEmpty()) {
return ret;
}
// true if there are any extended entries (named user or named group)
boolean hasExtended = false;
for (Acl.NamedAclActions namedActions : acl.getUserActionsList()) {
String name = namedActions.getName();
AclActions actions = fromProto(namedActions.getActions());
AclEntry entry;
if (name.equals(AccessControlList.OWNING_USER_KEY)) {
entry = new AclEntry.Builder().setType(AclEntryType.OWNING_USER).setSubject(acl.getOwningUser()).setActions(actions).build();
} else {
hasExtended = true;
entry = new AclEntry.Builder().setType(AclEntryType.NAMED_USER).setSubject(name).setActions(actions).build();
}
ret.setEntry(entry);
}
for (Acl.NamedAclActions namedActions : acl.getGroupActionsList()) {
String name = namedActions.getName();
AclActions actions = fromProto(namedActions.getActions());
AclEntry entry;
if (name.equals(AccessControlList.OWNING_GROUP_KEY)) {
entry = new AclEntry.Builder().setType(AclEntryType.OWNING_GROUP).setSubject(acl.getOwningGroup()).setActions(actions).build();
} else {
hasExtended = true;
entry = new AclEntry.Builder().setType(AclEntryType.NAMED_GROUP).setSubject(name).setActions(actions).build();
}
ret.setEntry(entry);
}
if (hasExtended) {
// Only set the mask if there are any extended acl entries.
AclActions actions = fromProto(acl.getMaskActions());
AclEntry entry = new AclEntry.Builder().setType(AclEntryType.MASK).setActions(actions).build();
ret.setEntry(entry);
}
AclActions actions = fromProto(acl.getOtherActions());
AclEntry entry = new AclEntry.Builder().setType(AclEntryType.OTHER).setActions(actions).build();
ret.setEntry(entry);
return ret;
}
use of alluxio.security.authorization.DefaultAccessControlList in project alluxio by Alluxio.
the class ProtoUtils method toProto.
/**
* @param acl {@link AccessControlList}
* @return protobuf representation
*/
public static Acl.AccessControlList toProto(AccessControlList acl) {
Acl.AccessControlList.Builder builder = Acl.AccessControlList.newBuilder();
builder.setOwningUser(acl.getOwningUser());
builder.setOwningGroup(acl.getOwningGroup());
// base entries
builder.addUserActions(Acl.NamedAclActions.newBuilder().setName(AccessControlList.OWNING_USER_KEY).setActions(toProto(acl.getOwningUserActions())).build());
builder.addGroupActions(Acl.NamedAclActions.newBuilder().setName(AccessControlList.OWNING_GROUP_KEY).setActions(toProto(acl.getOwningGroupActions())).build());
builder.setOtherActions(toProto(acl.getOtherActions()));
if (acl.getExtendedEntries() != null) {
builder.addAllUserActions(getNamedUsersProto(acl.getExtendedEntries()));
builder.addAllGroupActions(getNamedGroupsProto(acl.getExtendedEntries()));
builder.setMaskActions(toProto(acl.getExtendedEntries().getMask()));
}
if (acl instanceof DefaultAccessControlList) {
DefaultAccessControlList defaultAcl = (DefaultAccessControlList) acl;
builder.setIsDefault(true);
builder.setIsEmpty(defaultAcl.isEmpty());
} else {
builder.setIsDefault(false);
// non default acl is always not empty
builder.setIsEmpty(false);
}
return builder.build();
}
use of alluxio.security.authorization.DefaultAccessControlList in project alluxio by Alluxio.
the class FileInfoTest method createRandom.
public static FileInfo createRandom() {
FileInfo result = new FileInfo();
Random random = new Random();
long fileId = random.nextLong();
String name = CommonUtils.randomAlphaNumString(random.nextInt(10));
String path = CommonUtils.randomAlphaNumString(random.nextInt(10));
String ufsPath = CommonUtils.randomAlphaNumString(random.nextInt(10));
long mountId = random.nextLong();
long length = random.nextLong();
long blockSizeBytes = random.nextLong();
long creationTimeMs = random.nextLong();
boolean completed = random.nextBoolean();
boolean folder = random.nextBoolean();
boolean pinned = random.nextBoolean();
boolean cacheable = random.nextBoolean();
boolean persisted = random.nextBoolean();
List<Long> blockIds = new ArrayList<>();
long numBlockIds = random.nextInt(10);
for (int i = 0; i < numBlockIds; i++) {
blockIds.add(random.nextLong());
}
int inMemoryPercentage = random.nextInt();
int inAlluxioPercentage = random.nextInt();
long lastModificationTimeMs = random.nextLong();
long lastAccessTimeMs = random.nextLong();
long ttl = random.nextLong();
String userName = CommonUtils.randomAlphaNumString(random.nextInt(10));
String groupName = CommonUtils.randomAlphaNumString(random.nextInt(10));
int permission = random.nextInt();
String persistenceState = CommonUtils.randomAlphaNumString(random.nextInt(10));
boolean mountPoint = random.nextBoolean();
List<FileBlockInfo> fileBlocksInfos = new ArrayList<>();
long numFileBlockInfos = random.nextInt(10);
for (int i = 0; i < numFileBlockInfos; i++) {
fileBlocksInfos.add(FileBlockInfoTest.createRandom());
}
int replicationMax = random.nextInt(10);
int replicationMin = random.nextInt(10);
Map<String, byte[]> xttrs = new HashMap<>();
for (int i = 0; i < random.nextInt(10); i++) {
xttrs.put(CommonUtils.randomAlphaNumString(random.nextInt(10)), CommonUtils.randomBytes(random.nextInt(10)));
}
result.setBlockIds(blockIds);
result.setBlockSizeBytes(blockSizeBytes);
result.setCacheable(cacheable);
result.setCompleted(completed);
result.setCreationTimeMs(creationTimeMs);
result.setFileBlockInfos(fileBlocksInfos);
result.setFileId(fileId);
result.setFolder(folder);
result.setGroup(groupName);
result.setInMemoryPercentage(inMemoryPercentage);
result.setLastModificationTimeMs(lastModificationTimeMs);
result.setLastAccessTimeMs(lastAccessTimeMs);
result.setLength(length);
result.setMode(permission);
result.setMountPoint(mountPoint);
result.setReplicationMax(replicationMax);
result.setReplicationMin(replicationMin);
result.setName(name);
result.setOwner(userName);
result.setPath(path);
result.setPersisted(persisted);
result.setPersistenceState(persistenceState);
result.setPinned(pinned);
result.setTtl(ttl);
result.setTtlAction(TtlAction.DELETE);
result.setMountId(mountId);
result.setUfsPath(ufsPath);
result.setInAlluxioPercentage(inAlluxioPercentage);
List<String> stringEntries = Arrays.asList("user::rw-", "group::r--", "other::rwx");
AccessControlList acl = AccessControlList.fromStringEntries(userName, groupName, stringEntries);
result.setAcl(acl);
List<String> defaultStringEntries = Arrays.asList("default:user::rw-", "default:group::r--", "default:other::rwx");
result.setDefaultAcl((DefaultAccessControlList) AccessControlList.fromStringEntries(userName, groupName, defaultStringEntries));
result.setXAttr(xttrs);
return result;
}
use of alluxio.security.authorization.DefaultAccessControlList in project alluxio by Alluxio.
the class InodeTree method createPath.
/**
* Creates a file or directory at path.
*
* This method expects that the last edge leading to the target inode to be write-locked. If the
* last existing inode in the path is /a/b/c and we want to create /a/b/c/d/e, the c->d edge must
* be write locked.
*
* On success, createPath attempts to push the write lock forward as far as possible. For the
* above example, createPath would take a write lock on d->e, and downgrade the c->d lock from a
* write lock to a read lock. This may not be possible if inodePath is a composite path which
* doesn't own the write lock. In that case no downgrade will occur.
*
* @param rpcContext the rpc context
* @param inodePath the path
* @param context method context
* @return a list of created inodes
* @throws FileAlreadyExistsException when there is already a file at path if we want to create a
* directory there
* @throws BlockInfoException when blockSizeBytes is invalid
* @throws InvalidPathException when path is invalid, for example, (1) when there is nonexistent
* necessary parent directories and recursive is false, (2) when one of the necessary
* parent directories is actually a file
* @throws FileDoesNotExistException if the parent of the path does not exist and the recursive
* option is false
*/
public List<Inode> createPath(RpcContext rpcContext, LockedInodePath inodePath, CreatePathContext<?, ?> context) throws FileAlreadyExistsException, BlockInfoException, InvalidPathException, IOException, FileDoesNotExistException {
Preconditions.checkState(inodePath.getLockPattern() == LockPattern.WRITE_EDGE);
// TODO(gpang): consider splitting this into createFilePath and createDirectoryPath, with a
// helper method for the shared logic.
AlluxioURI path = inodePath.getUri();
if (path.isRoot()) {
String errorMessage = "Not allowed to create existing root path: " + path;
LOG.error(errorMessage);
throw new FileAlreadyExistsException(errorMessage);
}
if (inodePath.fullPathExists()) {
if (context instanceof CreateDirectoryContext && ((CreateDirectoryContext) context).getOptions().getAllowExists()) {
return Collections.emptyList();
} else {
String pathType = "file";
if (context instanceof CreateDirectoryContext) {
pathType = "directory";
}
String errorMessage = String.format("Not allowed to create %s because path already exists: %s", pathType, path);
throw new FileAlreadyExistsException(errorMessage);
}
}
if (context instanceof CreateFileContext) {
CreateFileContext fileContext = (CreateFileContext) context;
if (fileContext.getOptions().getBlockSizeBytes() < 1) {
throw new BlockInfoException("Invalid block size " + fileContext.getOptions().getBlockSizeBytes());
}
}
LOG.debug("createPath {}", path);
String[] pathComponents = inodePath.mPathComponents;
String name = path.getName();
// pathIndex is the index into pathComponents where we start filling in the path from the inode.
int pathIndex = inodePath.getExistingInodeCount();
if (pathIndex < pathComponents.length - 1) {
// Otherwise we add the remaining path components to the list of components to create.
if (!context.isRecursive()) {
throw new FileDoesNotExistException(String.format("File %s creation failed. Component %d(%s) does not exist", path, pathIndex, pathComponents[pathIndex]));
}
}
// The ancestor inode (parent or ancestor) of the target path.
Inode ancestorInode = inodePath.getAncestorInode();
if (!ancestorInode.isDirectory()) {
throw new InvalidPathException("Could not traverse to parent directory of path " + path + ". Component " + pathComponents[pathIndex - 1] + " is not a directory.");
}
InodeDirectoryView currentInodeDirectory = ancestorInode.asDirectory();
List<Inode> createdInodes = new ArrayList<>();
if (context.isPersisted()) {
// Synchronously persist directories. These inodes are already READ locked.
for (Inode inode : inodePath.getInodeList()) {
if (!inode.isPersisted()) {
// This cast is safe because we've already verified that the file inode doesn't exist.
syncPersistExistingDirectory(rpcContext, inode.asDirectory());
}
}
}
if ((pathIndex < (pathComponents.length - 1) || !mInodeStore.getChild(currentInodeDirectory, name).isPresent()) && context.getOperationTimeMs() > currentInodeDirectory.getLastModificationTimeMs()) {
// (1) There are components in parent paths that need to be created. Or
// (2) The last component of the path needs to be created.
// In these two cases, the last traversed Inode will be modified if the new timestamp is after
// the existing last modified time.
long currentId = currentInodeDirectory.getId();
try (LockResource lr = mInodeLockManager.lockUpdate(currentId)) {
long updatedLastModified = mInodeStore.get(currentId).get().getLastModificationTimeMs();
if (updatedLastModified < context.getOperationTimeMs()) {
UpdateInodeEntry.Builder updateInodeEntry = UpdateInodeEntry.newBuilder().setId(currentId).setLastModificationTimeMs(context.getOperationTimeMs()).setLastAccessTimeMs(context.getOperationTimeMs());
if (context.getXAttr() != null) {
updateInodeEntry.putAllXAttr(CommonUtils.convertToByteString(context.getXAttr()));
}
mState.applyAndJournal(rpcContext, updateInodeEntry.build());
}
}
}
// Fill in the ancestor directories that were missing.
// NOTE, we set the mode of missing ancestor directories to be the default value, rather
// than inheriting the option of the final file to create, because it may not have
// "execute" permission.
CreateDirectoryContext missingDirContext = CreateDirectoryContext.defaults();
missingDirContext.getOptions().setCommonOptions(FileSystemMasterCommonPOptions.newBuilder().setTtl(context.getTtl()).setTtlAction(context.getTtlAction()));
missingDirContext.setWriteType(context.getWriteType());
missingDirContext.setOperationTimeMs(context.getOperationTimeMs());
missingDirContext.setMountPoint(false);
missingDirContext.setOwner(context.getOwner());
missingDirContext.setGroup(context.getGroup());
missingDirContext.setXAttr(context.getXAttr());
StringBuilder pathBuilder = new StringBuilder().append(String.join(AlluxioURI.SEPARATOR, Arrays.asList(pathComponents).subList(0, pathIndex)));
for (int k = pathIndex; k < (pathComponents.length - 1); k++) {
MutableInodeDirectory newDir = MutableInodeDirectory.create(mDirectoryIdGenerator.getNewDirectoryId(rpcContext.getJournalContext()), currentInodeDirectory.getId(), pathComponents[k], missingDirContext);
if (currentInodeDirectory.isPinned() && !newDir.isPinned()) {
newDir.setPinned(true);
newDir.setMediumTypes(new HashSet<>(currentInodeDirectory.getMediumTypes()));
}
inheritOwnerAndGroupIfEmpty(newDir, currentInodeDirectory);
// if the parent has default ACL, copy that default ACL as the new directory's default
// and access acl, ANDed with the umask
// if it is part of a metadata load operation, we ignore the umask and simply inherit
// the default ACL as the directory's new default and access ACL
short mode = context.isMetadataLoad() ? Mode.createFullAccess().toShort() : newDir.getMode();
DefaultAccessControlList dAcl = currentInodeDirectory.getDefaultACL();
if (!dAcl.isEmpty()) {
Pair<AccessControlList, DefaultAccessControlList> pair = dAcl.generateChildDirACL(mode);
newDir.setInternalAcl(pair.getFirst());
newDir.setDefaultACL(pair.getSecond());
}
String newDirPath = k == 0 ? ROOT_PATH : pathBuilder.append(AlluxioURI.SEPARATOR).append(pathComponents[k]).toString();
mState.applyAndJournal(rpcContext, newDir, newDirPath);
inodePath.addNextInode(Inode.wrap(newDir));
// concurrent creates from trying to persist the same directory name.
if (context.isPersisted()) {
syncPersistExistingDirectory(rpcContext, newDir);
}
createdInodes.add(Inode.wrap(newDir));
currentInodeDirectory = newDir;
}
// Create the final path component.
MutableInode<?> newInode;
// create the new inode, with a write lock
if (context instanceof CreateDirectoryContext) {
CreateDirectoryContext directoryContext = (CreateDirectoryContext) context;
MutableInodeDirectory newDir = MutableInodeDirectory.create(mDirectoryIdGenerator.getNewDirectoryId(rpcContext.getJournalContext()), currentInodeDirectory.getId(), name, directoryContext);
// if the parent has default ACL, take the default ACL ANDed with the umask as the new
// directory's default and access acl
// When it is a metadata load operation, do not take the umask into account
short mode = context.isMetadataLoad() ? Mode.createFullAccess().toShort() : newDir.getMode();
DefaultAccessControlList dAcl = currentInodeDirectory.getDefaultACL();
if (!dAcl.isEmpty()) {
Pair<AccessControlList, DefaultAccessControlList> pair = dAcl.generateChildDirACL(mode);
newDir.setInternalAcl(pair.getFirst());
newDir.setDefaultACL(pair.getSecond());
}
if (directoryContext.isPersisted()) {
// Do not journal the persist entry, since a creation entry will be journaled instead.
if (context.isMetadataLoad()) {
// if we are creating the file as a result of loading metadata, the newDir is already
// persisted, and we got the permissions info from the ufs.
newDir.setOwner(context.getOwner().intern()).setGroup(context.getGroup().intern()).setMode(context.getMode().toShort());
Long operationTimeMs = context.getOperationTimeMs();
if (operationTimeMs != null) {
newDir.setLastModificationTimeMs(operationTimeMs, true);
newDir.setLastAccessTimeMs(operationTimeMs, true);
}
newDir.setPersistenceState(PersistenceState.PERSISTED);
} else {
syncPersistNewDirectory(newDir);
}
}
// Do NOT call setOwner/Group after inheriting from parent if empty
inheritOwnerAndGroupIfEmpty(newDir, currentInodeDirectory);
newInode = newDir;
} else if (context instanceof CreateFileContext) {
CreateFileContext fileContext = (CreateFileContext) context;
MutableInodeFile newFile = MutableInodeFile.create(mContainerIdGenerator.getNewContainerId(), currentInodeDirectory.getId(), name, System.currentTimeMillis(), fileContext);
// if the parent has a default ACL, copy that default ACL ANDed with the umask as the new
// file's access ACL.
// If it is a metadata load operation, do not consider the umask.
DefaultAccessControlList dAcl = currentInodeDirectory.getDefaultACL();
short mode = context.isMetadataLoad() ? Mode.createFullAccess().toShort() : newFile.getMode();
if (!dAcl.isEmpty()) {
AccessControlList acl = dAcl.generateChildFileACL(mode);
newFile.setInternalAcl(acl);
}
if (fileContext.isCacheable()) {
newFile.setCacheable(true);
}
if (fileContext.getWriteType() == WriteType.ASYNC_THROUGH) {
newFile.setPersistenceState(PersistenceState.TO_BE_PERSISTED);
}
// Do NOT call setOwner/Group after inheriting from parent if empty
inheritOwnerAndGroupIfEmpty(newFile, currentInodeDirectory);
newInode = newFile;
} else {
throw new IllegalStateException(String.format("Unrecognized create options: %s", context));
}
if (currentInodeDirectory.isPinned() && !newInode.isPinned()) {
newInode.setPinned(true);
newInode.setMediumTypes(new HashSet<>(currentInodeDirectory.getMediumTypes()));
}
mState.applyAndJournal(rpcContext, newInode, inodePath.getUri().getPath());
Inode inode = Inode.wrap(newInode);
inodePath.addNextInode(inode);
createdInodes.add(inode);
LOG.debug("createFile: File Created: {} parent: {}", newInode, currentInodeDirectory);
return createdInodes;
}
use of alluxio.security.authorization.DefaultAccessControlList in project alluxio by Alluxio.
the class MutableInodeDirectory method fromJournalEntry.
/**
* Converts the entry to an {@link MutableInodeDirectory}.
*
* @param entry the entry to convert
* @return the {@link MutableInodeDirectory} representation
*/
public static MutableInodeDirectory fromJournalEntry(InodeDirectoryEntry entry) {
// If journal entry has no mode set, set default mode for backwards-compatibility.
MutableInodeDirectory ret = new MutableInodeDirectory(entry.getId()).setCreationTimeMs(entry.getCreationTimeMs()).setName(entry.getName()).setParentId(entry.getParentId()).setPersistenceState(PersistenceState.valueOf(entry.getPersistenceState())).setPinned(entry.getPinned()).setLastModificationTimeMs(entry.getLastModificationTimeMs(), true).setLastAccessTimeMs(entry.hasLastAccessTimeMs() ? entry.getLastAccessTimeMs() : entry.getLastModificationTimeMs(), true).setMountPoint(entry.getMountPoint()).setTtl(entry.getTtl()).setTtlAction(ProtobufUtils.fromProtobuf(entry.getTtlAction())).setDirectChildrenLoaded(entry.getDirectChildrenLoaded());
if (entry.hasAcl()) {
ret.mAcl = ProtoUtils.fromProto(entry.getAcl());
} else {
// Backward compatibility.
AccessControlList acl = new AccessControlList();
acl.setOwningUser(entry.getOwner().intern());
acl.setOwningGroup(entry.getGroup().intern());
short mode = entry.hasMode() ? (short) entry.getMode() : Constants.DEFAULT_FILE_SYSTEM_MODE;
acl.setMode(mode);
ret.mAcl = acl;
}
if (entry.hasDefaultAcl()) {
ret.mDefaultAcl = (DefaultAccessControlList) ProtoUtils.fromProto(entry.getDefaultAcl());
} else {
ret.mDefaultAcl = new DefaultAccessControlList();
}
ret.setMediumTypes(new HashSet<>(entry.getMediumTypeList()));
if (entry.getXAttrCount() > 0) {
ret.setXAttr(CommonUtils.convertFromByteString(entry.getXAttrMap()));
}
return ret;
}
Aggregations