HDFS-5613. NameNode: implement handling of ACLs in combination with symlinks. Contributed by Chris Nauroth.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-4685@1559804 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2fbe8235dc
commit
9df33876ff
@ -36,6 +36,9 @@ HDFS-4685 (Unreleased)
|
|||||||
HDFS-5612. NameNode: change all permission checks to enforce ACLs in
|
HDFS-5612. NameNode: change all permission checks to enforce ACLs in
|
||||||
addition to permissions. (Chris Nauroth via wheat9)
|
addition to permissions. (Chris Nauroth via wheat9)
|
||||||
|
|
||||||
|
HDFS-5613. NameNode: implement handling of ACLs in combination with
|
||||||
|
symlinks. (Chris Nauroth via wheat9)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
/**
|
/**
|
||||||
* Helper methods useful for writing ACL tests.
|
* Helper methods useful for writing ACL tests.
|
||||||
*/
|
*/
|
||||||
final class AclTestHelpers {
|
public final class AclTestHelpers {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new AclEntry with scope, type and permission (no name).
|
* Create a new AclEntry with scope, type and permission (no name).
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.hadoop.security;
|
package org.apache.hadoop.security;
|
||||||
|
|
||||||
|
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.apache.hadoop.hdfs.server.namenode.AclTestHelpers.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@ -24,6 +28,7 @@
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.PrivilegedExceptionAction;
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@ -101,8 +106,43 @@ public void tearDown() throws Exception {
|
|||||||
|
|
||||||
@Test(timeout = 5000)
|
@Test(timeout = 5000)
|
||||||
public void testDelete() throws Exception {
|
public void testDelete() throws Exception {
|
||||||
// Try to delete where the symlink's parent dir is not writable
|
|
||||||
fs.setPermission(linkParent, new FsPermission((short) 0555));
|
fs.setPermission(linkParent, new FsPermission((short) 0555));
|
||||||
|
doDeleteLinkParentNotWritable();
|
||||||
|
|
||||||
|
fs.setPermission(linkParent, new FsPermission((short) 0777));
|
||||||
|
fs.setPermission(targetParent, new FsPermission((short) 0555));
|
||||||
|
fs.setPermission(target, new FsPermission((short) 0555));
|
||||||
|
doDeleteTargetParentAndTargetNotWritable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAclDelete() throws Exception {
|
||||||
|
fs.setAcl(linkParent, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
doDeleteLinkParentNotWritable();
|
||||||
|
|
||||||
|
fs.setAcl(linkParent, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
fs.setAcl(targetParent, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
fs.setAcl(target, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
doDeleteTargetParentAndTargetNotWritable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDeleteLinkParentNotWritable() throws Exception {
|
||||||
|
// Try to delete where the symlink's parent dir is not writable
|
||||||
try {
|
try {
|
||||||
user.doAs(new PrivilegedExceptionAction<Object>() {
|
user.doAs(new PrivilegedExceptionAction<Object>() {
|
||||||
@Override
|
@Override
|
||||||
@ -116,11 +156,11 @@ public Object run() throws IOException {
|
|||||||
} catch (AccessControlException e) {
|
} catch (AccessControlException e) {
|
||||||
GenericTestUtils.assertExceptionContains("Permission denied", e);
|
GenericTestUtils.assertExceptionContains("Permission denied", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDeleteTargetParentAndTargetNotWritable() throws Exception {
|
||||||
// Try a delete where the symlink parent dir is writable,
|
// Try a delete where the symlink parent dir is writable,
|
||||||
// but the target's parent and target are not
|
// but the target's parent and target are not
|
||||||
fs.setPermission(linkParent, new FsPermission((short) 0777));
|
|
||||||
fs.setPermission(targetParent, new FsPermission((short) 0555));
|
|
||||||
fs.setPermission(target, new FsPermission((short) 0555));
|
|
||||||
user.doAs(new PrivilegedExceptionAction<Object>() {
|
user.doAs(new PrivilegedExceptionAction<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public Object run() throws IOException {
|
public Object run() throws IOException {
|
||||||
@ -139,6 +179,20 @@ public Object run() throws IOException {
|
|||||||
@Test(timeout = 5000)
|
@Test(timeout = 5000)
|
||||||
public void testReadWhenTargetNotReadable() throws Exception {
|
public void testReadWhenTargetNotReadable() throws Exception {
|
||||||
fs.setPermission(target, new FsPermission((short) 0000));
|
fs.setPermission(target, new FsPermission((short) 0000));
|
||||||
|
doReadTargetNotReadable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAclReadTargetNotReadable() throws Exception {
|
||||||
|
fs.setAcl(target, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, READ_WRITE),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), NONE),
|
||||||
|
aclEntry(ACCESS, GROUP, READ),
|
||||||
|
aclEntry(ACCESS, OTHER, READ)));
|
||||||
|
doReadTargetNotReadable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doReadTargetNotReadable() throws Exception {
|
||||||
try {
|
try {
|
||||||
user.doAs(new PrivilegedExceptionAction<Object>() {
|
user.doAs(new PrivilegedExceptionAction<Object>() {
|
||||||
@Override
|
@Override
|
||||||
@ -157,8 +211,22 @@ public Object run() throws IOException {
|
|||||||
|
|
||||||
@Test(timeout = 5000)
|
@Test(timeout = 5000)
|
||||||
public void testFileStatus() throws Exception {
|
public void testFileStatus() throws Exception {
|
||||||
// Try to getFileLinkStatus the link when the target is not readable
|
|
||||||
fs.setPermission(target, new FsPermission((short) 0000));
|
fs.setPermission(target, new FsPermission((short) 0000));
|
||||||
|
doGetFileLinkStatusTargetNotReadable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAclGetFileLinkStatusTargetNotReadable() throws Exception {
|
||||||
|
fs.setAcl(target, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, READ_WRITE),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), NONE),
|
||||||
|
aclEntry(ACCESS, GROUP, READ),
|
||||||
|
aclEntry(ACCESS, OTHER, READ)));
|
||||||
|
doGetFileLinkStatusTargetNotReadable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doGetFileLinkStatusTargetNotReadable() throws Exception {
|
||||||
|
// Try to getFileLinkStatus the link when the target is not readable
|
||||||
user.doAs(new PrivilegedExceptionAction<Object>() {
|
user.doAs(new PrivilegedExceptionAction<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public Object run() throws IOException {
|
public Object run() throws IOException {
|
||||||
@ -176,9 +244,28 @@ public Object run() throws IOException {
|
|||||||
|
|
||||||
@Test(timeout = 5000)
|
@Test(timeout = 5000)
|
||||||
public void testRenameLinkTargetNotWritableFC() throws Exception {
|
public void testRenameLinkTargetNotWritableFC() throws Exception {
|
||||||
// Rename the link when the target and parent are not writable
|
|
||||||
fs.setPermission(target, new FsPermission((short) 0555));
|
fs.setPermission(target, new FsPermission((short) 0555));
|
||||||
fs.setPermission(targetParent, new FsPermission((short) 0555));
|
fs.setPermission(targetParent, new FsPermission((short) 0555));
|
||||||
|
doRenameLinkTargetNotWritableFC();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAclRenameTargetNotWritableFC() throws Exception {
|
||||||
|
fs.setAcl(target, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
fs.setAcl(targetParent, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
doRenameLinkTargetNotWritableFC();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRenameLinkTargetNotWritableFC() throws Exception {
|
||||||
|
// Rename the link when the target and parent are not writable
|
||||||
user.doAs(new PrivilegedExceptionAction<Object>() {
|
user.doAs(new PrivilegedExceptionAction<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public Object run() throws IOException {
|
public Object run() throws IOException {
|
||||||
@ -197,8 +284,22 @@ public Object run() throws IOException {
|
|||||||
|
|
||||||
@Test(timeout = 5000)
|
@Test(timeout = 5000)
|
||||||
public void testRenameSrcNotWritableFC() throws Exception {
|
public void testRenameSrcNotWritableFC() throws Exception {
|
||||||
// Rename the link when the target and parent are not writable
|
|
||||||
fs.setPermission(linkParent, new FsPermission((short) 0555));
|
fs.setPermission(linkParent, new FsPermission((short) 0555));
|
||||||
|
doRenameSrcNotWritableFC();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAclRenameSrcNotWritableFC() throws Exception {
|
||||||
|
fs.setAcl(linkParent, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
doRenameSrcNotWritableFC();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRenameSrcNotWritableFC() throws Exception {
|
||||||
|
// Rename the link when the target and parent are not writable
|
||||||
try {
|
try {
|
||||||
user.doAs(new PrivilegedExceptionAction<Object>() {
|
user.doAs(new PrivilegedExceptionAction<Object>() {
|
||||||
@Override
|
@Override
|
||||||
@ -220,9 +321,28 @@ public Object run() throws IOException {
|
|||||||
|
|
||||||
@Test(timeout = 5000)
|
@Test(timeout = 5000)
|
||||||
public void testRenameLinkTargetNotWritableFS() throws Exception {
|
public void testRenameLinkTargetNotWritableFS() throws Exception {
|
||||||
// Rename the link when the target and parent are not writable
|
|
||||||
fs.setPermission(target, new FsPermission((short) 0555));
|
fs.setPermission(target, new FsPermission((short) 0555));
|
||||||
fs.setPermission(targetParent, new FsPermission((short) 0555));
|
fs.setPermission(targetParent, new FsPermission((short) 0555));
|
||||||
|
doRenameLinkTargetNotWritableFS();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAclRenameTargetNotWritableFS() throws Exception {
|
||||||
|
fs.setAcl(target, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
fs.setAcl(targetParent, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
doRenameLinkTargetNotWritableFS();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRenameLinkTargetNotWritableFS() throws Exception {
|
||||||
|
// Rename the link when the target and parent are not writable
|
||||||
user.doAs(new PrivilegedExceptionAction<Object>() {
|
user.doAs(new PrivilegedExceptionAction<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public Object run() throws IOException {
|
public Object run() throws IOException {
|
||||||
@ -241,8 +361,22 @@ public Object run() throws IOException {
|
|||||||
|
|
||||||
@Test(timeout = 5000)
|
@Test(timeout = 5000)
|
||||||
public void testRenameSrcNotWritableFS() throws Exception {
|
public void testRenameSrcNotWritableFS() throws Exception {
|
||||||
// Rename the link when the target and parent are not writable
|
|
||||||
fs.setPermission(linkParent, new FsPermission((short) 0555));
|
fs.setPermission(linkParent, new FsPermission((short) 0555));
|
||||||
|
doRenameSrcNotWritableFS();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAclRenameSrcNotWritableFS() throws Exception {
|
||||||
|
fs.setAcl(linkParent, Arrays.asList(
|
||||||
|
aclEntry(ACCESS, USER, ALL),
|
||||||
|
aclEntry(ACCESS, USER, user.getUserName(), READ_EXECUTE),
|
||||||
|
aclEntry(ACCESS, GROUP, ALL),
|
||||||
|
aclEntry(ACCESS, OTHER, ALL)));
|
||||||
|
doRenameSrcNotWritableFS();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRenameSrcNotWritableFS() throws Exception {
|
||||||
|
// Rename the link when the target and parent are not writable
|
||||||
try {
|
try {
|
||||||
user.doAs(new PrivilegedExceptionAction<Object>() {
|
user.doAs(new PrivilegedExceptionAction<Object>() {
|
||||||
@Override
|
@Override
|
||||||
@ -258,6 +392,4 @@ public Object run() throws IOException {
|
|||||||
GenericTestUtils.assertExceptionContains("Permission denied", e);
|
GenericTestUtils.assertExceptionContains("Permission denied", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user