This is an automated email from the ASF dual-hosted git repository.
sammichen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 4e32dbaacd HDDS-4715. ACL on link bucket (#4559)
4e32dbaacd is described below
commit 4e32dbaacd80c6d39521579fda04444ea2a95418
Author: Hongbing Wang <[email protected]>
AuthorDate: Wed May 24 14:49:40 2023 +0800
HDDS-4715. ACL on link bucket (#4559)
---
.../docs/content/design/volume-management.md | 4 +-
.../apache/hadoop/ozone/client/rpc/RpcClient.java | 21 ++
.../dist/src/main/smoketest/basic/links.robot | 72 ++++--
.../apache/hadoop/ozone/om/TestOzoneManagerHA.java | 35 +++
.../hadoop/ozone/om/TestOzoneManagerHAWithACL.java | 279 +++++++++++++++++----
.../apache/hadoop/ozone/om/BucketManagerImpl.java | 36 ++-
.../org/apache/hadoop/ozone/om/KeyManagerImpl.java | 18 +-
.../apache/hadoop/ozone/om/OmMetadataReader.java | 12 +-
.../apache/hadoop/ozone/om/OmSnapshotManager.java | 2 +-
.../org/apache/hadoop/ozone/om/OzoneManager.java | 4 +-
.../om/request/bucket/acl/OMBucketAclRequest.java | 9 +-
.../ozone/om/request/key/acl/OMKeyAclRequest.java | 9 +-
.../om/request/key/acl/OMKeyAclRequestWithFSO.java | 9 +-
.../ozone/om/request/bucket/TestBucketRequest.java | 6 +
.../ozone/om/request/key/TestOMKeyRequest.java | 2 +
.../ozone/shell/bucket/GetAclBucketHandler.java | 37 +++
16 files changed, 468 insertions(+), 87 deletions(-)
diff --git a/hadoop-hdds/docs/content/design/volume-management.md
b/hadoop-hdds/docs/content/design/volume-management.md
index a21ffb7894..def8a25a75 100644
--- a/hadoop-hdds/docs/content/design/volume-management.md
+++ b/hadoop-hdds/docs/content/design/volume-management.md
@@ -125,9 +125,11 @@ Note: Sanjay is added to the authors as the original
proposal of this approach.
* `bucket link` operation creates a link bucket. Links are like regular
buckets, stored in DB the same way, but with two new, optional pieces of
information: source volume and bucket. (The bucket being referenced by the
link is called "source", not "target", to follow symlink terminology.)
* Link buckets share the namespace with regular buckets. If a bucket or link
with the same name already exists, a `BUCKET_ALREADY_EXISTS` result is returned.
* Link buckets are not inherently specific to a user, access is restricted
only by ACL.
+ * Link buckets retain their owner ACLs, which are inherited from the default
ACLs of their volume. Additionally, link buckets allow anyone to have READ and
WRITE permissions, which is similar to Linux POSIX symbolic.
+ * All add/set/remove ACL operation proxy to the source bucket. Getacl
operation of a link bucket shows link bucket's ACL.
* Links are persistent, ie. they can be used until they are deleted.
* Existing bucket operations (info, delete, ACL) work on the link object in
the same way as they do on regular buckets. No new link-specific RPC is
required.
- * Links are followed for key operations (list, get, put, etc.). Read
permission on the link is required for this.
+ * Links are followed for key operations (list, get, put, etc.). Read
permission on the source bucket is required for this.
* Checks for existence of the source bucket, as well as ACL, are performed
only when following the link (similar to symlinks). Source bucket is not
checked when operating on the link bucket itself (eg. deleting it). This
avoids the need for reverse checks for each bucket delete or ACL change.
* Bucket links are generic, not restricted to the `s3v` volume.
diff --git
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
index a4dbfb1828..06a1d3d61d 100644
---
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
+++
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
@@ -31,6 +31,7 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -166,6 +167,8 @@ import static
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_KEY_PROVIDER_
import static
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_REQUIRED_OM_VERSION_MIN_KEY;
import static org.apache.hadoop.ozone.OzoneConsts.OLD_QUOTA_DEFAULT;
import static
org.apache.hadoop.ozone.OzoneConsts.OZONE_MAXIMUM_ACCESS_ID_LENGTH;
+import static
org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.READ;
+import static
org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.WRITE;
import org.apache.logging.log4j.util.Strings;
import org.apache.ratis.protocol.ClientId;
@@ -643,6 +646,11 @@ public class RpcClient implements ClientProtocol {
if (bucketArgs.getAcls() != null) {
listOfAcls.addAll(bucketArgs.getAcls());
}
+ // Link bucket default acl
+ if (bucketArgs.getSourceVolume() != null
+ && bucketArgs.getSourceBucket() != null) {
+ listOfAcls.add(linkBucketDefaultAcl());
+ }
OmBucketInfo.Builder builder = OmBucketInfo.newBuilder();
builder.setVolumeName(volumeName)
@@ -737,6 +745,19 @@ public class RpcClient implements ClientProtocol {
userRights, groupRights);
}
+ /**
+ * Link bucket default acl defined [world::rw]
+ * which is similar to Linux POSIX symbolic.
+ *
+ * @return OzoneAcl
+ */
+ private OzoneAcl linkBucketDefaultAcl() {
+ BitSet aclRights = new BitSet();
+ aclRights.set(READ.ordinal());
+ aclRights.set(WRITE.ordinal());
+ return new OzoneAcl(ACLIdentityType.WORLD, "", aclRights, ACCESS);
+ }
+
/**
* Get a valid Delegation Token.
*
diff --git a/hadoop-ozone/dist/src/main/smoketest/basic/links.robot
b/hadoop-ozone/dist/src/main/smoketest/basic/links.robot
index f89ea2d755..ba923397d6 100644
--- a/hadoop-ozone/dist/src/main/smoketest/basic/links.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/basic/links.robot
@@ -19,7 +19,7 @@ Library OperatingSystem
Resource ../commonlib.robot
Resource ../ozone-lib/shell.robot
Test Setup Run Keyword if '${SECURITY_ENABLED}' == 'true' Kinit
test user testuser testuser.keytab
-Test Timeout 2 minute
+Test Timeout 4 minute
Suite Setup Create volumes
*** Variables ***
@@ -39,35 +39,44 @@ Setup ACL tests
Execute ozone sh bucket create ${source}/readable-bucket
Execute ozone sh key put
${source}/readable-bucket/key-in-readable-bucket /etc/passwd
Execute ozone sh bucket create ${source}/unreadable-bucket
- Execute ozone sh bucket link ${source}/readable-bucket
${target}/readable-link
- Execute ozone sh bucket link ${source}/readable-bucket
${target}/unreadable-link
+
Execute ozone sh bucket link ${source}/unreadable-bucket
${target}/link-to-unreadable-bucket
+ Execute ozone sh volume addacl --acl user:testuser2:r[DEFAULT]
${target}
+
+ Execute ozone sh bucket link ${source}/readable-bucket
${target}/readable-link
+ Execute ozone sh bucket link ${source}/readable-bucket
${target}/readable-link2
- Execute ozone sh volume addacl --acl user:testuser2:r ${target}
Execute ozone sh volume addacl --acl user:testuser2:rl
${source}
Execute ozone sh bucket addacl --acl user:testuser2:rl
${source}/readable-bucket
- Execute ozone sh bucket addacl --acl user:testuser2:r
${target}/readable-link
- Execute ozone sh bucket addacl --acl user:testuser2:r
${target}/link-to-unreadable-bucket
+
+Verify Bucket ACL
+ [arguments] ${source_option} ${object} ${type} ${name}
${acls}
+ ${actual_acls} = Execute ozone sh bucket getacl
${source_option} ${object} | jq -r '.[] | select(.type == "${type}") |
select(.name == "${name}") | .aclList[]' | xargs
+ Should Be Equal ${acls} ${actual_acls}
Can follow link with read access
Execute kdestroy
Run Keyword Kinit test user testuser2
testuser2.keytab
${result} = Execute And Ignore Error ozone sh key list
${target}/readable-link
Should Contain ${result}
key-in-readable-bucket
+ ${result} = Execute And Ignore Error ozone sh key list
${target}/readable-link2
+ Should Contain ${result}
key-in-readable-bucket
Cannot follow link without read access
Execute kdestroy
Run Keyword Kinit test user testuser2
testuser2.keytab
- ${result} = Execute And Ignore Error ozone sh key list
${target}/unreadable-link
+ ${result} = Execute And Ignore Error ozone sh key list
${target}/link-to-unreadable-bucket
+ Should Contain ${result}
PERMISSION_DENIED
+ ${result} = Execute And Ignore Error ozone sh key list
${source}/unreadable-bucket
Should Contain ${result}
PERMISSION_DENIED
-ACL verified on source bucket
+ACL verified on source and target bucket
Execute kdestroy
Run Keyword Kinit test user testuser2
testuser2.keytab
${result} = Execute ozone sh bucket info
${target}/link-to-unreadable-bucket
Should Contain ${result}
link-to-unreadable-bucket
Should Not Contain ${result}
PERMISSION_DENIED
- ${result} = Execute And Ignore Error ozone sh key list
${target}/link-to-unreadable-bucket
+ ${result} = Execute And Ignore Error ozone sh bucket info
${source}/unreadable-bucket
Should Contain ${result}
PERMISSION_DENIED
Create link loop
@@ -124,14 +133,39 @@ Bucket info shows source
Should Contain ${result}
creationTime
Should Not contain ${result}
metadata
-Source and target have separate ACLs
- Execute ozone sh bucket addacl --acl user:user1:rwxy ${target}/link1
- Verify ACL bucket ${target}/link1 USER user1 READ WRITE
READ_ACL WRITE_ACL
- Verify ACL bucket ${source}/bucket1 USER user1 ${EMPTY}
-
- Execute ozone sh bucket addacl --acl group:group2:r ${source}/bucket1
- Verify ACL bucket ${target}/link1 GROUP group2 ${EMPTY}
- Verify ACL bucket ${source}/bucket1 GROUP group2 READ
+Source and target bucket have different ACLs
+ Execute ozone sh bucket addacl --acl user:user1:rwxy
${target}/link1
+ Verify ACL bucket ${target}/link1 USER user1
${EMPTY}
+ Verify Bucket ACL --source=false ${target}/link1 USER user1
${EMPTY}
+ Verify Bucket ACL --source ${target}/link1 USER user1
READ WRITE READ_ACL WRITE_ACL
+ Verify ACL bucket ${source}/bucket1 USER user1
READ WRITE READ_ACL WRITE_ACL
+
+ Execute ozone sh bucket removeacl --acl user:user1:y
${target}/link1
+ Verify ACL bucket ${target}/link1 USER user1
${EMPTY}
+ Verify Bucket ACL --source ${target}/link1 USER user1
READ WRITE READ_ACL
+
+ Execute ozone sh bucket setacl --acl user:user1:rw
${source}/bucket1
+ Verify ACL bucket ${target}/link1 USER user1
${EMPTY}
+ Verify Bucket ACL --source ${target}/link1 USER user1
READ WRITE
+
+ Execute ozone sh bucket addacl --acl group:group2:r
${source}/bucket1
+ Verify ACL bucket ${target}/link1 GROUP group2
${EMPTY}
+ Verify Bucket ACL --source ${target}/link1 GROUP group2
READ
+
+Source and target key have same ACLs
+ Execute ozone sh key addacl --acl user:user1:rwxy
${source}/bucket1/key1
+ Verify ACL key ${target}/link1/key1 USER user1
READ WRITE READ_ACL WRITE_ACL
+ Verify ACL key ${source}/bucket1/key1 USER user1
READ WRITE READ_ACL WRITE_ACL
+ Execute ozone sh key removeacl --acl user:user1:y
${target}/link1/key1
+ Verify ACL key ${target}/link1/key1 USER user1
READ WRITE READ_ACL
+ Verify ACL key ${source}/bucket1/key1 USER user1
READ WRITE READ_ACL
+ Execute ozone sh key setacl --acl user:user1:rw
${source}/bucket1/key1
+ Verify ACL key ${target}/link1/key1 USER user1
READ WRITE
+ Verify ACL key ${source}/bucket1/key1 USER user1
READ WRITE
+
+ Execute ozone sh key addacl --acl group:group2:r
${source}/bucket1/key1
+ Verify ACL key ${target}/link1/key1 GROUP group2 READ
+ Verify ACL key ${source}/bucket1/key1 GROUP group2 READ
Buckets and links share namespace
Execute ozone sh bucket link
${source}/bucket2 ${target}/link2
@@ -148,8 +182,8 @@ Can follow link with read access
Cannot follow link without read access
Run Keyword if '${SECURITY_ENABLED}' == 'true' Cannot follow link
without read access
-ACL verified on source bucket
- Run Keyword if '${SECURITY_ENABLED}' == 'true' ACL verified on
source bucket
+ACL verified on source and target bucket
+ Run Keyword if '${SECURITY_ENABLED}' == 'true' ACL verified on
source and target bucket
Loop in link chain is detected
[setup] Create link loop
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHA.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHA.java
index 6c3e085866..1e1092214c 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHA.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHA.java
@@ -25,6 +25,7 @@ import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.ozone.MiniOzoneCluster;
import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl;
import org.apache.hadoop.ozone.OzoneConfigKeys;
+import org.apache.hadoop.ozone.client.BucketArgs;
import org.apache.hadoop.ozone.client.ObjectStore;
import org.apache.hadoop.ozone.client.OzoneBucket;
import org.apache.hadoop.ozone.client.OzoneClient;
@@ -259,6 +260,40 @@ public abstract class TestOzoneManagerHA {
return ozoneBucket;
}
+ protected OzoneBucket linkBucket(OzoneBucket srcBuk) throws Exception {
+ String userName = "user" + RandomStringUtils.randomNumeric(5);
+ String adminName = "admin" + RandomStringUtils.randomNumeric(5);
+ String linkedVolName = "volume-link-" + RandomStringUtils.randomNumeric(5);
+
+ VolumeArgs createVolumeArgs = VolumeArgs.newBuilder()
+ .setOwner(userName)
+ .setAdmin(adminName)
+ .build();
+
+ BucketArgs createBucketArgs = new BucketArgs.Builder()
+ .setSourceVolume(srcBuk.getVolumeName())
+ .setSourceBucket(srcBuk.getName())
+ .build();
+
+ objectStore.createVolume(linkedVolName, createVolumeArgs);
+ OzoneVolume linkedVolumeInfo = objectStore.getVolume(linkedVolName);
+
+ Assert.assertTrue(linkedVolumeInfo.getName().equals(linkedVolName));
+ Assert.assertTrue(linkedVolumeInfo.getOwner().equals(userName));
+ Assert.assertTrue(linkedVolumeInfo.getAdmin().equals(adminName));
+
+ String linkedBucketName = UUID.randomUUID().toString();
+ linkedVolumeInfo.createBucket(linkedBucketName, createBucketArgs);
+
+ OzoneBucket linkedBucket = linkedVolumeInfo.getBucket(linkedBucketName);
+
+ Assert.assertTrue(linkedBucket.getName().equals(linkedBucketName));
+ Assert.assertTrue(linkedBucket.getVolumeName().equals(linkedVolName));
+ Assert.assertTrue(linkedBucket.isLink());
+
+ return linkedBucket;
+ }
+
/**
* Stop the current leader OM.
*
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHAWithACL.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHAWithACL.java
index 887c1a8e5d..0db1860ad0 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHAWithACL.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHAWithACL.java
@@ -25,6 +25,7 @@ import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
+import java.io.IOException;
import java.util.List;
import java.util.BitSet;
import java.util.Collections;
@@ -53,6 +54,15 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
testAddPrefixAcl();
testRemovePrefixAcl();
testSetPrefixAcl();
+
+ testLinkBucketAddBucketAcl();
+ testLinkBucketRemoveBucketAcl();
+ testLinkBucketSetBucketAcl();
+
+ testLinkBucketAddKeyAcl();
+ testLinkBucketRemoveKeyAcl();
+ testLinkBucketSetKeyAcl();
+
}
public void testAddBucketAcl() throws Exception {
@@ -61,11 +71,7 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
OzoneAcl defaultUserAcl = new OzoneAcl(USER, remoteUserName,
READ, DEFAULT);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
- .setResType(OzoneObj.ResourceType.BUCKET)
- .setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName()).build();
+ OzoneObj ozoneObj = buildBucketObj(ozoneBucket);
testAddAcl(remoteUserName, ozoneObj, defaultUserAcl);
}
@@ -76,11 +82,7 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
OzoneAcl defaultUserAcl = new OzoneAcl(USER, remoteUserName,
READ, DEFAULT);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
- .setResType(OzoneObj.ResourceType.BUCKET)
- .setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName()).build();
+ OzoneObj ozoneObj = buildBucketObj(ozoneBucket);
testRemoveAcl(remoteUserName, ozoneObj, defaultUserAcl);
@@ -92,11 +94,7 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
OzoneAcl defaultUserAcl = new OzoneAcl(USER, remoteUserName,
READ, DEFAULT);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
- .setResType(OzoneObj.ResourceType.BUCKET)
- .setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName()).build();
+ OzoneObj ozoneObj = buildBucketObj(ozoneBucket);
testSetAcl(remoteUserName, ozoneObj, defaultUserAcl);
}
@@ -133,12 +131,7 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
String key = createKey(ozoneBucket);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
- .setResType(OzoneObj.ResourceType.KEY)
- .setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName())
- .setKeyName(key).build();
+ OzoneObj ozoneObj = buildKeyObj(ozoneBucket, key);
testAddAcl(remoteUserName, ozoneObj, userAcl);
}
@@ -151,12 +144,7 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
String key = createKey(ozoneBucket);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
- .setResType(OzoneObj.ResourceType.KEY)
- .setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName())
- .setKeyName(key).build();
+ OzoneObj ozoneObj = buildKeyObj(ozoneBucket, key);
testRemoveAcl(remoteUserName, ozoneObj, userAcl);
@@ -170,12 +158,7 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
String key = createKey(ozoneBucket);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
- .setResType(OzoneObj.ResourceType.KEY)
- .setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName())
- .setKeyName(key).build();
+ OzoneObj ozoneObj = buildKeyObj(ozoneBucket, key);
testSetAcl(remoteUserName, ozoneObj, userAcl);
@@ -188,12 +171,7 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
OzoneAcl defaultUserAcl = new OzoneAcl(USER, remoteUserName,
READ, DEFAULT);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
- .setResType(OzoneObj.ResourceType.PREFIX)
- .setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName())
- .setPrefixName(prefixName).build();
+ OzoneObj ozoneObj = buildPrefixObj(ozoneBucket, prefixName);
testAddAcl(remoteUserName, ozoneObj, defaultUserAcl);
}
@@ -207,12 +185,7 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
OzoneAcl userAcl1 = new OzoneAcl(USER, "remote",
READ, ACCESS);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
- .setResType(OzoneObj.ResourceType.PREFIX)
- .setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName())
- .setPrefixName(prefixName).build();
+ OzoneObj ozoneObj = buildPrefixObj(ozoneBucket, prefixName);
ObjectStore objectStore = getObjectStore();
@@ -241,16 +214,201 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
OzoneAcl defaultUserAcl = new OzoneAcl(USER, remoteUserName,
READ, DEFAULT);
- OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder()
+ OzoneObj ozoneObj = buildPrefixObj(ozoneBucket, prefixName);
+
+ testSetAcl(remoteUserName, ozoneObj, defaultUserAcl);
+ }
+
+ public void testLinkBucketAddBucketAcl() throws Exception {
+ OzoneBucket srcBucket = setupBucket();
+ OzoneBucket linkedBucket = linkBucket(srcBucket);
+
+ OzoneObj linkObj = buildBucketObj(linkedBucket);
+ OzoneObj srcObj = buildBucketObj(srcBucket);
+
+ // Add ACL to the LINK and verify that it is added to the source bucket
+ OzoneAcl acl1 = new OzoneAcl(USER, "remoteUser1", READ, DEFAULT);
+ boolean addAcl = getObjectStore().addAcl(linkObj, acl1);
+ Assert.assertTrue(addAcl);
+ assertEqualsAcls(srcObj, linkObj);
+
+ // Add ACL to the SOURCE and verify that it from link
+ OzoneAcl acl2 = new OzoneAcl(USER, "remoteUser2", WRITE, DEFAULT);
+ boolean addAcl2 = getObjectStore().addAcl(srcObj, acl2);
+ Assert.assertTrue(addAcl2);
+ assertEqualsAcls(srcObj, linkObj);
+
+ }
+
+ public void testLinkBucketRemoveBucketAcl() throws Exception {
+ // case1 : test remove link acl
+ OzoneBucket srcBucket = setupBucket();
+ OzoneBucket linkedBucket = linkBucket(srcBucket);
+ OzoneObj linkObj = buildBucketObj(linkedBucket);
+ OzoneObj srcObj = buildBucketObj(srcBucket);
+ // As by default create will add some default acls in RpcClient.
+ List<OzoneAcl> acls = getObjectStore().getAcl(linkObj);
+ Assert.assertTrue(acls.size() > 0);
+ // Remove an existing acl.
+ boolean removeAcl = getObjectStore().removeAcl(linkObj, acls.get(0));
+ Assert.assertTrue(removeAcl);
+ assertEqualsAcls(srcObj, linkObj);
+
+ // case2 : test remove src acl
+ OzoneBucket srcBucket2 = setupBucket();
+ OzoneBucket linkedBucket2 = linkBucket(srcBucket2);
+ OzoneObj linkObj2 = buildBucketObj(linkedBucket2);
+ OzoneObj srcObj2 = buildBucketObj(srcBucket2);
+ // As by default create will add some default acls in RpcClient.
+ List<OzoneAcl> acls2 = getObjectStore().getAcl(srcObj2);
+ Assert.assertTrue(acls2.size() > 0);
+ // Remove an existing acl.
+ boolean removeAcl2 = getObjectStore().removeAcl(srcObj2, acls.get(0));
+ Assert.assertTrue(removeAcl2);
+ assertEqualsAcls(srcObj2, linkObj2);
+
+ }
+
+ public void testLinkBucketSetBucketAcl() throws Exception {
+ OzoneBucket srcBucket = setupBucket();
+ OzoneBucket linkedBucket = linkBucket(srcBucket);
+
+ OzoneObj linkObj = buildBucketObj(linkedBucket);
+ OzoneObj srcObj = buildBucketObj(srcBucket);
+
+ // Set ACL to the LINK and verify that it is set to the source bucket
+ List<OzoneAcl> acl1 = Collections.singletonList(
+ new OzoneAcl(USER, "remoteUser1", READ, DEFAULT));
+ boolean setAcl1 = getObjectStore().setAcl(linkObj, acl1);
+ Assert.assertTrue(setAcl1);
+ assertEqualsAcls(srcObj, linkObj);
+
+ // Set ACL to the SOURCE and verify that it from link
+ List<OzoneAcl> acl2 = Collections.singletonList(
+ new OzoneAcl(USER, "remoteUser2", WRITE, DEFAULT));
+ boolean setAcl2 = getObjectStore().setAcl(srcObj, acl2);
+ Assert.assertTrue(setAcl2);
+ assertEqualsAcls(srcObj, linkObj);
+
+ }
+
+ public void testLinkBucketAddKeyAcl() throws Exception {
+ OzoneBucket srcBucket = setupBucket();
+ OzoneBucket linkedBucket = linkBucket(srcBucket);
+ String key = createKey(linkedBucket);
+ OzoneObj linkObj = buildKeyObj(linkedBucket, key);
+ OzoneObj srcObj = buildKeyObj(srcBucket, key);
+
+ String user1 = "remoteUser1";
+ OzoneAcl acl1 = new OzoneAcl(USER, user1, READ, DEFAULT);
+ testAddAcl(user1, linkObj, acl1); // case1: set link acl
+ assertEqualsAcls(srcObj, linkObj);
+
+ String user2 = "remoteUser2";
+ OzoneAcl acl2 = new OzoneAcl(USER, user2, READ, DEFAULT);
+ testAddAcl(user2, srcObj, acl2); // case2: set src acl
+ assertEqualsAcls(srcObj, linkObj);
+
+ }
+
+ public void testLinkBucketRemoveKeyAcl() throws Exception {
+
+ // CASE 1: from link bucket
+ OzoneBucket srcBucket = setupBucket();
+ OzoneBucket linkedBucket = linkBucket(srcBucket);
+ String key = createKey(linkedBucket);
+ OzoneObj linkObj = buildKeyObj(linkedBucket, key);
+ OzoneObj srcObj = buildKeyObj(srcBucket, key);
+ String user = "remoteUser1";
+ OzoneAcl acl = new OzoneAcl(USER, user, READ, DEFAULT);
+ testRemoveAcl(user, linkObj, acl);
+ assertEqualsAcls(srcObj, linkObj);
+
+ // CASE 2: from src bucket
+ OzoneBucket srcBucket2 = setupBucket();
+ OzoneBucket linkedBucket2 = linkBucket(srcBucket2);
+ String key2 = createKey(srcBucket2);
+ OzoneObj linkObj2 = buildKeyObj(linkedBucket2, key2);
+ OzoneObj srcObj2 = buildKeyObj(srcBucket2, key2);
+ String user2 = "remoteUser2";
+ OzoneAcl acl2 = new OzoneAcl(USER, user2, READ, DEFAULT);
+ testRemoveAcl(user2, srcObj2, acl2);
+ assertEqualsAcls(srcObj2, linkObj2);
+
+ }
+
+ public void testLinkBucketSetKeyAcl() throws Exception {
+ OzoneBucket srcBucket = setupBucket();
+ OzoneBucket linkedBucket = linkBucket(srcBucket);
+ String key = createKey(linkedBucket);
+ OzoneObj linkObj = buildKeyObj(linkedBucket, key);
+ OzoneObj srcObj = buildKeyObj(srcBucket, key);
+
+ String user1 = "remoteUser1";
+ OzoneAcl acl1 = new OzoneAcl(USER, user1, READ, DEFAULT);
+ testSetAcl(user1, linkObj, acl1); // case1: set link acl
+ assertEqualsAcls(srcObj, linkObj);
+
+ String user2 = "remoteUser2";
+ OzoneAcl acl2 = new OzoneAcl(USER, user2, READ, DEFAULT);
+ testSetAcl(user2, srcObj, acl2); // case2: set src acl
+ assertEqualsAcls(srcObj, linkObj);
+
+ }
+
+ private OzoneObj buildBucketObj(OzoneBucket bucket) {
+ return OzoneObjInfo.Builder.newBuilder()
+ .setResType(OzoneObj.ResourceType.BUCKET)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .setVolumeName(bucket.getVolumeName())
+ .setBucketName(bucket.getName()).build();
+ }
+
+ private OzoneObj buildKeyObj(OzoneBucket bucket, String key) {
+ return OzoneObjInfo.Builder.newBuilder()
+ .setResType(OzoneObj.ResourceType.KEY)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .setVolumeName(bucket.getVolumeName())
+ .setBucketName(bucket.getName())
+ .setKeyName(key).build();
+ }
+
+ private OzoneObj buildPrefixObj(OzoneBucket bucket, String prefix) {
+ return OzoneObjInfo.Builder.newBuilder()
.setResType(OzoneObj.ResourceType.PREFIX)
.setStoreType(OzoneObj.StoreType.OZONE)
- .setVolumeName(ozoneBucket.getVolumeName())
- .setBucketName(ozoneBucket.getName())
- .setPrefixName(prefixName).build();
+ .setVolumeName(bucket.getVolumeName())
+ .setBucketName(bucket.getName())
+ .setPrefixName(prefix).build();
+ }
- testSetAcl(remoteUserName, ozoneObj, defaultUserAcl);
+ private void assertEqualsAcls(OzoneObj srcObj, OzoneObj linkObj)
+ throws IOException {
+ if (linkObj.getResourceType() == OzoneObj.ResourceType.BUCKET) {
+ linkObj = getSourceBucketObj(linkObj);
+ }
+ Assert.assertEquals(getObjectStore().getAcl(srcObj),
+ getObjectStore().getAcl(linkObj));
}
+ private OzoneObj getSourceBucketObj(OzoneObj obj)
+ throws IOException {
+ assert obj.getResourceType() == OzoneObj.ResourceType.BUCKET;
+ OzoneBucket bucket = getObjectStore()
+ .getVolume(obj.getVolumeName())
+ .getBucket(obj.getBucketName());
+ if (!bucket.isLink()) {
+ return obj;
+ }
+ obj = OzoneObjInfo.Builder.newBuilder()
+ .setBucketName(bucket.getSourceBucket())
+ .setVolumeName(bucket.getSourceVolume())
+ .setKeyName(obj.getKeyName())
+ .setResType(obj.getResourceType())
+ .setStoreType(obj.getStoreType())
+ .build();
+ return getSourceBucketObj(obj);
+ }
private void testSetAcl(String remoteUserName, OzoneObj ozoneObj,
OzoneAcl userAcl) throws Exception {
@@ -303,6 +461,27 @@ public class TestOzoneManagerHAWithACL extends
TestOzoneManagerHA {
Assert.assertTrue(addAcl);
}
+ private void testAddLinkAcl(String remoteUserName, OzoneObj ozoneObj,
+ OzoneAcl userAcl) throws Exception {
+ ObjectStore objectStore = getObjectStore();
+ boolean addAcl = objectStore.addAcl(ozoneObj, userAcl);
+ Assert.assertTrue(addAcl);
+
+ List<OzoneAcl> acls = objectStore.getAcl(ozoneObj);
+
+ Assert.assertTrue(containsAcl(userAcl, acls));
+
+ // Add an already existing acl.
+ addAcl = objectStore.addAcl(ozoneObj, userAcl);
+ Assert.assertFalse(addAcl);
+
+ // Add an acl by changing acl type with same type, name and scope.
+ userAcl = new OzoneAcl(USER, remoteUserName,
+ WRITE, DEFAULT);
+ addAcl = objectStore.addAcl(ozoneObj, userAcl);
+ Assert.assertTrue(addAcl);
+ }
+
private void testRemoveAcl(String remoteUserName, OzoneObj ozoneObj,
OzoneAcl userAcl) throws Exception {
ObjectStore objectStore = getObjectStore();
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/BucketManagerImpl.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/BucketManagerImpl.java
index 9df006ec08..815eee2924 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/BucketManagerImpl.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/BucketManagerImpl.java
@@ -21,10 +21,12 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.helpers.OzoneAclUtil;
+import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType;
import org.apache.hadoop.ozone.security.acl.OzoneObj;
import org.apache.hadoop.ozone.security.acl.RequestContext;
@@ -49,9 +51,13 @@ public class BucketManagerImpl implements BucketManager {
private static final Logger LOG =
LoggerFactory.getLogger(BucketManagerImpl.class);
+ private final OzoneManager ozoneManager;
+
private final OMMetadataManager metadataManager;
- public BucketManagerImpl(OMMetadataManager metadataManager) {
+ public BucketManagerImpl(OzoneManager ozoneManager,
+ OMMetadataManager metadataManager) {
+ this.ozoneManager = ozoneManager;
this.metadataManager = metadataManager;
}
@@ -117,6 +123,8 @@ public class BucketManagerImpl implements BucketManager {
throw new IllegalArgumentException("Unexpected argument passed to " +
"BucketManager. OzoneObj type:" + obj.getResourceType());
}
+ // bucket getAcl operation does not need resolveBucketLink in server side
+ // see: hadoop-hdds/docs/content/design/volume-management.md
String volume = obj.getVolumeName();
String bucket = obj.getBucketName();
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volume, bucket);
@@ -149,6 +157,32 @@ public class BucketManagerImpl implements BucketManager {
String volume = ozObject.getVolumeName();
String bucket = ozObject.getBucketName();
+
+ boolean bucketNeedResolved =
+ ozObject.getResourceType() == OzoneObj.ResourceType.BUCKET
+ && (context.getAclRights() != ACLType.DELETE
+ && context.getAclRights() != ACLType.READ_ACL
+ && context.getAclRights() != ACLType.READ);
+
+ if (bucketNeedResolved ||
+ ozObject.getResourceType() == OzoneObj.ResourceType.KEY) {
+ try {
+ ResolvedBucket resolvedBucket =
+ ozoneManager.resolveBucketLink(
+ Pair.of(ozObject.getVolumeName(), ozObject.getBucketName()));
+ volume = resolvedBucket.realVolume();
+ bucket = resolvedBucket.realBucket();
+ } catch (IOException e) {
+ if (e instanceof OMException &&
+ ((OMException) e).getResult() == BUCKET_NOT_FOUND) {
+ LOG.warn("checkAccess on non-exist source bucket " +
+ "Volume:{} Bucket:{}.", volume, bucket);
+ } else {
+ throw new OMException(e.getMessage(), INTERNAL_ERROR);
+ }
+ }
+ }
+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volume, bucket);
try {
String dbBucketKey = metadataManager.getBucketKey(volume, bucket);
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/KeyManagerImpl.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/KeyManagerImpl.java
index e94f6e021a..9c5ad7081a 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/KeyManagerImpl.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/KeyManagerImpl.java
@@ -41,6 +41,7 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.conf.StorageUnit;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
import
org.apache.hadoop.crypto.key.KeyProviderCryptoExtension.EncryptedKeyVersion;
@@ -864,8 +865,10 @@ public class KeyManagerImpl implements KeyManager {
@Override
public List<OzoneAcl> getAcl(OzoneObj obj) throws IOException {
validateOzoneObj(obj);
- String volume = obj.getVolumeName();
- String bucket = obj.getBucketName();
+ ResolvedBucket resolvedBucket = ozoneManager.resolveBucketLink(
+ Pair.of(obj.getVolumeName(), obj.getBucketName()));
+ String volume = resolvedBucket.realVolume();
+ String bucket = resolvedBucket.realBucket();
String keyName = obj.getKeyName();
OmKeyInfo keyInfo;
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volume, bucket);
@@ -907,8 +910,15 @@ public class KeyManagerImpl implements KeyManager {
Objects.requireNonNull(context);
Objects.requireNonNull(context.getClientUgi());
- String volume = ozObject.getVolumeName();
- String bucket = ozObject.getBucketName();
+ ResolvedBucket resolvedBucket;
+ try {
+ resolvedBucket = ozoneManager.resolveBucketLink(
+ Pair.of(ozObject.getVolumeName(), ozObject.getBucketName()));
+ } catch (IOException e) {
+ throw new OMException("Failed to resolveBucketLink:", e, INTERNAL_ERROR);
+ }
+ String volume = resolvedBucket.realVolume();
+ String bucket = resolvedBucket.realBucket();
String keyName = ozObject.getKeyName();
String objectKey = metadataManager.getOzoneKey(volume, bucket, keyName);
OmKeyArgs args = new OmKeyArgs.Builder()
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataReader.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataReader.java
index b21dab2522..e429b82d35 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataReader.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataReader.java
@@ -371,12 +371,22 @@ public class OmMetadataReader implements
IOmMetadataReader, Auditor {
* @throws IOException if there is error.
*/
public List<OzoneAcl> getAcl(OzoneObj obj) throws IOException {
+
+ String volumeName = obj.getVolumeName();
+ String bucketName = obj.getBucketName();
+ String keyName = obj.getKeyName();
+ if (obj.getResourceType() == ResourceType.KEY) {
+ ResolvedBucket resolvedBucket = ozoneManager.resolveBucketLink(
+ Pair.of(volumeName, bucketName));
+ volumeName = resolvedBucket.realVolume();
+ bucketName = resolvedBucket.realBucket();
+ }
boolean auditSuccess = true;
try {
if (isAclEnabled) {
checkAcls(obj.getResourceType(), obj.getStoreType(), ACLType.READ_ACL,
- obj.getVolumeName(), obj.getBucketName(), obj.getKeyName());
+ volumeName, bucketName, keyName);
}
metrics.incNumGetAcl();
switch (obj.getResourceType()) {
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmSnapshotManager.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmSnapshotManager.java
index eb5ea0f299..d6f4dd79cf 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmSnapshotManager.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmSnapshotManager.java
@@ -328,7 +328,7 @@ public final class OmSnapshotManager implements
AutoCloseable {
// metadataManager
PrefixManagerImpl pm = new PrefixManagerImpl(snapshotMetadataManager,
false);
- KeyManagerImpl km = new KeyManagerImpl(null,
+ KeyManagerImpl km = new KeyManagerImpl(ozoneManager,
ozoneManager.getScmClient(), snapshotMetadataManager, conf,
ozoneManager.getBlockTokenSecretManager(),
ozoneManager.getKmsProvider(), ozoneManager.getPerfMetrics());
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index fc1337dd38..0bdcc10cf9 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -793,7 +793,8 @@ public final class OzoneManager extends
ServiceRuntimeInfoImpl
OzoneAclUtils.setOMMultiTenantManager(multiTenantManager);
}
volumeManager = new VolumeManagerImpl(metadataManager);
- bucketManager = new BucketManagerImpl(metadataManager);
+
+ bucketManager = new BucketManagerImpl(this, metadataManager);
Class<? extends S3SecretStoreProvider> storeProviderClass =
configuration.getClass(
@@ -810,6 +811,7 @@ public final class OzoneManager extends
ServiceRuntimeInfoImpl
throw new IOException(e);
}
S3SecretCacheProvider secretCacheProvider =
S3SecretCacheProvider.IN_MEMORY;
+
s3SecretManager = new S3SecretLockedManager(
new S3SecretManagerImpl(
store,
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/acl/OMBucketAclRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/acl/OMBucketAclRequest.java
index 6d9868f055..5baee40801 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/acl/OMBucketAclRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/acl/OMBucketAclRequest.java
@@ -22,12 +22,14 @@ import java.io.IOException;
import java.util.List;
import java.util.Map;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.audit.AuditLogger;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OMMetrics;
import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.ResolvedBucket;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper;
@@ -88,9 +90,10 @@ public abstract class OMBucketAclRequest extends
OMClientRequest {
try {
ObjectParser objectParser = new ObjectParser(getPath(),
ObjectType.BUCKET);
-
- volume = objectParser.getVolume();
- bucket = objectParser.getBucket();
+ ResolvedBucket resolvedBucket = ozoneManager.resolveBucketLink(
+ Pair.of(objectParser.getVolume(), objectParser.getBucket()));
+ volume = resolvedBucket.realVolume();
+ bucket = resolvedBucket.realBucket();
// check Acl
if (ozoneManager.getAclsEnabled()) {
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAclRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAclRequest.java
index 1cbbebed73..b13ce21ea8 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAclRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAclRequest.java
@@ -21,9 +21,11 @@ package org.apache.hadoop.ozone.om.request.key.acl;
import java.io.IOException;
import java.util.Map;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.ozone.audit.AuditLogger;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.ResolvedBucket;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
@@ -80,9 +82,10 @@ public abstract class OMKeyAclRequest extends
OMClientRequest {
try {
ObjectParser objectParser = new ObjectParser(getPath(),
ObjectType.KEY);
-
- volume = objectParser.getVolume();
- bucket = objectParser.getBucket();
+ ResolvedBucket resolvedBucket = ozoneManager.resolveBucketLink(
+ Pair.of(objectParser.getVolume(), objectParser.getBucket()));
+ volume = resolvedBucket.realVolume();
+ bucket = resolvedBucket.realBucket();
key = objectParser.getKey();
// check Acl
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAclRequestWithFSO.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAclRequestWithFSO.java
index ca43c43c72..e83486bb90 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAclRequestWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAclRequestWithFSO.java
@@ -17,11 +17,13 @@
*/
package org.apache.hadoop.ozone.om.request.key.acl;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.hdds.utils.db.Table;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.ResolvedBucket;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.helpers.OmDirectoryInfo;
@@ -73,9 +75,10 @@ public abstract class OMKeyAclRequestWithFSO extends
OMKeyAclRequest {
try {
ObjectParser objectParser = new ObjectParser(getPath(),
OzoneManagerProtocolProtos.OzoneObj.ObjectType.KEY);
-
- volume = objectParser.getVolume();
- bucket = objectParser.getBucket();
+ ResolvedBucket resolvedBucket = ozoneManager.resolveBucketLink(
+ Pair.of(objectParser.getVolume(), objectParser.getBucket()));
+ volume = resolvedBucket.realVolume();
+ bucket = resolvedBucket.realBucket();
key = objectParser.getKey();
// check Acl
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestBucketRequest.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestBucketRequest.java
index 1b6923ed44..cd036c373e 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestBucketRequest.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestBucketRequest.java
@@ -19,6 +19,8 @@
package org.apache.hadoop.ozone.om.request.bucket;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.hadoop.ozone.om.ResolvedBucket;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager;
import org.junit.After;
@@ -88,6 +90,10 @@ public class TestBucketRequest {
auditLogger = Mockito.mock(AuditLogger.class);
when(ozoneManager.getAuditLogger()).thenReturn(auditLogger);
Mockito.doNothing().when(auditLogger).logWrite(any(AuditMessage.class));
+
+ when(ozoneManager.resolveBucketLink(any(Pair.class)))
+ .thenAnswer(invocation -> new ResolvedBucket(
+ invocation.getArgument(0), invocation.getArgument(0)));
}
@After
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyRequest.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyRequest.java
index 0a9eda2291..083c64db4b 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyRequest.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyRequest.java
@@ -213,6 +213,8 @@ public class TestOMKeyRequest {
when(ozoneManager.resolveBucketLink(any(Pair.class),
any(OMClientRequest.class)))
.thenReturn(new ResolvedBucket(volumeAndBucket, volumeAndBucket));
+ when(ozoneManager.resolveBucketLink(any(Pair.class)))
+ .thenReturn(new ResolvedBucket(volumeAndBucket, volumeAndBucket));
OmSnapshotManager omSnapshotManager = new OmSnapshotManager(ozoneManager);
when(ozoneManager.getOmSnapshotManager())
.thenReturn(omSnapshotManager);
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/GetAclBucketHandler.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/GetAclBucketHandler.java
index a9a2d81199..33e1493bb5 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/GetAclBucketHandler.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/GetAclBucketHandler.java
@@ -17,11 +17,17 @@
*/
package org.apache.hadoop.ozone.shell.bucket;
+import org.apache.hadoop.ozone.client.OzoneBucket;
+import org.apache.hadoop.ozone.client.OzoneClient;
+import org.apache.hadoop.ozone.security.acl.OzoneObj;
+import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
import org.apache.hadoop.ozone.shell.OzoneAddress;
import org.apache.hadoop.ozone.shell.acl.AclHandler;
import org.apache.hadoop.ozone.shell.acl.GetAclHandler;
import picocli.CommandLine;
+import java.io.IOException;
+
/**
* Get ACL of bucket.
*/
@@ -32,9 +38,40 @@ public class GetAclBucketHandler extends GetAclHandler {
@CommandLine.Mixin
private BucketUri address;
+ @CommandLine.Option(names = {"--source"},
+ defaultValue = "false",
+ description = "Display source bucket ACLs if --source=true," +
+ " default false to display ACLs of the link bucket itself.")
+ private boolean getSourceAcl;
+
@Override
protected OzoneAddress getAddress() {
return address.getValue();
}
+ @Override
+ protected void execute(OzoneClient client, OzoneObj obj) throws IOException {
+ if (getSourceAcl) {
+ obj = getSourceObj(client, obj);
+ }
+ super.execute(client, obj);
+ }
+
+ private OzoneObj getSourceObj(OzoneClient client, OzoneObj obj)
+ throws IOException {
+ OzoneBucket bucket = client.getObjectStore()
+ .getVolume(obj.getVolumeName())
+ .getBucket(obj.getBucketName());
+ if (!bucket.isLink()) {
+ return obj;
+ }
+ obj = OzoneObjInfo.Builder.newBuilder()
+ .setBucketName(bucket.getSourceBucket())
+ .setVolumeName(bucket.getSourceVolume())
+ .setKeyName(obj.getKeyName())
+ .setResType(obj.getResourceType())
+ .setStoreType(obj.getStoreType())
+ .build();
+ return getSourceObj(client, obj);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]