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 0ba47ef4f0..b61baabb4a 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
@@ -200,7 +200,7 @@ public FolderRenamePending(Path redoFile, NativeAzureFileSystem fs)
JsonNode oldFolderName = json.get("OldFolderName");
JsonNode newFolderName = json.get("NewFolderName");
if (oldFolderName == null || newFolderName == null) {
- this.committed = false;
+ this.committed = false;
} else {
this.srcKey = oldFolderName.textValue();
this.dstKey = newFolderName.textValue();
@@ -349,7 +349,7 @@ public String makeRenamePendingFileContents() {
return contents;
}
-
+
/**
* This is an exact copy of org.codehaus.jettison.json.JSONObject.quote
* method.
@@ -639,7 +639,7 @@ public String getScheme() {
return "wasb";
}
-
+
/**
*
* A {@link FileSystem} for reading and writing files stored on authRules;
+ private boolean performOwnerMatch;
- // The full qualified URL to the root directory
+ // The full qualified URL to the root directory
private String qualifiedPrefixUrl;
public MockWasbAuthorizerImpl(NativeAzureFileSystem fs) {
@@ -43,15 +46,22 @@ public MockWasbAuthorizerImpl(NativeAzureFileSystem fs) {
@Override
public void init(Configuration conf) {
+ init(conf, false);
+ }
+
+ /*
+ authorization matches owner with currentUserShortName while evaluating auth rules
+ if currentUserShortName is set to a string that is not empty
+ */
+ public void init(Configuration conf, boolean matchOwner) {
authRules = new HashMap();
+ this.performOwnerMatch = matchOwner;
}
public void addAuthRule(String wasbAbsolutePath,
String accessType, boolean access) {
-
- wasbAbsolutePath = qualifiedPrefixUrl + wasbAbsolutePath;
-
- AuthorizationComponent component = wasbAbsolutePath.endsWith("*")
+ wasbAbsolutePath = qualifiedPrefixUrl + wasbAbsolutePath;
+ AuthorizationComponent component = wasbAbsolutePath.endsWith("*")
? new AuthorizationComponent("^" + wasbAbsolutePath.replace("*", ".*"), accessType)
: new AuthorizationComponent(wasbAbsolutePath, accessType);
@@ -59,18 +69,40 @@ public void addAuthRule(String wasbAbsolutePath,
}
@Override
- public boolean authorize(String wasbAbsolutePath, String accessType)
+ public boolean authorize(String wasbAbsolutePath, String accessType, String owner)
throws WasbAuthorizationException {
if (wasbAbsolutePath.endsWith(NativeAzureFileSystem.FolderRenamePending.SUFFIX)) {
return true;
}
+ String currentUserShortName = "";
+ if (this.performOwnerMatch) {
+ try {
+ UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
+ currentUserShortName = ugi.getShortUserName();
+ } catch (Exception e) {
+ //no op
+ }
+ }
+
+ // In case of root("/"), owner match does not happen because owner is returned as empty string.
+ // we try to force owner match just for purpose of tests to make sure all operations work seemlessly with owner.
+ if (this.performOwnerMatch
+ && StringUtils.equalsIgnoreCase(wasbAbsolutePath, qualifiedPrefixUrl + "/")) {
+ owner = currentUserShortName;
+ }
+
+ boolean shouldEvaluateOwnerAccess = owner != null && !owner.isEmpty()
+ && this.performOwnerMatch;
+
+ boolean isOwnerMatch = StringUtils.equalsIgnoreCase(currentUserShortName, owner);
+
AuthorizationComponent component =
new AuthorizationComponent(wasbAbsolutePath, accessType);
if (authRules.containsKey(component)) {
- return authRules.get(component);
+ return shouldEvaluateOwnerAccess ? isOwnerMatch && authRules.get(component) : authRules.get(component);
} else {
// Regex-pattern match if we don't have a straight match
for (Map.Entry entry : authRules.entrySet()) {
@@ -79,12 +111,16 @@ public boolean authorize(String wasbAbsolutePath, String accessType)
String keyAccess = key.getAccessType();
if (keyPath.endsWith("*") && Pattern.matches(keyPath, wasbAbsolutePath) && keyAccess.equals(accessType)) {
- return entry.getValue();
+ return shouldEvaluateOwnerAccess ? isOwnerMatch && entry.getValue() : entry.getValue();
}
}
return false;
}
}
+
+ public void deleteAllAuthRules() {
+ authRules.clear();
+ }
}
class AuthorizationComponent {
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 f7a2eb796f..a0276cb5f5 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
@@ -29,6 +29,7 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import com.google.common.annotations.VisibleForTesting;
import static org.apache.hadoop.fs.azure.AzureNativeFileSystemStore.KEY_USE_SECURE_MODE;
@@ -38,6 +39,9 @@
public class TestNativeAzureFileSystemAuthorization
extends AbstractWasbTestBase {
+ @VisibleForTesting
+ protected MockWasbAuthorizerImpl authorizer;
+
@Override
protected AzureBlobStorageTestAccount createTestAccount() throws Exception {
Configuration conf = new Configuration();
@@ -54,9 +58,8 @@ public void beforeMethod() {
Assume.assumeTrue("Test valid when both SecureMode and Authorization are enabled .. skipping",
useSecureMode && useAuthorization);
- Assume.assumeTrue(
- useSecureMode && useAuthorization
- );
+ authorizer = new MockWasbAuthorizerImpl(fs);
+ authorizer.init(null);
}
@@ -66,12 +69,12 @@ public void beforeMethod() {
/**
* Setup up permissions to allow a recursive delete for cleanup purposes.
*/
- private void allowRecursiveDelete(NativeAzureFileSystem fs, MockWasbAuthorizerImpl authorizer, String path) {
+ protected void allowRecursiveDelete(NativeAzureFileSystem fs, String path) {
int index = path.lastIndexOf('/');
String parent = (index == 0) ? "/" : path.substring(0, index);
- authorizer.init(null);
+ authorizer.deleteAllAuthRules();
authorizer.addAuthRule(parent, WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule((path.endsWith("*") ? path : path+"*"), WasbAuthorizationOperations.WRITE.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -80,7 +83,7 @@ private void allowRecursiveDelete(NativeAzureFileSystem fs, MockWasbAuthorizerIm
/**
* Setup the expected exception class, and exception message that the test is supposed to fail with
*/
- private void setExpectedFailureMessage(String operation, Path path) {
+ protected void setExpectedFailureMessage(String operation, Path path) {
expectedEx.expect(WasbAuthorizationException.class);
expectedEx.expectMessage(String.format("%s operation for Path : %s not allowed",
operation, path.makeQualified(fs.getUri(), fs.getWorkingDirectory())));
@@ -98,8 +101,6 @@ public void testCreateAccessWithoutCreateIntermediateFoldersCheckPositive() thro
Path parentDir = new Path("/");
Path testPath = new Path(parentDir, "test.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -126,8 +127,6 @@ public void testCreateAccessWithCreateIntermediateFoldersCheckPositive() throws
Path parentDir = new Path("/testCreateAccessCheckPositive/1/2/3");
Path testPath = new Path(parentDir, "test.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -137,7 +136,7 @@ public void testCreateAccessWithCreateIntermediateFoldersCheckPositive() throws
ContractTestUtils.assertPathExists(fs, "testPath was not created", testPath);
}
finally {
- allowRecursiveDelete(fs, authorizer, "/testCreateAccessCheckPositive");
+ allowRecursiveDelete(fs, "/testCreateAccessCheckPositive");
fs.delete(new Path("/testCreateAccessCheckPositive"), true);
}
}
@@ -156,8 +155,6 @@ public void testCreateAccessWithOverwriteCheckNegative() throws Throwable {
setExpectedFailureMessage("create", testPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -186,8 +183,6 @@ public void testCreateAccessWithOverwriteCheckPositive() throws Throwable {
Path parentDir = new Path("/");
Path testPath = new Path(parentDir, "test.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.WRITE.toString(), true);
@@ -219,8 +214,6 @@ public void testCreateAccessCheckNegative() throws Throwable {
setExpectedFailureMessage("create", testPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), false);
fs.updateWasbAuthorizer(authorizer);
@@ -229,7 +222,7 @@ public void testCreateAccessCheckNegative() throws Throwable {
}
finally {
/* Provide permissions to cleanup in case the file got created */
- allowRecursiveDelete(fs, authorizer, parentDir.toString());
+ allowRecursiveDelete(fs, parentDir.toString());
fs.delete(parentDir, true);
}
}
@@ -245,8 +238,6 @@ public void testListAccessCheckPositive() throws Throwable {
Path intermediateFolders = new Path(parentDir, "1/2/3/");
Path testPath = new Path(intermediateFolders, "test.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -256,7 +247,7 @@ public void testListAccessCheckPositive() throws Throwable {
fs.listStatus(testPath);
}
finally {
- allowRecursiveDelete(fs, authorizer, parentDir.toString());
+ allowRecursiveDelete(fs, parentDir.toString());
fs.delete(parentDir, true);
}
}
@@ -274,8 +265,6 @@ public void testListAccessCheckNegative() throws Throwable {
setExpectedFailureMessage("liststatus", testPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), false);
fs.updateWasbAuthorizer(authorizer);
@@ -285,7 +274,7 @@ public void testListAccessCheckNegative() throws Throwable {
fs.listStatus(testPath);
}
finally {
- allowRecursiveDelete(fs, authorizer, parentDir.toString());
+ allowRecursiveDelete(fs, parentDir.toString());
fs.delete(parentDir, true);
}
}
@@ -301,8 +290,6 @@ public void testRenameAccessCheckPositive() throws Throwable {
Path srcPath = new Path(parentDir, "test1.dat");
Path dstPath = new Path(parentDir, "test2.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true); /* to create parentDir */
authorizer.addAuthRule(parentDir.toString(), WasbAuthorizationOperations.WRITE.toString(), true); /* for rename */
authorizer.addAuthRule(srcPath.toString(), WasbAuthorizationOperations.READ.toString(), true); /* for exists */
@@ -317,7 +304,7 @@ public void testRenameAccessCheckPositive() throws Throwable {
ContractTestUtils.assertPathDoesNotExist(fs, "sourcePath exists after rename!", srcPath);
}
finally {
- allowRecursiveDelete(fs, authorizer, parentDir.toString());
+ allowRecursiveDelete(fs, parentDir.toString());
fs.delete(parentDir, true);
}
}
@@ -335,8 +322,6 @@ public void testRenameAccessCheckNegative() throws Throwable {
setExpectedFailureMessage("rename", srcPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true); /* to create parent dir */
authorizer.addAuthRule(parentDir.toString(), WasbAuthorizationOperations.WRITE.toString(), false);
authorizer.addAuthRule(srcPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
@@ -351,7 +336,7 @@ public void testRenameAccessCheckNegative() throws Throwable {
} finally {
ContractTestUtils.assertPathExists(fs, "sourcePath does not exist after rename failure!", srcPath);
- allowRecursiveDelete(fs, authorizer, parentDir.toString());
+ allowRecursiveDelete(fs, parentDir.toString());
fs.delete(parentDir, true);
}
}
@@ -370,8 +355,6 @@ public void testRenameAccessCheckNegativeOnDstFolder() throws Throwable {
setExpectedFailureMessage("rename", dstPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true); /* to create parent dir */
authorizer.addAuthRule(parentSrcDir.toString(), WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(parentDstDir.toString(), WasbAuthorizationOperations.WRITE.toString(), false);
@@ -386,7 +369,7 @@ public void testRenameAccessCheckNegativeOnDstFolder() throws Throwable {
ContractTestUtils.assertPathDoesNotExist(fs, "destPath does not exist", dstPath);
} finally {
ContractTestUtils.assertPathExists(fs, "sourcePath does not exist after rename !", srcPath);
- allowRecursiveDelete(fs, authorizer, parentSrcDir.toString());
+ allowRecursiveDelete(fs, parentSrcDir.toString());
fs.delete(parentSrcDir, true);
}
}
@@ -403,8 +386,6 @@ public void testRenameAccessCheckPositiveOnDstFolder() throws Throwable {
Path parentDstDir = new Path("/testRenameAccessCheckPositiveDst");
Path dstPath = new Path(parentDstDir, "test2.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true); /* to create parent dirs */
authorizer.addAuthRule(parentSrcDir.toString(), WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(parentDstDir.toString(), WasbAuthorizationOperations.WRITE.toString(), true);
@@ -420,10 +401,10 @@ public void testRenameAccessCheckPositiveOnDstFolder() throws Throwable {
ContractTestUtils.assertPathDoesNotExist(fs, "sourcePath does not exist", srcPath);
ContractTestUtils.assertPathExists(fs, "destPath does not exist", dstPath);
} finally {
- allowRecursiveDelete(fs, authorizer, parentSrcDir.toString());
+ allowRecursiveDelete(fs, parentSrcDir.toString());
fs.delete(parentSrcDir, true);
- allowRecursiveDelete(fs, authorizer, parentDstDir.toString());
+ allowRecursiveDelete(fs, parentDstDir.toString());
fs.delete(parentDstDir, true);
}
}
@@ -438,8 +419,6 @@ public void testReadAccessCheckPositive() throws Throwable {
Path parentDir = new Path("/testReadAccessCheckPositive");
Path testPath = new Path(parentDir, "test.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -463,7 +442,7 @@ public void testReadAccessCheckPositive() throws Throwable {
if(inputStream != null) {
inputStream.close();
}
- allowRecursiveDelete(fs, authorizer, parentDir.toString());
+ allowRecursiveDelete(fs, parentDir.toString());
fs.delete(parentDir, true);
}
}
@@ -481,8 +460,6 @@ public void testReadAccessCheckNegative() throws Throwable {
setExpectedFailureMessage("read", testPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), false);
fs.updateWasbAuthorizer(authorizer);
@@ -505,7 +482,7 @@ public void testReadAccessCheckNegative() throws Throwable {
if (inputStream != null) {
inputStream.close();
}
- allowRecursiveDelete(fs, authorizer, parentDir.toString());
+ allowRecursiveDelete(fs, parentDir.toString());
fs.delete(parentDir, true);
}
}
@@ -520,8 +497,6 @@ public void testFileDeleteAccessCheckPositive() throws Throwable {
Path parentDir = new Path("/");
Path testPath = new Path(parentDir, "test.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -547,8 +522,6 @@ public void testFileDeleteAccessCheckNegative() throws Throwable {
setExpectedFailureMessage("delete", testPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -558,7 +531,7 @@ public void testFileDeleteAccessCheckNegative() throws Throwable {
/* Remove permissions for delete to force failure */
- authorizer.init(null);
+ authorizer.deleteAllAuthRules();
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), false);
fs.updateWasbAuthorizer(authorizer);
@@ -566,7 +539,7 @@ public void testFileDeleteAccessCheckNegative() throws Throwable {
}
finally {
/* Restore permissions to force a successful delete */
- authorizer.init(null);
+ authorizer.deleteAllAuthRules();
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -587,8 +560,6 @@ public void testFileDeleteAccessWithIntermediateFoldersCheckPositive() throws Th
Path parentDir = new Path("/testDeleteIntermediateFolder");
Path testPath = new Path(parentDir, "1/2/test.dat");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true); // for create and delete
authorizer.addAuthRule("/testDeleteIntermediateFolder*",
WasbAuthorizationOperations.WRITE.toString(), true); // for recursive delete
@@ -602,7 +573,7 @@ public void testFileDeleteAccessWithIntermediateFoldersCheckPositive() throws Th
ContractTestUtils.assertPathDoesNotExist(fs, "testPath exists after deletion!", parentDir);
}
finally {
- allowRecursiveDelete(fs, authorizer, parentDir.toString());
+ allowRecursiveDelete(fs, parentDir.toString());
fs.delete(parentDir, true);
}
}
@@ -616,8 +587,6 @@ public void testGetFileStatusPositive() throws Throwable {
Path testPath = new Path("/");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -635,8 +604,6 @@ public void testGetFileStatusNegative() throws Throwable {
setExpectedFailureMessage("getFileStatus", testPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.READ.toString(), false);
fs.updateWasbAuthorizer(authorizer);
@@ -652,8 +619,6 @@ public void testMkdirsCheckPositive() throws Throwable {
Path testPath = new Path("/testMkdirsAccessCheckPositive/1/2/3");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -663,7 +628,7 @@ public void testMkdirsCheckPositive() throws Throwable {
ContractTestUtils.assertIsDirectory(fs, testPath);
}
finally {
- allowRecursiveDelete(fs, authorizer, "/testMkdirsAccessCheckPositive");
+ allowRecursiveDelete(fs, "/testMkdirsAccessCheckPositive");
fs.delete(new Path("/testMkdirsAccessCheckPositive"), true);
}
}
@@ -679,8 +644,6 @@ public void testMkdirsCheckNegative() throws Throwable {
setExpectedFailureMessage("mkdirs", testPath);
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), false);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
@@ -690,12 +653,11 @@ public void testMkdirsCheckNegative() throws Throwable {
ContractTestUtils.assertPathDoesNotExist(fs, "testPath was not created", testPath);
}
finally {
- allowRecursiveDelete(fs, authorizer, "/testMkdirsAccessCheckNegative");
+ allowRecursiveDelete(fs, "/testMkdirsAccessCheckNegative");
fs.delete(new Path("/testMkdirsAccessCheckNegative"), true);
}
}
-
/**
* Positive test triple slash format (wasb:///) access check
* @throws Throwable
@@ -705,8 +667,6 @@ public void testListStatusWithTripleSlashCheckPositive() throws Throwable {
Path testPath = new Path("/");
- MockWasbAuthorizerImpl authorizer = new MockWasbAuthorizerImpl(fs);
- authorizer.init(null);
authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
fs.updateWasbAuthorizer(authorizer);
diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azure/TestNativeAzureFileSystemAuthorizationWithOwner.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azure/TestNativeAzureFileSystemAuthorizationWithOwner.java
new file mode 100644
index 0000000000..3329e6763f
--- /dev/null
+++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azure/TestNativeAzureFileSystemAuthorizationWithOwner.java
@@ -0,0 +1,122 @@
+/**
+ * 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.fs.azure;
+
+import org.apache.hadoop.fs.contract.ContractTestUtils;
+import org.apache.hadoop.security.UserGroupInformation;
+import java.security.PrivilegedExceptionAction;
+
+import org.apache.hadoop.fs.Path;
+import org.junit.Test;
+import org.junit.Before;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class that runs wasb authorization tests with owner check enabled.
+ */
+public class TestNativeAzureFileSystemAuthorizationWithOwner
+ extends TestNativeAzureFileSystemAuthorization {
+
+ @Before
+ public void beforeMethod() {
+ super.beforeMethod();
+ authorizer.init(null, true);
+ }
+
+ /**
+ * Test case when owner matches current user
+ */
+ @Test
+ public void testOwnerPermissionPositive() throws Throwable {
+
+ Path parentDir = new Path("/testOwnerPermissionPositive");
+ Path testPath = new Path(parentDir, "test.data");
+
+ authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
+ authorizer.addAuthRule(testPath.toString(), WasbAuthorizationOperations.READ.toString(), true);
+ authorizer.addAuthRule(parentDir.toString(), WasbAuthorizationOperations.WRITE.toString(), true);
+ // additional rule used for assertPathExists
+ authorizer.addAuthRule(parentDir.toString(), WasbAuthorizationOperations.READ.toString(), true);
+ fs.updateWasbAuthorizer(authorizer);
+
+ try {
+ // creates parentDir with owner as current user
+ fs.mkdirs(parentDir);
+ ContractTestUtils.assertPathExists(fs, "parentDir does not exist", parentDir);
+
+ fs.create(testPath);
+ fs.getFileStatus(testPath);
+ ContractTestUtils.assertPathExists(fs, "testPath does not exist", testPath);
+
+ } finally {
+ allowRecursiveDelete(fs, parentDir.toString());
+ fs.delete(parentDir, true);
+ }
+ }
+
+ /**
+ * Negative test case for owner does not match current user
+ */
+ @Test
+ public void testOwnerPermissionNegative() throws Throwable {
+ expectedEx.expect(WasbAuthorizationException.class);
+
+ Path parentDir = new Path("/testOwnerPermissionNegative");
+ Path childDir = new Path(parentDir, "childDir");
+
+ setExpectedFailureMessage("mkdirs", childDir);
+
+ authorizer.addAuthRule("/", WasbAuthorizationOperations.WRITE.toString(), true);
+ authorizer.addAuthRule(parentDir.toString(), WasbAuthorizationOperations.WRITE.toString(), true);
+
+ fs.updateWasbAuthorizer(authorizer);
+
+ try{
+ fs.mkdirs(parentDir);
+ UserGroupInformation ugiSuperUser = UserGroupInformation.createUserForTesting(
+ "testuser", new String[] {});
+
+ ugiSuperUser.doAs(new PrivilegedExceptionAction() {
+ @Override
+ public Void run() throws Exception {
+ fs.mkdirs(childDir);
+ return null;
+ }
+ });
+
+ } finally {
+ allowRecursiveDelete(fs, parentDir.toString());
+ fs.delete(parentDir, true);
+ }
+ }
+
+ /**
+ * Test to verify that retrieving owner information does not
+ * throw when file/folder does not exist
+ */
+ @Test
+ public void testRetrievingOwnerDoesNotFailWhenFileDoesNotExist() throws Throwable {
+
+ Path testdirectory = new Path("/testDirectory123454565");
+
+ String owner = fs.getOwnerForPath(testdirectory);
+ assertEquals("", owner);
+ }
+}
+