blob: 836fc0cc39df0e59a37e729fab6885ffebbe7f8d [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hdfs.server.namenode;
import static org.apache.hadoop.hdfs.server.namenode.AclTestHelpers.*;
import static org.apache.hadoop.fs.permission.AclEntryScope.*;
import static org.apache.hadoop.fs.permission.AclEntryType.*;
import static org.apache.hadoop.fs.permission.FsAction.*;
import static org.junit.Assert.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.AclEntry;
import org.apache.hadoop.fs.permission.AclStatus;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.protocol.AclException;
import org.apache.hadoop.hdfs.protocol.FsPermissionExtension;
import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
import org.apache.hadoop.hdfs.server.namenode.FSDirectory.DirOp;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
/**
* Tests NameNode interaction for all ACL modification APIs. This test suite
* also covers interaction of setPermission with inodes that have ACLs.
*/
public abstract class FSAclBaseTest {
private static final UserGroupInformation BRUCE =
UserGroupInformation.createUserForTesting("bruce", new String[] { });
private static final UserGroupInformation DIANA =
UserGroupInformation.createUserForTesting("diana", new String[] { });
private static final UserGroupInformation SUPERGROUP_MEMBER =
UserGroupInformation.createUserForTesting("super", new String[] {
DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_DEFAULT });
// group member
private static final UserGroupInformation BOB = UserGroupInformation
.createUserForTesting("bob", new String[] { "groupY", "groupZ" });
protected static MiniDFSCluster cluster;
protected static Configuration conf;
private static int pathCount = 0;
private static Path path;
@Rule
public ExpectedException exception = ExpectedException.none();
private FileSystem fs, fsAsBruce, fsAsDiana, fsAsSupergroupMember, fsAsBob;
protected static void startCluster() throws IOException {
conf.setBoolean(DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_KEY, true);
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
cluster.waitActive();
}
@AfterClass
public static void shutdown() {
if (cluster != null) {
cluster.shutdown();
}
}
@Before
public void setUp() throws Exception {
pathCount += 1;
path = new Path("/p" + pathCount);
initFileSystems();
}
@After
public void destroyFileSystems() {
IOUtils.cleanup(null, fs, fsAsBruce, fsAsDiana, fsAsSupergroupMember);
fs = fsAsBruce = fsAsDiana = fsAsSupergroupMember = fsAsBob = null;
}
@Test
public void testModifyAclEntries() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo", READ_EXECUTE),
aclEntry(DEFAULT, USER, "foo", READ_EXECUTE));
fs.modifyAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", READ_EXECUTE),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", READ_EXECUTE),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testModifyAclEntriesOnlyAccess() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo", READ_EXECUTE));
fs.modifyAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", READ_EXECUTE),
aclEntry(ACCESS, GROUP, READ_EXECUTE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testModifyAclEntriesOnlyDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", READ_EXECUTE));
fs.modifyAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", READ_EXECUTE),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testModifyAclEntriesMinimal() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo", READ_WRITE));
fs.modifyAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", READ_WRITE),
aclEntry(ACCESS, GROUP, READ) }, returned);
assertPermission((short)010660);
assertAclFeature(true);
}
@Test
public void testModifyAclEntriesMinimalDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE));
fs.modifyAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testModifyAclEntriesCustomMask() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, MASK, NONE));
fs.modifyAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ) }, returned);
assertPermission((short)010600);
assertAclFeature(true);
}
@Test
public void testModifyAclEntriesStickyBit() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)01750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo", READ_EXECUTE),
aclEntry(DEFAULT, USER, "foo", READ_EXECUTE));
fs.modifyAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", READ_EXECUTE),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", READ_EXECUTE),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)011750);
assertAclFeature(true);
}
@Test(expected=FileNotFoundException.class)
public void testModifyAclEntriesPathNotFound() throws IOException {
// Path has not been created.
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE));
fs.modifyAclEntries(path, aclSpec);
}
@Test(expected=AclException.class)
public void testModifyAclEntriesDefaultOnFile() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.modifyAclEntries(path, aclSpec);
}
@Test
public void testRemoveAclEntries() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo"),
aclEntry(DEFAULT, USER, "foo"));
fs.removeAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testRemoveAclEntriesOnlyAccess() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, USER, "bar", READ_WRITE),
aclEntry(ACCESS, GROUP, READ_WRITE),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo"));
fs.removeAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "bar", READ_WRITE),
aclEntry(ACCESS, GROUP, READ_WRITE) }, returned);
assertPermission((short)010760);
assertAclFeature(true);
}
@Test
public void testRemoveAclEntriesOnlyDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, USER, "bar", READ_EXECUTE));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo"));
fs.removeAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "bar", READ_EXECUTE),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testRemoveAclEntriesMinimal() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0760));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_WRITE),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo"),
aclEntry(ACCESS, MASK));
fs.removeAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)0760);
assertAclFeature(false);
}
@Test
public void testRemoveAclEntriesMinimalDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo"),
aclEntry(ACCESS, MASK),
aclEntry(DEFAULT, USER, "foo"),
aclEntry(DEFAULT, MASK));
fs.removeAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testRemoveAclEntriesStickyBit() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)01750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo"),
aclEntry(DEFAULT, USER, "foo"));
fs.removeAclEntries(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)011750);
assertAclFeature(true);
}
@Test(expected=FileNotFoundException.class)
public void testRemoveAclEntriesPathNotFound() throws IOException {
// Path has not been created.
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo"));
fs.removeAclEntries(path, aclSpec);
}
@Test
public void testRemoveDefaultAcl() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.removeDefaultAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE) }, returned);
assertPermission((short)010770);
assertAclFeature(true);
// restart of the cluster
restartCluster();
s = fs.getAclStatus(path);
AclEntry[] afterRestart = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(returned, afterRestart);
}
@Test
public void testRemoveDefaultAclOnlyAccess() throws Exception {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
fs.removeDefaultAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE) }, returned);
assertPermission((short)010770);
assertAclFeature(true);
// restart of the cluster
restartCluster();
s = fs.getAclStatus(path);
AclEntry[] afterRestart = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(returned, afterRestart);
}
@Test
public void testRemoveDefaultAclOnlyDefault() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.removeDefaultAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)0750);
assertAclFeature(false);
// restart of the cluster
restartCluster();
s = fs.getAclStatus(path);
AclEntry[] afterRestart = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(returned, afterRestart);
}
@Test
public void testRemoveDefaultAclMinimal() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
fs.removeDefaultAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)0750);
assertAclFeature(false);
// restart of the cluster
restartCluster();
s = fs.getAclStatus(path);
AclEntry[] afterRestart = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(returned, afterRestart);
}
@Test
public void testRemoveDefaultAclStickyBit() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)01750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.removeDefaultAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE) }, returned);
assertPermission((short)011770);
assertAclFeature(true);
// restart of the cluster
restartCluster();
s = fs.getAclStatus(path);
AclEntry[] afterRestart = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(returned, afterRestart);
}
@Test(expected=FileNotFoundException.class)
public void testRemoveDefaultAclPathNotFound() throws IOException {
// Path has not been created.
fs.removeDefaultAcl(path);
}
@Test
public void testRemoveAcl() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.removeAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)0750);
assertAclFeature(false);
}
@Test
public void testRemoveAclMinimalAcl() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
fs.removeAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)0640);
assertAclFeature(false);
}
@Test
public void testRemoveAclStickyBit() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)01750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.removeAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)01750);
assertAclFeature(false);
}
@Test
public void testRemoveAclOnlyDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.removeAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)0750);
assertAclFeature(false);
}
@Test(expected=FileNotFoundException.class)
public void testRemoveAclPathNotFound() throws IOException {
// Path has not been created.
fs.removeAcl(path);
}
@Test
public void testSetAcl() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010770);
assertAclFeature(true);
}
@Test
public void testSetAclOnlyAccess() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, READ_WRITE),
aclEntry(ACCESS, USER, "foo", READ),
aclEntry(ACCESS, GROUP, READ),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", READ),
aclEntry(ACCESS, GROUP, READ) }, returned);
assertPermission((short)010640);
assertAclFeature(true);
}
@Test
public void testSetAclOnlyDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testSetAclMinimal() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0644));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, READ_WRITE),
aclEntry(ACCESS, USER, "foo", READ),
aclEntry(ACCESS, GROUP, READ),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, READ_WRITE),
aclEntry(ACCESS, GROUP, READ),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)0640);
assertAclFeature(false);
}
@Test
public void testSetAclMinimalDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE));
fs.setAcl(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010750);
assertAclFeature(true);
}
@Test
public void testSetAclCustomMask() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, READ_WRITE),
aclEntry(ACCESS, USER, "foo", READ),
aclEntry(ACCESS, GROUP, READ),
aclEntry(ACCESS, MASK, ALL),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", READ),
aclEntry(ACCESS, GROUP, READ) }, returned);
assertPermission((short)010670);
assertAclFeature(true);
}
@Test
public void testSetAclStickyBit() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)01750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)011770);
assertAclFeature(true);
}
@Test(expected=FileNotFoundException.class)
public void testSetAclPathNotFound() throws IOException {
// Path has not been created.
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, READ_WRITE),
aclEntry(ACCESS, USER, "foo", READ),
aclEntry(ACCESS, GROUP, READ),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
}
@Test(expected=AclException.class)
public void testSetAclDefaultOnFile() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
}
@Test
public void testSetPermission() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.setPermission(path, FsPermission.createImmutable((short)0700));
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010700);
assertAclFeature(true);
}
@Test
public void testSetPermissionOnlyAccess() throws IOException {
fs.create(path).close();
fs.setPermission(path, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, READ_WRITE),
aclEntry(ACCESS, USER, "foo", READ),
aclEntry(ACCESS, GROUP, READ),
aclEntry(ACCESS, OTHER, NONE));
fs.setAcl(path, aclSpec);
fs.setPermission(path, FsPermission.createImmutable((short)0600));
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", READ),
aclEntry(ACCESS, GROUP, READ) }, returned);
assertPermission((short)010600);
assertAclFeature(true);
}
@Test
public void testSetPermissionOnlyDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.setPermission(path, FsPermission.createImmutable((short)0700));
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission((short)010700);
assertAclFeature(true);
}
@Test
public void testSetPermissionCannotSetAclBit() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
fs.setPermission(path, FsPermission.createImmutable((short)0700));
assertPermission((short)0700);
fs.setPermission(path,
new FsPermissionExtension(FsPermission.
createImmutable((short)0755), true, true));
INode inode = cluster.getNamesystem().getFSDirectory()
.getINode(path.toUri().getPath(), DirOp.READ_LINK);
assertNotNull(inode);
FsPermission perm = inode.getFsPermission();
assertNotNull(perm);
assertEquals(0755, perm.toShort());
assertEquals(0755, perm.toExtendedShort());
assertAclFeature(false);
}
@Test
public void testDefaultAclNewFile() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
Path filePath = new Path(path, "file1");
fs.create(filePath).close();
AclStatus s = fs.getAclStatus(filePath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE) }, returned);
assertPermission(filePath, (short)010640);
assertAclFeature(filePath, true);
}
@Test
public void testOnlyAccessAclNewFile() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo", ALL));
fs.modifyAclEntries(path, aclSpec);
Path filePath = new Path(path, "file1");
fs.create(filePath).close();
AclStatus s = fs.getAclStatus(filePath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission(filePath, (short)0644);
assertAclFeature(filePath, false);
}
@Test
public void testDefaultMinimalAclNewFile() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE));
fs.setAcl(path, aclSpec);
Path filePath = new Path(path, "file1");
fs.create(filePath).close();
AclStatus s = fs.getAclStatus(filePath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission(filePath, (short)0640);
assertAclFeature(filePath, false);
}
@Test
public void testDefaultAclNewDir() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
Path dirPath = new Path(path, "dir1");
fs.mkdirs(dirPath);
AclStatus s = fs.getAclStatus(dirPath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission(dirPath, (short)010750);
assertAclFeature(dirPath, true);
}
@Test
public void testOnlyAccessAclNewDir() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "foo", ALL));
fs.modifyAclEntries(path, aclSpec);
Path dirPath = new Path(path, "dir1");
fs.mkdirs(dirPath);
AclStatus s = fs.getAclStatus(dirPath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission(dirPath, (short)0755);
assertAclFeature(dirPath, false);
}
@Test
public void testDefaultMinimalAclNewDir() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE));
fs.setAcl(path, aclSpec);
Path dirPath = new Path(path, "dir1");
fs.mkdirs(dirPath);
AclStatus s = fs.getAclStatus(dirPath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, OTHER, NONE) }, returned);
assertPermission(dirPath, (short)010750);
assertAclFeature(dirPath, true);
}
@Test
public void testDefaultAclNewFileIntermediate() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
Path dirPath = new Path(path, "dir1");
Path filePath = new Path(dirPath, "file1");
fs.create(filePath).close();
AclEntry[] expected = new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) };
AclStatus s = fs.getAclStatus(dirPath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(dirPath, (short)010750);
assertAclFeature(dirPath, true);
expected = new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE) };
s = fs.getAclStatus(filePath);
returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(filePath, (short)010640);
assertAclFeature(filePath, true);
}
@Test
public void testDefaultAclNewDirIntermediate() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
Path dirPath = new Path(path, "dir1");
Path subdirPath = new Path(dirPath, "subdir1");
fs.mkdirs(subdirPath);
AclEntry[] expected = new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) };
AclStatus s = fs.getAclStatus(dirPath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(dirPath, (short)010750);
assertAclFeature(dirPath, true);
s = fs.getAclStatus(subdirPath);
returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(subdirPath, (short)010750);
assertAclFeature(subdirPath, true);
}
@Test
public void testDefaultAclNewSymlinkIntermediate() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
Path filePath = new Path(path, "file1");
fs.create(filePath).close();
fs.setPermission(filePath, FsPermission.createImmutable((short)0640));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
Path dirPath = new Path(path, "dir1");
Path linkPath = new Path(dirPath, "link1");
fs.createSymlink(filePath, linkPath, true);
AclEntry[] expected = new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, NONE) };
AclStatus s = fs.getAclStatus(dirPath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(dirPath, (short)010750);
assertAclFeature(dirPath, true);
expected = new AclEntry[] { };
s = fs.getAclStatus(linkPath);
returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(linkPath, (short)0640);
assertAclFeature(linkPath, false);
s = fs.getAclStatus(filePath);
returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(filePath, (short)0640);
assertAclFeature(filePath, false);
}
@Test
public void testDefaultAclNewFileWithMode() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0755));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
Path filePath = new Path(path, "file1");
int bufferSize = cluster.getConfiguration(0).getInt(
CommonConfigurationKeys.IO_FILE_BUFFER_SIZE_KEY,
CommonConfigurationKeys.IO_FILE_BUFFER_SIZE_DEFAULT);
fs.create(filePath, new FsPermission((short)0740), false, bufferSize,
fs.getDefaultReplication(filePath), fs.getDefaultBlockSize(path), null)
.close();
AclStatus s = fs.getAclStatus(filePath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE) }, returned);
assertPermission(filePath, (short)010740);
assertAclFeature(filePath, true);
}
@Test
public void testDefaultAclNewDirWithMode() throws Exception {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0755));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
Path dirPath = new Path(path, "dir1");
fs.mkdirs(dirPath, new FsPermission((short)0740));
AclStatus s = fs.getAclStatus(dirPath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] {
aclEntry(ACCESS, USER, "foo", ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, USER, ALL),
aclEntry(DEFAULT, USER, "foo", ALL),
aclEntry(DEFAULT, GROUP, READ_EXECUTE),
aclEntry(DEFAULT, MASK, ALL),
aclEntry(DEFAULT, OTHER, READ_EXECUTE) }, returned);
assertPermission(dirPath, (short)010740);
assertAclFeature(dirPath, true);
}
@Test
public void testDefaultAclRenamedFile() throws Exception {
Path dirPath = new Path(path, "dir");
FileSystem.mkdirs(fs, dirPath, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(dirPath, aclSpec);
Path filePath = new Path(path, "file1");
fs.create(filePath).close();
fs.setPermission(filePath, FsPermission.createImmutable((short)0640));
Path renamedFilePath = new Path(dirPath, "file1");
fs.rename(filePath, renamedFilePath);
AclEntry[] expected = new AclEntry[] { };
AclStatus s = fs.getAclStatus(renamedFilePath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(renamedFilePath, (short)0640);
assertAclFeature(renamedFilePath, false);
}
@Test
public void testDefaultAclRenamedDir() throws Exception {
Path dirPath = new Path(path, "dir");
FileSystem.mkdirs(fs, dirPath, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(dirPath, aclSpec);
Path subdirPath = new Path(path, "subdir");
FileSystem.mkdirs(fs, subdirPath, FsPermission.createImmutable((short)0750));
Path renamedSubdirPath = new Path(dirPath, "subdir");
fs.rename(subdirPath, renamedSubdirPath);
AclEntry[] expected = new AclEntry[] { };
AclStatus s = fs.getAclStatus(renamedSubdirPath);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(expected, returned);
assertPermission(renamedSubdirPath, (short)0750);
assertAclFeature(renamedSubdirPath, false);
}
@Test
public void testSkipAclEnforcementPermsDisabled() throws Exception {
Path bruceDir = new Path(path, "bruce");
Path bruceFile = new Path(bruceDir, "file");
fs.mkdirs(bruceDir);
fs.setOwner(bruceDir, "bruce", null);
fsAsBruce.create(bruceFile).close();
fsAsBruce.modifyAclEntries(bruceFile, Lists.newArrayList(
aclEntry(ACCESS, USER, "diana", NONE)));
assertFilePermissionDenied(fsAsDiana, DIANA, bruceFile);
try {
conf.setBoolean(DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY, false);
restartCluster();
assertFilePermissionGranted(fsAsDiana, DIANA, bruceFile);
} finally {
conf.setBoolean(DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY, true);
restartCluster();
}
}
@Test
public void testSkipAclEnforcementSuper() throws Exception {
Path bruceDir = new Path(path, "bruce");
Path bruceFile = new Path(bruceDir, "file");
fs.mkdirs(bruceDir);
fs.setOwner(bruceDir, "bruce", null);
fsAsBruce.create(bruceFile).close();
fsAsBruce.modifyAclEntries(bruceFile, Lists.newArrayList(
aclEntry(ACCESS, USER, "diana", NONE)));
assertFilePermissionGranted(fs, DIANA, bruceFile);
assertFilePermissionGranted(fsAsBruce, DIANA, bruceFile);
assertFilePermissionDenied(fsAsDiana, DIANA, bruceFile);
assertFilePermissionGranted(fsAsSupergroupMember, SUPERGROUP_MEMBER,
bruceFile);
}
@Test
public void testModifyAclEntriesMustBeOwnerOrSuper() throws Exception {
Path bruceDir = new Path(path, "bruce");
Path bruceFile = new Path(bruceDir, "file");
fs.mkdirs(bruceDir);
fs.setOwner(bruceDir, "bruce", null);
fsAsBruce.create(bruceFile).close();
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "diana", ALL));
fsAsBruce.modifyAclEntries(bruceFile, aclSpec);
fs.modifyAclEntries(bruceFile, aclSpec);
fsAsSupergroupMember.modifyAclEntries(bruceFile, aclSpec);
exception.expect(AccessControlException.class);
fsAsDiana.modifyAclEntries(bruceFile, aclSpec);
}
@Test
public void testRemoveAclEntriesMustBeOwnerOrSuper() throws Exception {
Path bruceDir = new Path(path, "bruce");
Path bruceFile = new Path(bruceDir, "file");
fs.mkdirs(bruceDir);
fs.setOwner(bruceDir, "bruce", null);
fsAsBruce.create(bruceFile).close();
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, "diana"));
fsAsBruce.removeAclEntries(bruceFile, aclSpec);
fs.removeAclEntries(bruceFile, aclSpec);
fsAsSupergroupMember.removeAclEntries(bruceFile, aclSpec);
exception.expect(AccessControlException.class);
fsAsDiana.removeAclEntries(bruceFile, aclSpec);
}
@Test
public void testRemoveDefaultAclMustBeOwnerOrSuper() throws Exception {
Path bruceDir = new Path(path, "bruce");
Path bruceFile = new Path(bruceDir, "file");
fs.mkdirs(bruceDir);
fs.setOwner(bruceDir, "bruce", null);
fsAsBruce.create(bruceFile).close();
fsAsBruce.removeDefaultAcl(bruceFile);
fs.removeDefaultAcl(bruceFile);
fsAsSupergroupMember.removeDefaultAcl(bruceFile);
exception.expect(AccessControlException.class);
fsAsDiana.removeDefaultAcl(bruceFile);
}
@Test
public void testRemoveAclMustBeOwnerOrSuper() throws Exception {
Path bruceDir = new Path(path, "bruce");
Path bruceFile = new Path(bruceDir, "file");
fs.mkdirs(bruceDir);
fs.setOwner(bruceDir, "bruce", null);
fsAsBruce.create(bruceFile).close();
fsAsBruce.removeAcl(bruceFile);
fs.removeAcl(bruceFile);
fsAsSupergroupMember.removeAcl(bruceFile);
exception.expect(AccessControlException.class);
fsAsDiana.removeAcl(bruceFile);
}
@Test
public void testSetAclMustBeOwnerOrSuper() throws Exception {
Path bruceDir = new Path(path, "bruce");
Path bruceFile = new Path(bruceDir, "file");
fs.mkdirs(bruceDir);
fs.setOwner(bruceDir, "bruce", null);
fsAsBruce.create(bruceFile).close();
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, READ_WRITE),
aclEntry(ACCESS, USER, "diana", READ_WRITE),
aclEntry(ACCESS, GROUP, READ),
aclEntry(ACCESS, OTHER, READ));
fsAsBruce.setAcl(bruceFile, aclSpec);
fs.setAcl(bruceFile, aclSpec);
fsAsSupergroupMember.setAcl(bruceFile, aclSpec);
exception.expect(AccessControlException.class);
fsAsDiana.setAcl(bruceFile, aclSpec);
}
@Test
public void testGetAclStatusRequiresTraverseOrSuper() throws Exception {
Path bruceDir = new Path(path, "bruce");
Path bruceFile = new Path(bruceDir, "file");
fs.mkdirs(bruceDir);
fs.setOwner(bruceDir, "bruce", null);
fsAsBruce.create(bruceFile).close();
fsAsBruce.setAcl(bruceDir, Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, USER, "diana", READ),
aclEntry(ACCESS, GROUP, NONE),
aclEntry(ACCESS, OTHER, NONE)));
fsAsBruce.getAclStatus(bruceFile);
fs.getAclStatus(bruceFile);
fsAsSupergroupMember.getAclStatus(bruceFile);
exception.expect(AccessControlException.class);
fsAsDiana.getAclStatus(bruceFile);
}
@Test
public void testAccess() throws IOException, InterruptedException {
Path p1 = new Path("/p1");
fs.mkdirs(p1);
fs.setOwner(p1, BRUCE.getShortUserName(), "groupX");
fsAsBruce.setAcl(p1, Lists.newArrayList(
aclEntry(ACCESS, USER, READ),
aclEntry(ACCESS, USER, "bruce", READ),
aclEntry(ACCESS, GROUP, NONE),
aclEntry(ACCESS, OTHER, NONE)));
fsAsBruce.access(p1, FsAction.READ);
try {
fsAsBruce.access(p1, FsAction.WRITE);
fail("The access call should have failed.");
} catch (AccessControlException e) {
// expected
}
Path badPath = new Path("/bad/bad");
try {
fsAsBruce.access(badPath, FsAction.READ);
fail("The access call should have failed");
} catch (FileNotFoundException e) {
// expected
}
// Add a named group entry with only READ access
fsAsBruce.modifyAclEntries(p1, Lists.newArrayList(
aclEntry(ACCESS, GROUP, "groupY", READ)));
// Now bob should have read access, but not write
fsAsBob.access(p1, READ);
try {
fsAsBob.access(p1, WRITE);
fail("The access call should have failed.");
} catch (AccessControlException e) {
// expected;
}
// Add another named group entry with WRITE access
fsAsBruce.modifyAclEntries(p1, Lists.newArrayList(
aclEntry(ACCESS, GROUP, "groupZ", WRITE)));
// Now bob should have write access
fsAsBob.access(p1, WRITE);
// Add a named user entry to deny bob
fsAsBruce.modifyAclEntries(p1,
Lists.newArrayList(aclEntry(ACCESS, USER, "bob", NONE)));
try {
fsAsBob.access(p1, READ);
fail("The access call should have failed.");
} catch (AccessControlException e) {
// expected;
}
}
@Test
public void testEffectiveAccess() throws Exception {
Path p1 = new Path("/testEffectiveAccess");
fs.mkdirs(p1);
// give all access at first
fs.setPermission(p1, FsPermission.valueOf("-rwxrwxrwx"));
AclStatus aclStatus = fs.getAclStatus(p1);
assertEquals("Entries should be empty", 0, aclStatus.getEntries().size());
assertEquals("Permission should be carried by AclStatus",
fs.getFileStatus(p1).getPermission(), aclStatus.getPermission());
// Add a named entries with all access
fs.modifyAclEntries(p1, Lists.newArrayList(
aclEntry(ACCESS, USER, "bruce", ALL),
aclEntry(ACCESS, GROUP, "groupY", ALL)));
aclStatus = fs.getAclStatus(p1);
assertEquals("Entries should contain owner group entry also", 3, aclStatus
.getEntries().size());
// restrict the access
fs.setPermission(p1, FsPermission.valueOf("-rwxr-----"));
// latest permissions should be reflected as effective permission
aclStatus = fs.getAclStatus(p1);
List<AclEntry> entries = aclStatus.getEntries();
for (AclEntry aclEntry : entries) {
if (aclEntry.getName() != null || aclEntry.getType() == GROUP) {
assertEquals(FsAction.ALL, aclEntry.getPermission());
assertEquals(FsAction.READ, aclStatus.getEffectivePermission(aclEntry));
}
}
fsAsBruce.access(p1, READ);
try {
fsAsBruce.access(p1, WRITE);
fail("Access should not be given");
} catch (AccessControlException e) {
// expected
}
fsAsBob.access(p1, READ);
try {
fsAsBob.access(p1, WRITE);
fail("Access should not be given");
} catch (AccessControlException e) {
// expected
}
}
/**
* Verify the de-duplication of AclFeatures with same entries.
*
* @throws Exception
*/
@Test
public void testDeDuplication() throws Exception {
// This test needs to verify the count of the references which is held by
// static data structure. So shutting down entire cluster to get the fresh
// data.
shutdown();
AclStorage.getUniqueAclFeatures().clear();
startCluster();
setUp();
int currentSize = 0;
Path p1 = new Path("/testDeduplication");
{
// unique default AclEntries for this test
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(DEFAULT, USER, "testdeduplicateuser", ALL),
aclEntry(DEFAULT, GROUP, "testdeduplicategroup", ALL));
fs.mkdirs(p1);
fs.modifyAclEntries(p1, aclSpec);
assertEquals("One more ACL feature should be unique", currentSize + 1,
AclStorage.getUniqueAclFeatures().getUniqueElementsSize());
currentSize++;
}
Path child1 = new Path(p1, "child1");
AclFeature child1AclFeature;
{
// new child dir should copy entries from its parent.
fs.mkdirs(child1);
assertEquals("One more ACL feature should be unique", currentSize + 1,
AclStorage.getUniqueAclFeatures().getUniqueElementsSize());
child1AclFeature = getAclFeature(child1, cluster);
assertEquals("Reference count should be 1", 1,
child1AclFeature.getRefCount());
currentSize++;
}
Path child2 = new Path(p1, "child2");
{
// new child dir should copy entries from its parent. But all entries are
// same as its sibling without any more acl changes.
fs.mkdirs(child2);
assertEquals("existing AclFeature should be re-used", currentSize,
AclStorage.getUniqueAclFeatures().getUniqueElementsSize());
AclFeature child2AclFeature = getAclFeature(child1, cluster);
assertSame("Same Aclfeature should be re-used", child1AclFeature,
child2AclFeature);
assertEquals("Reference count should be 2", 2,
child2AclFeature.getRefCount());
}
{
// modification of ACL on should decrement the original reference count
// and increase new one.
List<AclEntry> aclSpec = Lists.newArrayList(aclEntry(ACCESS, USER,
"user1", ALL));
fs.modifyAclEntries(child1, aclSpec);
AclFeature modifiedAclFeature = getAclFeature(child1, cluster);
assertEquals("Old Reference count should be 1", 1,
child1AclFeature.getRefCount());
assertEquals("New Reference count should be 1", 1,
modifiedAclFeature.getRefCount());
// removing the new added ACL entry should refer to old ACLfeature
AclEntry aclEntry = new AclEntry.Builder().setScope(ACCESS).setType(USER)
.setName("user1").build();
fs.removeAclEntries(child1, Lists.newArrayList(aclEntry));
assertEquals("Old Reference count should be 2 again", 2,
child1AclFeature.getRefCount());
assertEquals("New Reference count should be 0", 0,
modifiedAclFeature.getRefCount());
}
{
// verify the reference count on deletion of Acls
fs.removeAcl(child2);
assertEquals("Reference count should be 1", 1,
child1AclFeature.getRefCount());
}
{
// verify the reference count on deletion of dir with ACL
fs.delete(child1, true);
assertEquals("Reference count should be 0", 0,
child1AclFeature.getRefCount());
}
Path file1 = new Path(p1, "file1");
Path file2 = new Path(p1, "file2");
AclFeature fileAclFeature;
{
// Using same reference on creation of file
fs.create(file1).close();
fileAclFeature = getAclFeature(file1, cluster);
assertEquals("Reference count should be 1", 1,
fileAclFeature.getRefCount());
fs.create(file2).close();
assertEquals("Reference count should be 2", 2,
fileAclFeature.getRefCount());
}
{
// modifying ACLs on file should decrease the reference count on old
// instance and increase on the new instance
List<AclEntry> aclSpec = Lists.newArrayList(aclEntry(ACCESS, USER,
"user1", ALL));
// adding new ACL entry
fs.modifyAclEntries(file1, aclSpec);
AclFeature modifiedFileAcl = getAclFeature(file1, cluster);
assertEquals("Old Reference count should be 1", 1,
fileAclFeature.getRefCount());
assertEquals("New Reference count should be 1", 1,
modifiedFileAcl.getRefCount());
// removing the new added ACL entry should refer to old ACLfeature
AclEntry aclEntry = new AclEntry.Builder().setScope(ACCESS).setType(USER)
.setName("user1").build();
fs.removeAclEntries(file1, Lists.newArrayList(aclEntry));
assertEquals("Old Reference count should be 2", 2,
fileAclFeature.getRefCount());
assertEquals("New Reference count should be 0", 0,
modifiedFileAcl.getRefCount());
}
{
// reference count should be decreased on deletion of files with ACLs
fs.delete(file2, true);
assertEquals("Reference count should be decreased on delete of the file",
1, fileAclFeature.getRefCount());
fs.delete(file1, true);
assertEquals("Reference count should be decreased on delete of the file",
0, fileAclFeature.getRefCount());
// On reference count reaches 0 instance should be removed from map
fs.create(file1).close();
AclFeature newFileAclFeature = getAclFeature(file1, cluster);
assertNotSame("Instance should be different on reference count 0",
fileAclFeature, newFileAclFeature);
fileAclFeature = newFileAclFeature;
}
Map<AclFeature, Integer> restartRefCounter = new HashMap<>();
// Restart the Namenode to check the references.
// Here reference counts will not be same after restart because, while
// shutting down namenode will not call any removal of AclFeature.
// However this is applicable only in case of tests as in real-cluster JVM
// itself will be new.
List<AclFeature> entriesBeforeRestart = AclStorage.getUniqueAclFeatures()
.getEntries();
{
//restart by loading edits
for (AclFeature aclFeature : entriesBeforeRestart) {
restartRefCounter.put(aclFeature, aclFeature.getRefCount());
}
cluster.restartNameNode(true);
List<AclFeature> entriesAfterRestart = AclStorage.getUniqueAclFeatures()
.getEntries();
assertEquals("Entries before and after should be same",
entriesBeforeRestart, entriesAfterRestart);
for (AclFeature aclFeature : entriesAfterRestart) {
int before = restartRefCounter.get(aclFeature);
assertEquals("ReferenceCount After Restart should be doubled",
before * 2, aclFeature.getRefCount());
}
}
{
//restart by loading fsimage
cluster.getNameNodeRpc()
.setSafeMode(SafeModeAction.SAFEMODE_ENTER, false);
cluster.getNameNodeRpc().saveNamespace();
cluster.getNameNodeRpc()
.setSafeMode(SafeModeAction.SAFEMODE_LEAVE, false);
cluster.restartNameNode(true);
List<AclFeature> entriesAfterRestart = AclStorage.getUniqueAclFeatures()
.getEntries();
assertEquals("Entries before and after should be same",
entriesBeforeRestart, entriesAfterRestart);
for (AclFeature aclFeature : entriesAfterRestart) {
int before = restartRefCounter.get(aclFeature);
assertEquals("ReferenceCount After 2 Restarts should be tripled",
before * 3, aclFeature.getRefCount());
}
}
}
/**
* Creates a FileSystem for the super-user.
*
* @return FileSystem for super-user
* @throws Exception if creation fails
*/
protected FileSystem createFileSystem() throws Exception {
return cluster.getFileSystem();
}
/**
* Creates a FileSystem for a specific user.
*
* @param user UserGroupInformation specific user
* @return FileSystem for specific user
* @throws Exception if creation fails
*/
protected FileSystem createFileSystem(UserGroupInformation user)
throws Exception {
return DFSTestUtil.getFileSystemAs(user, cluster.getConfiguration(0));
}
/**
* Initializes all FileSystem instances used in the tests.
*
* @throws Exception if initialization fails
*/
private void initFileSystems() throws Exception {
fs = createFileSystem();
fsAsBruce = createFileSystem(BRUCE);
fsAsDiana = createFileSystem(DIANA);
fsAsBob = createFileSystem(BOB);
fsAsSupergroupMember = createFileSystem(SUPERGROUP_MEMBER);
}
/**
* Restarts the cluster without formatting, so all data is preserved.
*
* @throws Exception if restart fails
*/
private void restartCluster() throws Exception {
destroyFileSystems();
shutdown();
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).format(false)
.build();
cluster.waitActive();
initFileSystems();
}
/**
* Asserts whether or not the inode for the test path has an AclFeature.
*
* @param expectAclFeature boolean true if an AclFeature must be present,
* false if an AclFeature must not be present
* @throws IOException thrown if there is an I/O error
*/
private static void assertAclFeature(boolean expectAclFeature)
throws IOException {
assertAclFeature(path, expectAclFeature);
}
private static void assertAclFeature(Path pathToCheck,
boolean expectAclFeature) throws IOException {
assertAclFeature(cluster, pathToCheck, expectAclFeature);
}
/**
* Asserts whether or not the inode for a specific path has an AclFeature.
*
* @param miniCluster the cluster into which the path resides
* @param pathToCheck Path inode to check
* @param expectAclFeature boolean true if an AclFeature must be present,
* false if an AclFeature must not be present
* @throws IOException thrown if there is an I/O error
*/
public static void assertAclFeature(final MiniDFSCluster miniCluster,
Path pathToCheck, boolean expectAclFeature) throws IOException {
AclFeature aclFeature = getAclFeature(pathToCheck, miniCluster);
if (expectAclFeature) {
assertNotNull(aclFeature);
// Intentionally capturing a reference to the entries, not using nested
// calls. This way, we get compile-time enforcement that the entries are
// stored in an ImmutableList.
ImmutableList<AclEntry> entries = AclStorage
.getEntriesFromAclFeature(aclFeature);
assertFalse(entries.isEmpty());
} else {
assertNull(aclFeature);
}
}
/**
* Get AclFeature for the path
*/
public static AclFeature getAclFeature(Path pathToCheck,
MiniDFSCluster cluster) throws IOException {
INode inode = cluster.getNamesystem().getFSDirectory()
.getINode(pathToCheck.toUri().getPath(), DirOp.READ_LINK);
assertNotNull(inode);
AclFeature aclFeature = inode.getAclFeature();
return aclFeature;
}
/**
* Asserts the value of the FsPermission bits on the inode of the test path.
*
* @param perm short expected permission bits
* @throws IOException thrown if there is an I/O error
*/
private void assertPermission(short perm) throws IOException {
assertPermission(path, perm);
}
/**
* Asserts the value of the FsPermission bits on the inode of a specific path.
*
* @param pathToCheck Path inode to check
* @param perm short expected permission bits
* @throws IOException thrown if there is an I/O error
*/
private void assertPermission(Path pathToCheck, short perm)
throws IOException {
AclTestHelpers.assertPermission(fs, pathToCheck, perm);
}
}