You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by jh...@apache.org on 2017/10/07 00:06:35 UTC
[31/50] [abbrv] hadoop git commit: HADOOP-14899. Restrict Access to
setPermission operation when authorization is enabled in WASB Contributed by
Kannapiran Srinivasan.
HADOOP-14899. Restrict Access to setPermission operation when authorization is enabled in WASB
Contributed by Kannapiran Srinivasan.
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/572cdb54
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/572cdb54
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/572cdb54
Branch: refs/heads/YARN-5734
Commit: 572cdb54632d8a29c4d9900f9e988ada8e3fe2ec
Parents: 49ae538
Author: Steve Loughran <st...@apache.org>
Authored: Fri Oct 6 17:43:38 2017 +0100
Committer: Steve Loughran <st...@apache.org>
Committed: Fri Oct 6 17:43:38 2017 +0100
----------------------------------------------------------------------
.../hadoop/fs/azure/NativeAzureFileSystem.java | 146 ++++++++--
.../hadoop-azure/src/site/markdown/index.md | 18 +-
.../TestNativeAzureFileSystemAuthorization.java | 276 +++++++++++++++++--
3 files changed, 391 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hadoop/blob/572cdb54/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azure/NativeAzureFileSystem.java
----------------------------------------------------------------------
diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azure/NativeAzureFileSystem.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azure/NativeAzureFileSystem.java
index 2e5241d..07cfe72 100644
--- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azure/NativeAzureFileSystem.java
+++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azure/NativeAzureFileSystem.java
@@ -79,6 +79,8 @@ import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticatedURL;
import org.apache.hadoop.util.Progressable;
import org.apache.hadoop.util.Time;
+
+import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -699,10 +701,29 @@ public class NativeAzureFileSystem extends FileSystem {
* Configuration property used to specify list of users that can perform
* chown operation when authorization is enabled in WASB.
*/
- public static final String AZURE_CHOWN_USERLIST_PROPERTY_NAME = "fs.azure.chown.allowed.userlist";
+ public static final String AZURE_CHOWN_USERLIST_PROPERTY_NAME =
+ "fs.azure.chown.allowed.userlist";
static final String AZURE_CHOWN_USERLIST_PROPERTY_DEFAULT_VALUE = "*";
+ /**
+ * Configuration property used to specify list of daemon users that can
+ * perform chmod operation when authorization is enabled in WASB.
+ */
+ public static final String AZURE_DAEMON_USERLIST_PROPERTY_NAME =
+ "fs.azure.daemon.userlist";
+
+ static final String AZURE_DAEMON_USERLIST_PROPERTY_DEFAULT_VALUE = "*";
+
+ /**
+ * Configuration property used to specify list of users that can perform
+ * chmod operation when authorization is enabled in WASB.
+ */
+ public static final String AZURE_CHMOD_USERLIST_PROPERTY_NAME =
+ "fs.azure.chmod.allowed.userlist";
+
+ static final String AZURE_CHMOD_USERLIST_PROPERTY_DEFAULT_VALUE = "*";
+
static final String AZURE_BLOCK_LOCATION_HOST_PROPERTY_NAME =
"fs.azure.block.location.impersonatedhost";
private static final String AZURE_BLOCK_LOCATION_HOST_DEFAULT =
@@ -1189,7 +1210,9 @@ public class NativeAzureFileSystem extends FileSystem {
private DelegationTokenAuthenticatedURL authURL;
private DelegationTokenAuthenticatedURL.Token authToken = new DelegationTokenAuthenticatedURL.Token();
private String credServiceUrl;
-
+ private List<String> chownAllowedUsers;
+ private List<String> chmodAllowedUsers;
+ private List<String> daemonUsers;
/**
* Configuration key to enable authorization support in WASB.
*/
@@ -1366,6 +1389,19 @@ public class NativeAzureFileSystem extends FileSystem {
this.authorizer =
new RemoteWasbAuthorizerImpl();
authorizer.init(conf);
+
+ this.chmodAllowedUsers =
+ Arrays.asList(conf.getTrimmedStrings(
+ AZURE_CHMOD_USERLIST_PROPERTY_NAME,
+ AZURE_CHMOD_USERLIST_PROPERTY_DEFAULT_VALUE));
+ this.chownAllowedUsers =
+ Arrays.asList(conf.getTrimmedStrings(
+ AZURE_CHOWN_USERLIST_PROPERTY_NAME,
+ AZURE_CHOWN_USERLIST_PROPERTY_DEFAULT_VALUE));
+ this.daemonUsers =
+ Arrays.asList(conf.getTrimmedStrings(
+ AZURE_DAEMON_USERLIST_PROPERTY_NAME,
+ AZURE_DAEMON_USERLIST_PROPERTY_DEFAULT_VALUE));
}
if (UserGroupInformation.isSecurityEnabled() && kerberosSupportEnabled) {
@@ -3446,6 +3482,27 @@ public class NativeAzureFileSystem extends FileSystem {
if (metadata == null) {
throw new FileNotFoundException("File doesn't exist: " + p);
}
+
+ // If authorization is enabled, check if the user is
+ // part of chmod allowed list or a daemon user or owner of the file/folder
+ if (azureAuthorization) {
+ UserGroupInformation currentUgi = UserGroupInformation.getCurrentUser();
+
+ // Check if the user is part of chown allowed list or a daemon user.
+ if (!isAllowedUser(currentUgi.getShortUserName(), chmodAllowedUsers)
+ && !isAllowedUser(currentUgi.getShortUserName(), daemonUsers)) {
+
+ //Check if the user is the owner of the file.
+ String owner = metadata.getPermissionStatus().getUserName();
+ if (!currentUgi.getShortUserName().equals(owner)) {
+ throw new WasbAuthorizationException(
+ String.format("user '%s' does not have the privilege to "
+ + "change the permission of files/folders.",
+ currentUgi.getShortUserName()));
+ }
+ }
+ }
+
permission = applyUMask(permission,
metadata.isDir() ? UMaskApplyMode.ChangeExistingDirectory
: UMaskApplyMode.ChangeExistingFile);
@@ -3491,26 +3548,14 @@ public class NativeAzureFileSystem extends FileSystem {
* to change the ownership of file/folder
*/
if (this.azureAuthorization && username != null) {
- String[] listOfUsers = getConf().getTrimmedStrings(AZURE_CHOWN_USERLIST_PROPERTY_NAME,
- AZURE_CHOWN_USERLIST_PROPERTY_DEFAULT_VALUE);
- boolean shouldSkipUserCheck = listOfUsers.length == 1 && listOfUsers[0].equals("*");
- // skip the check if the chown allowed users config value is set as '*'
- if (!shouldSkipUserCheck) {
- UserGroupInformation currentUgi = UserGroupInformation.getCurrentUser();
- UserGroupInformation actualUgi = currentUgi.getRealUser();
+ UserGroupInformation currentUgi = UserGroupInformation.getCurrentUser();
- if (actualUgi == null) {
- actualUgi = currentUgi;
- }
-
- List<String> userList = Arrays.asList(listOfUsers);
- if (userList.contains("*")) {
- throw new IllegalArgumentException("User list must contain "
- + "either '*' or list of user names, but not both.");
- } else if (!userList.contains(actualUgi.getShortUserName())) {
- throw new WasbAuthorizationException(String.format("user '%s' does not have the privilege to change the ownership of files/folders.",
- actualUgi.getShortUserName()));
- }
+ if (!isAllowedUser(currentUgi.getShortUserName(),
+ chownAllowedUsers)) {
+ throw new WasbAuthorizationException(
+ String.format("user '%s' does not have the privilege to change "
+ + "the ownership of files/folders.",
+ currentUgi.getShortUserName()));
}
}
@@ -3528,6 +3573,38 @@ public class NativeAzureFileSystem extends FileSystem {
}
}
+ /**
+ * Is the user allowed?
+ * <ol>
+ * <li>No user: false</li>
+ * <li>Empty list: false</li>
+ * <li>List == ["*"]: true</li>
+ * <li>Otherwise: is the user in the list?</li>
+ * </ol>
+ * @param username user to check; may be null
+ * @param userList list of users; may be null or empty
+ * @return
+ * @throws IllegalArgumentException if the userList is invalid.
+ */
+ private boolean isAllowedUser(String username, List<String> userList) {
+
+ if (null == userList || userList.isEmpty()) {
+ return false;
+ }
+
+ boolean shouldSkipUserCheck = userList.size() == 1
+ && userList.get(0).equals("*");
+
+ // skip the check if the allowed users config value is set as '*'
+ if (!shouldSkipUserCheck) {
+ Preconditions.checkArgument(!userList.contains("*"),
+ "User list must contain either '*' or a list of user names,"
+ + " but not both.");
+ return userList.contains(username);
+ }
+ return true;
+ }
+
@Override
public synchronized void close() throws IOException {
if (isClosed) {
@@ -3779,4 +3856,31 @@ public class NativeAzureFileSystem extends FileSystem {
}
return owner;
}
+
+ /**
+ * Helper method to update the chownAllowedUsers in tests.
+ * @param chownAllowedUsers list of chown allowed users
+ */
+ @VisibleForTesting
+ void updateChownAllowedUsers(List<String> chownAllowedUsers) {
+ this.chownAllowedUsers = chownAllowedUsers;
+ }
+
+ /**
+ * Helper method to update the chmodAllowedUsers in tests.
+ * @param chmodAllowedUsers list of chmod allowed users
+ */
+ @VisibleForTesting
+ void updateChmodAllowedUsers(List<String> chmodAllowedUsers) {
+ this.chmodAllowedUsers = chmodAllowedUsers;
+ }
+
+ /**
+ * Helper method to update the daemonUsers in tests.
+ * @param daemonUsers list of daemon users
+ */
+ @VisibleForTesting
+ void updateDaemonUsers(List<String> daemonUsers) {
+ this.daemonUsers = daemonUsers;
+ }
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/572cdb54/hadoop-tools/hadoop-azure/src/site/markdown/index.md
----------------------------------------------------------------------
diff --git a/hadoop-tools/hadoop-azure/src/site/markdown/index.md b/hadoop-tools/hadoop-azure/src/site/markdown/index.md
index 876d7cc..3f29a6e 100644
--- a/hadoop-tools/hadoop-azure/src/site/markdown/index.md
+++ b/hadoop-tools/hadoop-azure/src/site/markdown/index.md
@@ -463,7 +463,7 @@ The service is expected to return a response in JSON format for GETDELEGATIONTOK
When authorization is enabled, only the users listed in the following configuration
are allowed to change the owning user of files/folders in WASB. The configuration
-value takes a comma seperated list of user names who are allowed to perform chown.
+value takes a comma separated list of user names who are allowed to perform chown.
```xml
<property>
@@ -471,6 +471,22 @@ value takes a comma seperated list of user names who are allowed to perform chow
<value>user1,user2</value>
</property>
```
+### chmod behaviour when authorization is enabled in WASB
+
+When authorization is enabled, only the owner and the users listed in the
+following configurations are allowed to change the permissions of files/folders in WASB.
+The configuration value takes a comma separated list of user names who are allowed to perform chmod.
+
+```xml
+<property>
+ <name>fs.azure.daemon.userlist</name>
+ <value>user1,user2</value>
+</property>
+<property>
+ <name>fs.azure.chmod.allowed.userlist</name>
+ <value>userA,userB</value>
+</property>
+```
Caching of both SAS keys and Authorization responses can be enabled using the following setting:
The cache settings are applicable only when fs.azure.authorization is enabled.
http://git-wip-us.apache.org/repos/asf/hadoop/blob/572cdb54/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azure/TestNativeAzureFileSystemAuthorization.java
----------------------------------------------------------------------
diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azure/TestNativeAzureFileSystemAuthorization.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azure/TestNativeAzureFileSystemAuthorization.java
index 4e7b6fb..9a5e6e0 100644
--- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azure/TestNativeAzureFileSystemAuthorization.java
+++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azure/TestNativeAzureFileSystemAuthorization.java
@@ -21,10 +21,14 @@ package org.apache.hadoop.fs.azure;
import java.io.FileNotFoundException;
import java.security.PrivilegedExceptionAction;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
+import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.contract.ContractTestUtils;
import org.apache.hadoop.fs.permission.FsPermission;
@@ -49,6 +53,8 @@ import static org.junit.Assert.assertEquals;
public class TestNativeAzureFileSystemAuthorization
extends AbstractWasbTestBase {
+ private static final short FULL_PERMISSION_WITH_STICKYBIT = 1777;
+
@VisibleForTesting
protected MockWasbAuthorizerImpl authorizer;
@@ -66,6 +72,8 @@ public class TestNativeAzureFileSystemAuthorization
conf.set(RemoteWasbAuthorizerImpl.KEY_REMOTE_AUTH_SERVICE_URLS, "http://localhost/");
conf.set(NativeAzureFileSystem.AZURE_CHOWN_USERLIST_PROPERTY_NAME, "user1 , user2");
conf.set(KEY_AUTH_SERVICE_CACHING_ENABLE, "false");
+ conf.set(NativeAzureFileSystem.AZURE_CHMOD_USERLIST_PROPERTY_NAME, "user1 , user2");
+ conf.set(NativeAzureFileSystem.AZURE_DAEMON_USERLIST_PROPERTY_NAME, "hive , hcs , yarn");
return conf;
}
@@ -925,7 +933,7 @@ public class TestNativeAzureFileSystemAuthorization
// create child with owner as dummyUser
UserGroupInformation dummyUser = UserGroupInformation.createUserForTesting(
- "dummyUser", new String[] {"dummygroup"});
+ "user1", new String[] {"dummygroup"});
dummyUser.doAs(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
@@ -1226,16 +1234,13 @@ public class TestNativeAzureFileSystemAuthorization
*/
@Test
public void testSetOwnerThrowsForUnauthorisedUsers() throws Throwable {
-
- expectedEx.expect(WasbAuthorizationException.class);
-
Path testPath = new Path("/testSetOwnerNegative");
authorizer.addAuthRuleForOwner("/", WRITE, true);
- authorizer.addAuthRuleForOwner(testPath.toString(), READ, true);
+ authorizer.addAuthRuleForOwner("/", READ, true);
fs.updateWasbAuthorizer(authorizer);
- String owner = null;
+ final String owner;
UserGroupInformation unauthorisedUser = UserGroupInformation.createUserForTesting(
"unauthoriseduser", new String[] {"group1"});
try {
@@ -1246,13 +1251,17 @@ public class TestNativeAzureFileSystemAuthorization
unauthorisedUser.doAs(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
+ try {
fs.setOwner(testPath, "newowner", null);
- return null;
+ fail("Failing test because setOwner call was expected to throw");
+ } catch (WasbAuthorizationException wex) {
+ // check that the owner is not modified
+ assertOwnerEquals(testPath, owner);
+ }
+ return null;
}
});
} finally {
- // check that the owner is not modified
- assertEquals(owner, fs.getFileStatus(testPath).getOwner());
fs.delete(testPath, false);
}
}
@@ -1288,8 +1297,8 @@ public class TestNativeAzureFileSystemAuthorization
@Override
public Void run() throws Exception {
fs.setOwner(testPath, newOwner, newGroup);
- assertEquals(newOwner, fs.getFileStatus(testPath).getOwner());
- assertEquals(newGroup, fs.getFileStatus(testPath).getGroup());
+ assertOwnerEquals(testPath, newOwner);
+ assertEquals(newGroup, fs.getFileStatus(testPath).getGroup());
return null;
}
});
@@ -1305,19 +1314,17 @@ public class TestNativeAzureFileSystemAuthorization
* */
@Test
public void testSetOwnerSucceedsForAnyUserWhenWildCardIsSpecified() throws Throwable {
+ fs.updateChownAllowedUsers(Collections.singletonList("*"));
+ final Path testPath = new Path("/testSetOwnerPositiveWildcard");
Configuration conf = fs.getConf();
- conf.set(NativeAzureFileSystem.AZURE_CHOWN_USERLIST_PROPERTY_NAME, "*");
- fs.setConf(conf);
- Path testPath = new Path("/testSetOwnerPositiveWildcard");
-
authorizer.init(conf);
authorizer.addAuthRuleForOwner("/", WRITE, true);
authorizer.addAuthRuleForOwner(testPath.getParent().toString(), READ, true);
fs.updateWasbAuthorizer(authorizer);
- String newOwner = "newowner";
- String newGroup = "newgroup";
+ final String newOwner = "newowner";
+ final String newGroup = "newgroup";
UserGroupInformation user = UserGroupInformation.createUserForTesting(
"anyuser", new String[]{"group1"});
@@ -1334,7 +1341,7 @@ public class TestNativeAzureFileSystemAuthorization
@Override
public Void run() throws Exception {
fs.setOwner(testPath, newOwner, newGroup);
- assertEquals(newOwner, fs.getFileStatus(testPath).getOwner());
+ assertOwnerEquals(testPath, newOwner);
assertEquals(newGroup, fs.getFileStatus(testPath).getGroup());
return null;
}
@@ -1350,20 +1357,16 @@ public class TestNativeAzureFileSystemAuthorization
*/
@Test
public void testSetOwnerFailsForIllegalSetup() throws Throwable {
+ fs.updateChownAllowedUsers(Arrays.asList("user1", "*"));
- expectedEx.expect(IllegalArgumentException.class);
+ final Path testPath = new Path("/testSetOwnerFailsForIllegalSetup");
Configuration conf = fs.getConf();
- conf.set(NativeAzureFileSystem.AZURE_CHOWN_USERLIST_PROPERTY_NAME, "user1, *");
- fs.setConf(conf);
- Path testPath = new Path("/testSetOwnerFailsForIllegalSetup");
-
authorizer.init(conf);
authorizer.addAuthRuleForOwner("/", WRITE, true);
authorizer.addAuthRuleForOwner(testPath.getParent().toString(), READ, true);
fs.updateWasbAuthorizer(authorizer);
- String owner = null;
UserGroupInformation user = UserGroupInformation.createUserForTesting(
"anyuser", new String[]{"group1"});
try {
@@ -1371,18 +1374,22 @@ public class TestNativeAzureFileSystemAuthorization
fs.mkdirs(testPath);
ContractTestUtils.assertPathExists(fs, "test path does not exist", testPath);
- owner = fs.getFileStatus(testPath).getOwner();
+ final String owner = fs.getFileStatus(testPath).getOwner();
user.doAs(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
+ try {
fs.setOwner(testPath, "newowner", null);
+ fail("Failing test because setOwner call was expected to throw");
+ } catch (IllegalArgumentException iex) {
+ // check that the owner is not modified
+ assertOwnerEquals(testPath, owner);
+ }
return null;
}
});
} finally {
- // check that the owner is not modified
- assertEquals(owner, fs.getFileStatus(testPath).getOwner());
fs.delete(testPath, false);
}
}
@@ -1433,4 +1440,219 @@ public class TestNativeAzureFileSystemAuthorization
fs.delete(testPath, true);
}
}
+
+ /**
+ * Negative test for setPermission when Authorization is enabled.
+ */
+ @Test
+ public void testSetPermissionThrowsForUnauthorisedUsers() throws Throwable {
+ //setPermission is called by a user who is not a daemon user
+ //and not chmodAllowedUsers and not owner of the file/folder.
+ //This test validates a authorization exception during setPermission call
+ testSetPermission("/testSetPermissionNegative", null, null, "unauthorizeduser",
+ true, false);
+ }
+
+ /**
+ * Positive test for setPermission when Authorization is enabled.
+ */
+ @Test
+ public void testSetPermissionForAuthorisedUsers() throws Throwable {
+ //user1 is already part of chmodAllowedUsers.
+ //This test validates the allowed user can do setPermission
+ testSetPermission("/testSetPermissionPositive", null, null, "user1",
+ false, false);
+ }
+
+ /**
+ * Positive test for setPermission as owner when Authorization is enabled.
+ */
+ @Test
+ public void testSetPermissionForOwner() throws Throwable {
+ //setPermission is called by the owner and expect a success
+ //during setPermission call
+ testSetPermission("/testSetPermissionPositiveOwner",
+ null, null, null, false, false);
+ }
+
+ /**
+ * Test setPermission when wildcard is specified in allowed user list.
+ */
+ @Test
+ public void testSetPermissionWhenWildCardInAllowedUserList() throws Throwable {
+ //Allow all to setPermission and expect a success
+ //during setPermission call
+ List<String> chmodAllowedUsers = Collections.singletonList("*");
+
+ testSetPermission("/testSetPermissionWhenWildCardInAllowedUserList",
+ chmodAllowedUsers, null, "testuser", false, false);
+ }
+
+ /**
+ * Test setPermission when invalid configuration value for allowed user list
+ * i.e. wildcard character and a username.
+ */
+ @Test
+ public void testSetPermissionForInvalidAllowedUserList() throws Throwable {
+ //Setting up an invalid chmodAllowedUsers and expects a failure
+ //during setPermission call
+ List<String> chmodAllowedUsers = Arrays.asList("*", "testuser");
+
+ testSetPermission("/testSetPermissionForInvalidAllowedUserList",
+ chmodAllowedUsers, null, "testuser", true, true);
+ }
+
+ /**
+ * Test setPermission for a daemon user.
+ */
+ @Test
+ public void testSetPermissionForDaemonUser() throws Throwable {
+ //hive user is already setup as daemon user.
+ //This test validates the daemon user can do setPermission
+ testSetPermission("/testSetPermissionForDaemonUser", null,
+ null, "hive", false, false);
+ }
+
+ /**
+ * Test setPermission when invalid configuration value for daemon user list
+ * i.e. wildcard character and a daemon username.
+ */
+ @Test
+ public void testSetPermissionForInvalidDaemonUserList() throws Throwable {
+
+ List<String> daemonUsers = Arrays.asList("*", "hive");
+
+ testSetPermission("/testSetPermissionForInvalidDaemonUserList", null,
+ daemonUsers, "testuser", true, true);
+
+ }
+
+ /**
+ * Helper method to test setPermission scenarios. This method handles both positive
+ * and negative scenarios of setPermission tests
+ */
+ private void testSetPermission(String path,
+ List<String> chmodAllowedUsers,
+ List<String> daemonUsers,
+ String user,
+ boolean isSetPermissionFailureCase,
+ boolean isInvalidSetup) throws Throwable {
+
+ final FsPermission filePermission;
+
+ final Path testPath = new Path(path);
+ final FsPermission newPermission = new FsPermission(FULL_PERMISSION_WITH_STICKYBIT);
+ authorizer.addAuthRule("/", WRITE, getCurrentUserShortName(), true);
+ authorizer.addAuthRule("/", READ, getCurrentUserShortName(), true);
+ fs.updateWasbAuthorizer(authorizer);
+
+ if (chmodAllowedUsers != null && !chmodAllowedUsers.isEmpty()) {
+ fs.updateChmodAllowedUsers(chmodAllowedUsers);
+ }
+
+ if (daemonUsers != null && !daemonUsers.isEmpty()) {
+ fs.updateDaemonUsers(daemonUsers);
+ }
+
+ UserGroupInformation testUser = (user != null) ? UserGroupInformation.createUserForTesting(
+ user, new String[] {"testgrp"}) : null;
+ try {
+ fs.mkdirs(testPath);
+ ContractTestUtils.assertPathExists(fs, "test path does not exist",
+ testPath);
+ filePermission = fs.getFileStatus(testPath).getPermission();
+
+ if (isSetPermissionFailureCase) {
+ executeSetPermissionFailure(testUser, testPath, filePermission,
+ newPermission, isInvalidSetup);
+ } else {
+ executeSetPermissionSuccess(testUser, testPath, filePermission,
+ newPermission);
+ }
+
+ } finally {
+ fs.delete(testPath, false);
+ }
+ }
+
+ /**
+ * This method expects a failure while invoking setPermission call
+ * and validates whether the failure is as expected
+ *
+ */
+ private void executeSetPermissionFailure(UserGroupInformation testUser,
+ Path testPath, FsPermission oldPermission, FsPermission newPermission,
+ boolean isInvalidSetup)
+ throws Throwable {
+ testUser.doAs(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ try {
+ //READ access required for getFileStatus
+ authorizer.addAuthRule("/", READ, getCurrentUserShortName(), true);
+ fs.setPermission(testPath, newPermission);
+ fail("Failing test because setPermission was expected to throw");
+
+ } catch (IllegalArgumentException iex) {
+ if (!isInvalidSetup) {
+ //fail if IllegalArgumentException is not expected
+ fail("Failing test because IllegalArgumentException"
+ + " is not expected to throw");
+ }
+ // check that the file permission is not modified.
+ assertPermissionEquals(testPath, oldPermission);
+ } catch (WasbAuthorizationException wex) {
+ if (isInvalidSetup) {
+ //fail if WasbAuthorizationException is not expected
+ fail("Failing test because WasbAuthorizationException"
+ + " is not expected to throw");
+ }
+ // check that the file permission is not modified.
+ assertPermissionEquals(testPath, oldPermission);
+ }
+ return null;
+ }
+ });
+ }
+
+ /**
+ * This method expects a success while invoking setPermission call
+ * and validates whether the new permissions are set
+ *
+ */
+ private void executeSetPermissionSuccess(UserGroupInformation testUser,
+ Path testPath, FsPermission oldPermission, FsPermission newPermission)
+ throws Throwable {
+ //If user is given, then use doAs
+ if (testUser != null) {
+ testUser.doAs(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ fs.setPermission(testPath, newPermission);
+ return null;
+ }
+ });
+ } else {
+ //If user is not given, then run in current user context
+ fs.setPermission(testPath, newPermission);
+ }
+
+ // check that the file permission is modified
+ assertPermissionEquals(testPath, newPermission);
+ // check old permission is not equals to new permission
+ assertNotEquals(newPermission, oldPermission);
+ }
+
+ private void assertPermissionEquals(Path path, FsPermission newPermission)
+ throws IOException {
+ FileStatus status = fs.getFileStatus(path);
+ assertEquals("Wrong permissions in " + status,
+ newPermission, status.getPermission());
+ }
+
+ private void assertOwnerEquals(Path path, String owner) throws IOException {
+ FileStatus status = fs.getFileStatus(path);
+ assertEquals("Wrong owner in " + status, owner, status.getOwner());
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org