/** * Changes the mode of an Alluxio file. * * @param path the path of the file * @param mode the mode to change to * @return 0 on success, a negative value on error */ @Override public int chmod(String path, @mode_t long mode) { AlluxioURI uri = mPathResolverCache.getUnchecked(path); SetAttributePOptions options = SetAttributePOptions.newBuilder() .setMode(new alluxio.security.authorization.Mode((short) mode).toProto()).build(); try { mFileSystem.setAttribute(uri, options); } catch (Throwable t) { LOG.error("Failed to change {} to mode {}", path, mode, t); return AlluxioFuseUtils.getErrorCode(t); } return 0; }
/** * Changes the permissions of directory or file with the path specified in args. * * @param path The {@link AlluxioURI} path as the input of the command * @param modeStr The new permission to be updated to the file or directory * @param recursive Whether change the permission recursively */ private void chmod(AlluxioURI path, String modeStr, boolean recursive) throws AlluxioException, IOException { Mode mode = ModeParser.parse(modeStr); SetAttributePOptions options = SetAttributePOptions.newBuilder().setMode(mode.toProto()).setRecursive(recursive).build(); mFileSystem.setAttribute(path, options); System.out .println("Changed permission of " + path + " to " + Integer.toOctalString(mode.toShort())); }
/** * Changes permission of a path. * * @param path path to set permission * @param permission permission set to path */ @Override public void setPermission(Path path, FsPermission permission) throws IOException { LOG.debug("setMode({},{})", path, permission.toString()); AlluxioURI uri = new AlluxioURI(HadoopUtils.getPathWithoutScheme(path)); SetAttributePOptions options = SetAttributePOptions.newBuilder() .setMode(new Mode(permission.toShort()).toProto()).setRecursive(false).build(); try { mFileSystem.setAttribute(uri, options); } catch (AlluxioException e) { throw new IOException(e); } }
/** * Attempts to create a folder with the specified path. Parent directories will be created. * * @param path path to create * @param permission permissions to grant the created folder * @return true if the indicated folder is created successfully or already exists */ @Override public boolean mkdirs(Path path, FsPermission permission) throws IOException { LOG.debug("mkdirs({}, {})", path, permission); if (mStatistics != null) { mStatistics.incrementWriteOps(1); } AlluxioURI uri = new AlluxioURI(HadoopUtils.getPathWithoutScheme(path)); CreateDirectoryPOptions options = CreateDirectoryPOptions.newBuilder().setRecursive(true) .setAllowExists(true).setMode(new Mode(permission.toShort()).toProto()).build(); try { mFileSystem.createDirectory(uri, options); return true; } catch (AlluxioException e) { throw new IOException(e); } }
@Test public void setAclWithoutOwner() throws Exception { createFileWithSingleBlock(NESTED_FILE_URI); mFileSystemMaster.setAttribute(NESTED_URI, SetAttributeContext .defaults(SetAttributePOptions.newBuilder().setMode(new Mode((short) 0777).toProto()))); Set<String> entries = Sets.newHashSet(mFileSystemMaster .getFileInfo(NESTED_FILE_URI, GET_STATUS_CONTEXT).convertAclToStringEntries()); assertEquals(3, entries.size()); try (AuthenticatedClientUserResource userA = new AuthenticatedClientUserResource("userA", ServerConfiguration.global())) { Set<String> newEntries = Sets.newHashSet("user::rwx", "group::rwx", "other::rwx"); mThrown.expect(AccessControlException.class); mFileSystemMaster.setAcl(NESTED_FILE_URI, SetAclAction.REPLACE, newEntries.stream().map(AclEntry::fromCliString).collect(Collectors.toList()), SetAclContext.defaults()); } }
/** * Initializes the root of the inode tree. * * @param owner the root owner * @param group the root group * @param mode the root mode * @param context the journal context to journal the initialization to */ public void initializeRoot(String owner, String group, Mode mode, JournalContext context) throws UnavailableException { if (mState.getRoot() == null) { MutableInodeDirectory root = MutableInodeDirectory.create( mDirectoryIdGenerator.getNewDirectoryId(context), NO_PARENT, ROOT_INODE_NAME, CreateDirectoryContext .defaults(CreateDirectoryPOptions.newBuilder().setMode(mode.toProto())) .setOwner(owner).setGroup(group)); root.setPersistenceState(PersistenceState.PERSISTED); mState.applyAndJournal(context, root); } }
/** * @return the inode directory representation */ protected static MutableInodeDirectory createInodeDirectory() { return MutableInodeDirectory.create(1, 0, "test1", CreateDirectoryContext .defaults(CreateDirectoryPOptions.newBuilder().setMode(TEST_DIR_MODE.toProto())) .setOwner(TEST_OWNER).setGroup(TEST_GROUP)); }
/** * @return Master side defaults for {@link CreateDirectoryPOptions} */ public static CreateDirectoryPOptions createDirectoryDefaults() { return CreateDirectoryPOptions.newBuilder() .setCommonOptions(commonDefaults()) .setMode(ModeUtils.applyDirectoryUMask(Mode.defaults(), ServerConfiguration.get(PropertyKey.SECURITY_AUTHORIZATION_PERMISSION_UMASK)).toProto()) .setRecursive(false) .setWriteType(ServerConfiguration .getEnum(PropertyKey.USER_FILE_WRITE_TYPE_DEFAULT, WriteType.class).toProto()) .setAllowExists(false).build(); }
@Test public void setAclNestedWithoutOwner() throws Exception { createFileWithSingleBlock(NESTED_FILE_URI); mFileSystemMaster.setAttribute(NESTED_URI, SetAttributeContext.defaults(SetAttributePOptions .newBuilder().setMode(new Mode((short) 0777).toProto()).setOwner("userA"))); Set<String> entries = Sets.newHashSet(mFileSystemMaster .getFileInfo(NESTED_FILE_URI, GET_STATUS_CONTEXT).convertAclToStringEntries()); assertEquals(3, entries.size()); // recursive setAcl should fail if one of the child is not owned by the user mThrown.expect(AccessControlException.class); try (AuthenticatedClientUserResource userA = new AuthenticatedClientUserResource("userA", ServerConfiguration.global())) { Set<String> newEntries = Sets.newHashSet("user::rwx", "group::rwx", "other::rwx"); mFileSystemMaster.setAcl(NESTED_URI, SetAclAction.REPLACE, newEntries.stream().map(AclEntry::fromCliString).collect(Collectors.toList()), SetAclContext.defaults(SetAclPOptions.newBuilder().setRecursive(true))); entries = Sets.newHashSet(mFileSystemMaster.getFileInfo(NESTED_FILE_URI, GET_STATUS_CONTEXT) .convertAclToStringEntries()); assertEquals(newEntries, entries); } }
/** * @param id block container id of this inode * @return the inode file representation */ protected MutableInodeFile createInodeFile(long id) { return MutableInodeFile.create(id, 1, "testFile" + id, 0, CreateFileContext .defaults(CreateFilePOptions.newBuilder().setBlockSizeBytes(Constants.KB) .setMode(TEST_FILE_MODE.toProto())) .setOwner(TEST_OWNER).setGroup(TEST_GROUP)); } }
private MutableInodeDirectory getRootInode() { return MutableInodeDirectory.create(0, -1, "", CreateDirectoryContext .defaults(CreateDirectoryPOptions.newBuilder().setMode(TEST_DIR_MODE.toProto())) .setOwner(TEST_USER_ADMIN.getUser()).setGroup(TEST_USER_ADMIN.getGroup())); }
/** * Sets up dependencies before a single test runs. */ @BeforeClass public static void beforeClass() throws Exception { sFileContext = CreateFileContext .defaults(CreateFilePOptions.newBuilder().setBlockSizeBytes(Constants.KB) .setMode(TEST_FILE_MODE.toProto())) .setOwner(TEST_OWNER).setGroup(TEST_GROUP); sDirectoryContext = CreateDirectoryContext .defaults(CreateDirectoryPOptions.newBuilder().setMode(TEST_DIR_MODE.toProto())) .setOwner(TEST_OWNER).setGroup(TEST_GROUP); sNestedFileContext = CreateFileContext .defaults(CreateFilePOptions.newBuilder().setBlockSizeBytes(Constants.KB) .setMode(TEST_FILE_MODE.toProto()).setRecursive(true)) .setOwner(TEST_OWNER).setGroup(TEST_GROUP); sNestedDirectoryContext = CreateDirectoryContext.defaults( CreateDirectoryPOptions.newBuilder().setMode(TEST_DIR_MODE.toProto()).setRecursive(true)) .setOwner(TEST_OWNER).setGroup(TEST_GROUP); }
@Test public void listStatusRecursivePermissions() throws Exception { final int files = 10; List<FileInfo> infos; List<String> filenames; // Test files in root directory. for (int i = 0; i < files; i++) { createFileWithSingleBlock(ROOT_URI.join("file" + String.format("%05d", i))); } // Test files in nested directory. for (int i = 0; i < files; i++) { createFileWithSingleBlock(NESTED_URI.join("file" + String.format("%05d", i))); } // Test with permissions mFileSystemMaster.setAttribute(NESTED_URI, SetAttributeContext.defaults(SetAttributePOptions .newBuilder().setMode(new Mode((short) 0400).toProto()).setRecursive(true))); try (Closeable r = new AuthenticatedUserRule("test_user1", ServerConfiguration.global()) .toResource()) { // Test recursive listStatus infos = mFileSystemMaster.listStatus(ROOT_URI, ListStatusContext.defaults(ListStatusPOptions .newBuilder().setLoadMetadataType(LoadMetadataPType.ALWAYS).setRecursive(true))); // 10 files in each directory, 1 level of directories assertEquals(files + 1, infos.size()); } }
@Override public void apply(FileSystem fs) throws Exception { Utils.createFile(fs, PATH); Utils.createFile(fs, NESTED); Utils.createFile(fs, MODE, CreateFilePOptions.newBuilder().setBlockSizeBytes(Constants.KB) .setRecursive(true).setMode(TEST_MODE.toProto()).build()); Utils.createFile(fs, THROUGH, CreateFilePOptions.newBuilder().setBlockSizeBytes(Constants.KB) .setRecursive(true).setWriteType(WritePType.THROUGH).build()); Utils.createFile(fs, TTL, CreateFilePOptions.newBuilder().setBlockSizeBytes(Constants.KB).setRecursive(true) .setCommonOptions(FileSystemMasterCommonPOptions.newBuilder().setTtl(TEST_TTL) .setTtlAction(alluxio.grpc.TtlAction.FREE)) .build()); }
@Test public void deleteDirRecursiveWithPermissions() throws Exception { // userA has permissions to delete directory and nested file createFileWithSingleBlock(NESTED_FILE_URI); mFileSystemMaster.setAttribute(NESTED_URI, SetAttributeContext .defaults(SetAttributePOptions.newBuilder().setMode(new Mode((short) 0777).toProto()))); mFileSystemMaster.setAttribute(NESTED_FILE_URI, SetAttributeContext .defaults(SetAttributePOptions.newBuilder().setMode(new Mode((short) 0777).toProto()))); try (AuthenticatedClientUserResource userA = new AuthenticatedClientUserResource("userA", ServerConfiguration.global())) { mFileSystemMaster.delete(NESTED_URI, DeleteContext.defaults(DeletePOptions.newBuilder().setRecursive(true))); } assertEquals(IdUtils.INVALID_FILE_ID, mFileSystemMaster.getFileId(NESTED_URI)); assertEquals(IdUtils.INVALID_FILE_ID, mFileSystemMaster.getFileId(NESTED_FILE_URI)); }
@Test public void deleteDirRecursiveWithInsufficientPermissions() throws Exception { // userA has permissions to delete directory but not one of the nested files createFileWithSingleBlock(NESTED_FILE_URI); createFileWithSingleBlock(NESTED_FILE2_URI); mFileSystemMaster.setAttribute(NESTED_URI, SetAttributeContext .defaults(SetAttributePOptions.newBuilder().setMode(new Mode((short) 0777).toProto()))); mFileSystemMaster.setAttribute(NESTED_FILE_URI, SetAttributeContext .defaults(SetAttributePOptions.newBuilder().setMode(new Mode((short) 0700).toProto()))); mFileSystemMaster.setAttribute(NESTED_FILE2_URI, SetAttributeContext .defaults(SetAttributePOptions.newBuilder().setMode(new Mode((short) 0777).toProto()))); try (AuthenticatedClientUserResource userA = new AuthenticatedClientUserResource("userA", ServerConfiguration.global())) { mFileSystemMaster.delete(NESTED_URI, DeleteContext.defaults(DeletePOptions.newBuilder().setRecursive(true))); fail("Deleting a directory w/ insufficient permission on child should fail"); } catch (AccessControlException e) { String expectedChildMessage = ExceptionMessage.PERMISSION_DENIED .getMessage("user=userA, access=-w-, path=" + NESTED_FILE_URI + ": failed at file"); assertTrue(e.getMessage().startsWith(ExceptionMessage.DELETE_FAILED_DIR_CHILDREN .getMessage(NESTED_URI, expectedChildMessage))); } assertNotEquals(IdUtils.INVALID_FILE_ID, mFileSystemMaster.getFileId(NESTED_URI)); assertNotEquals(IdUtils.INVALID_FILE_ID, mFileSystemMaster.getFileId(NESTED_FILE_URI)); assertNotEquals(IdUtils.INVALID_FILE_ID, mFileSystemMaster.getFileId(NESTED_FILE2_URI)); }
/** * @return Master side defaults for {@link CreateFilePOptions} */ public static CreateFilePOptions createFileDefaults() { return CreateFilePOptions.newBuilder() .setCommonOptions(commonDefaults()) .setRecursive(false) .setBlockSizeBytes(ServerConfiguration.getBytes(PropertyKey.USER_BLOCK_SIZE_BYTES_DEFAULT)) .setFileWriteLocationPolicy( ServerConfiguration.get(PropertyKey.USER_FILE_WRITE_LOCATION_POLICY)) .setWriteTier(ServerConfiguration.getInt(PropertyKey.USER_FILE_WRITE_TIER_DEFAULT)) .setWriteType(ServerConfiguration .getEnum(PropertyKey.USER_FILE_WRITE_TYPE_DEFAULT, WriteType.class).toProto()) .setMode(ModeUtils.applyFileUMask(Mode.defaults(), ServerConfiguration.get(PropertyKey.SECURITY_AUTHORIZATION_PERMISSION_UMASK)).toProto()) .setReplicationDurable(ServerConfiguration .getInt(PropertyKey.USER_FILE_REPLICATION_DURABLE)) .setReplicationMin(ServerConfiguration.getInt(PropertyKey.USER_FILE_REPLICATION_MIN)) .setReplicationMax(ServerConfiguration.getInt(PropertyKey.USER_FILE_REPLICATION_MAX)) .build(); }
private AlluxioURI createTestFile() throws Exception { AlluxioURI path = new AlluxioURI("/" + CommonUtils.randomAlphaNumString(10)); String owner = SecurityUtils.getOwnerFromGrpcClient(ServerConfiguration.global()); String group = SecurityUtils.getGroupFromGrpcClient(ServerConfiguration.global()); mFileSystemMaster.createFile(path, CreateFileContext .defaults( CreateFilePOptions.newBuilder().setMode(Mode.createFullAccess().toProto())) .setOwner(owner).setGroup(group)); mFileSystemMaster.completeFile(path, CompleteFileContext.defaults()); return path; }
@Override public void apply(FileSystem fs) throws Exception { fs.createDirectory(DIR); fs.createDirectory(NESTED_DIR); fs.createDirectory(NESTED_NESTED_DIR); fs.createDirectory(RECURSIVE, CreateDirectoryPOptions.newBuilder().setRecursive(true).build()); fs.createDirectory(RECURSIVE, CreateDirectoryPOptions.newBuilder().setAllowExists(true).build()); fs.createDirectory(MODE_DIR, CreateDirectoryPOptions.newBuilder().setMode(TEST_MODE.toProto()) .setRecursive(true).build()); // Set TTL via common options instead (should have the same effect). fs.createDirectory(COMMON_TTL_DIR, CreateDirectoryPOptions.newBuilder().setRecursive(true).setCommonOptions( FileSystemMasterCommonPOptions.newBuilder().setTtl(TTL).setTtlAction(TtlAction.DELETE)) .build()); fs.createDirectory(TTL_DIR, CreateDirectoryPOptions.newBuilder().setCommonOptions( FileSystemMasterCommonPOptions.newBuilder().setTtl(TTL).setTtlAction(TtlAction.DELETE)) .setRecursive(true).build()); fs.createDirectory(THROUGH_DIR, CreateDirectoryPOptions.newBuilder() .setWriteType(WritePType.THROUGH).setRecursive(true).build()); fs.createDirectory(ALL_OPTS_DIR, CreateDirectoryPOptions.newBuilder().setRecursive(true) .setMode(TEST_MODE.toProto()).setAllowExists(true).setWriteType(WritePType.THROUGH) .setCommonOptions( FileSystemMasterCommonPOptions.newBuilder().setTtl(TTL).setTtlAction(TtlAction.DELETE)) .build()); }
private void verifySetAcl(TestUser runUser, String path, String owner, String group, short mode, boolean recursive) throws Exception { try (Closeable r = new AuthenticatedUserRule(runUser.getUser(), ServerConfiguration.global()).toResource()) { SetAttributeContext context = SetAttributeContext.defaults(SetAttributePOptions.newBuilder() .setMode(new Mode(mode).toProto()).setRecursive(recursive)); if (owner != null) { context.getOptions().setOwner(owner); } if (group != null) { context.getOptions().setGroup(group); } mFileSystemMaster.setAttribute(new AlluxioURI(path), context); } try (Closeable r = new AuthenticatedUserRule(TEST_USER_ADMIN.getUser(), ServerConfiguration.global()).toResource()) { FileInfo fileInfo = mFileSystemMaster.getFileInfo(mFileSystemMaster.getFileId(new AlluxioURI(path))); if (owner != null) { assertEquals(owner, fileInfo.getOwner()); } if (group != null) { assertEquals(group, fileInfo.getGroup()); } if (mode != -1) { assertEquals(mode, fileInfo.getMode()); } } }