Skip to content

Commit 37a224b

Browse files
authored
HDDS-14899. [STS] Updates to ACLs in IamSessionPolicyResolver (#9977)
1 parent 1810c0d commit 37a224b

2 files changed

Lines changed: 68 additions & 26 deletions

File tree

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.LIST;
2727
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.READ;
2828
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.READ_ACL;
29+
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.WRITE;
2930
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.WRITE_ACL;
3031

3132
import com.fasterxml.jackson.databind.JsonNode;
@@ -868,24 +869,22 @@ enum S3Action {
868869
EnumSet.noneOf(ACLType.class)),
869870
GET_BUCKET_ACL("s3:GetBucketAcl", ActionKind.BUCKET, EnumSet.of(READ), EnumSet.of(READ, READ_ACL),
870871
EnumSet.noneOf(ACLType.class)),
871-
GET_BUCKET_LOCATION("s3:GetBucketLocation", ActionKind.BUCKET, EnumSet.of(READ), EnumSet.of(READ),
872-
EnumSet.noneOf(ACLType.class)),
873872
// Used for HeadBucket, ListObjects and ListObjectsV2 apis
874873
LIST_BUCKET("s3:ListBucket", ActionKind.BUCKET, EnumSet.of(READ), EnumSet.of(READ, LIST), EnumSet.of(READ)),
875874
// Used for ListMultipartUploads API
876875
LIST_BUCKET_MULTIPART_UPLOADS("s3:ListBucketMultipartUploads", ActionKind.BUCKET, EnumSet.of(READ),
877876
EnumSet.of(READ, LIST), EnumSet.noneOf(ACLType.class)),
878-
PUT_BUCKET_ACL("s3:PutBucketAcl", ActionKind.BUCKET, EnumSet.of(READ), EnumSet.of(WRITE_ACL),
877+
PUT_BUCKET_ACL("s3:PutBucketAcl", ActionKind.BUCKET, EnumSet.of(READ), EnumSet.of(READ, READ_ACL, WRITE_ACL),
879878
EnumSet.noneOf(ACLType.class)),
880879

881880
// Object-scope
882881
ABORT_MULTIPART_UPLOAD("s3:AbortMultipartUpload", ActionKind.OBJECT, EnumSet.of(READ), EnumSet.of(READ),
883-
EnumSet.of(DELETE)),
882+
EnumSet.of(WRITE)),
884883
// Used for DeleteObject (when versionId parameter is not supplied),
885884
// DeleteObjects (when versionId parameter is not supplied) APIs
886885
DELETE_OBJECT("s3:DeleteObject", ActionKind.OBJECT, EnumSet.of(READ), EnumSet.of(READ), EnumSet.of(DELETE)),
887886
DELETE_OBJECT_TAGGING("s3:DeleteObjectTagging", ActionKind.OBJECT, EnumSet.of(READ), EnumSet.of(READ),
888-
EnumSet.of(DELETE)),
887+
EnumSet.of(WRITE)),
889888
// Used for HeadObject, CopyObject (for source bucket), GetObject (without versionId parameter) APIs
890889
GET_OBJECT("s3:GetObject", ActionKind.OBJECT, EnumSet.of(READ), EnumSet.of(READ), EnumSet.of(READ)),
891890
GET_OBJECT_TAGGING("s3:GetObjectTagging", ActionKind.OBJECT, EnumSet.of(READ), EnumSet.of(READ), EnumSet.of(READ)),

hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ public void testBuildCaseInsensitiveS3ActionMap() {
307307
// Verify s3:Get* contains Get actions
308308
final Set<S3Action> getActions = caseInsensitiveS3ActionMap.get("s3:get*");
309309
assertThat(getActions).containsOnly(
310-
S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_BUCKET_LOCATION, S3Action.GET_OBJECT_TAGGING);
310+
S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_OBJECT_TAGGING);
311311

312312
// Verify s3:Put* contains Put actions
313313
final Set<S3Action> putActions = caseInsensitiveS3ActionMap.get("s3:put*");
@@ -380,13 +380,11 @@ public void testMapPolicyActionsToS3ActionsWithMultipleActionsMapAllCorrectly()
380380
@Test
381381
public void testMapPolicyActionsToS3ActionsWithWildcardExpansion() {
382382
final Set<S3Action> result = mapPolicyActionsToS3Actions(Collections.singleton("s3:Get*"));
383-
assertThat(result).containsOnly(S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_BUCKET_LOCATION,
384-
S3Action.GET_OBJECT_TAGGING);
383+
assertThat(result).containsOnly(S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_OBJECT_TAGGING);
385384

386385
// Ensure it is case-insensitive
387386
final Set<S3Action> resultCi = mapPolicyActionsToS3Actions(Collections.singleton("s3:gET*"));
388-
assertThat(resultCi).containsOnly(S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_BUCKET_LOCATION,
389-
S3Action.GET_OBJECT_TAGGING);
387+
assertThat(resultCi).containsOnly(S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_OBJECT_TAGGING);
390388
}
391389

392390
@Test
@@ -415,15 +413,15 @@ public void testMapPolicyActionsToS3ActionsWithOnlyUnsupportedActionsReturnsEmpt
415413
@Test
416414
public void testMapPolicyActionsToS3ActionsDeduplicatesResults() {
417415
final Set<S3Action> result = mapPolicyActionsToS3Actions(strSet("s3:Get*", "s3:GetObject", "s3:GetBucketAcl"));
418-
assertThat(result).containsOnly(S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_BUCKET_LOCATION,
419-
S3Action.GET_OBJECT_TAGGING);
416+
assertThat(result).containsOnly(S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_OBJECT_TAGGING);
420417
}
421418

422419
@Test
423420
public void testMapPolicyActionsToS3ActionsHandlesMultipleWildcards() {
424421
final Set<S3Action> result = mapPolicyActionsToS3Actions(strSet("s3:Get*", "s3:Put*"));
425-
assertThat(result).containsOnly(S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_BUCKET_LOCATION,
426-
S3Action.GET_OBJECT_TAGGING, S3Action.PUT_OBJECT, S3Action.PUT_OBJECT_TAGGING, S3Action.PUT_BUCKET_ACL);
422+
assertThat(result).containsOnly(
423+
S3Action.GET_OBJECT, S3Action.GET_BUCKET_ACL, S3Action.GET_OBJECT_TAGGING, S3Action.PUT_OBJECT,
424+
S3Action.PUT_OBJECT_TAGGING, S3Action.PUT_BUCKET_ACL);
427425
}
428426

429427
@Test
@@ -768,7 +766,7 @@ public void testCreatePathsAndPermissionsWithBucketWildcardResource() {
768766
final Set<S3Action> actions = Collections.singleton(IamSessionPolicyResolver.S3Action.PUT_BUCKET_ACL);
769767
final Set<IamSessionPolicyResolver.ResourceSpec> resourceSpecs = Collections.singleton(
770768
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.BUCKET_WILDCARD, "bucket1*", null, null));
771-
final Set<IOzoneObj> writeAclObject = objSet(bucket("bucket1*"));
769+
final Set<IOzoneObj> readReadAclAndWriteAclObject = objSet(bucket("bucket1*"));
772770
final Set<IOzoneObj> readVolume = objSet(volume());
773771

774772
expectIllegalArgumentException(
@@ -779,7 +777,8 @@ public void testCreatePathsAndPermissionsWithBucketWildcardResource() {
779777
createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
780778
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
781779
assertThat(resultRanger).containsExactlyInAnyOrder(
782-
new OzoneGrant(writeAclObject, acls(WRITE_ACL)), new OzoneGrant(readVolume, acls(READ)));
780+
new OzoneGrant(readReadAclAndWriteAclObject, acls(READ, READ_ACL, WRITE_ACL)),
781+
new OzoneGrant(readVolume, acls(READ)));
783782
}
784783

785784
@Test
@@ -827,6 +826,48 @@ public void testCreatePathsAndPermissionsWithObjectExactResource() {
827826
assertThat(resultRanger).containsExactly(new OzoneGrant(readObjects, acls(READ)));
828827
}
829828

829+
@Test
830+
public void testCreatePathsAndPermissionsWithDeleteObjectGrantsDeleteOnKey() {
831+
final Set<S3Action> actions = Collections.singleton(S3Action.DELETE_OBJECT);
832+
final Set<IamSessionPolicyResolver.ResourceSpec> resourceSpecs = Collections.singleton(
833+
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_EXACT, "bucket1", null, "key.txt"));
834+
final Set<IOzoneObj> readVolumeAndBucket = objSet(volume(), bucket("bucket1"));
835+
final Set<IOzoneObj> deleteKey = objSet(key("bucket1", "key.txt"));
836+
837+
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
838+
createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
839+
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
840+
assertThat(resultNative).containsExactlyInAnyOrder(
841+
new OzoneGrant(readVolumeAndBucket, acls(READ)), new OzoneGrant(deleteKey, acls(DELETE)));
842+
843+
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
844+
createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
845+
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
846+
assertThat(resultRanger).containsExactlyInAnyOrder(
847+
new OzoneGrant(readVolumeAndBucket, acls(READ)), new OzoneGrant(deleteKey, acls(DELETE)));
848+
}
849+
850+
@Test
851+
public void testCreatePathsAndPermissionsWithAbortMultipartUploadGrantsWriteOnKey() {
852+
final Set<S3Action> actions = Collections.singleton(S3Action.ABORT_MULTIPART_UPLOAD);
853+
final Set<IamSessionPolicyResolver.ResourceSpec> resourceSpecs = Collections.singleton(
854+
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_EXACT, "bucket1", null, "key.txt"));
855+
final Set<IOzoneObj> readVolumeAndBucket = objSet(volume(), bucket("bucket1"));
856+
final Set<IOzoneObj> writeKey = objSet(key("bucket1", "key.txt"));
857+
858+
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
859+
createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
860+
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
861+
assertThat(resultNative).containsExactlyInAnyOrder(
862+
new OzoneGrant(readVolumeAndBucket, acls(READ)), new OzoneGrant(writeKey, acls(WRITE)));
863+
864+
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
865+
createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
866+
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
867+
assertThat(resultRanger).containsExactlyInAnyOrder(
868+
new OzoneGrant(readVolumeAndBucket, acls(READ)), new OzoneGrant(writeKey, acls(WRITE)));
869+
}
870+
830871
@Test
831872
public void testCreatePathsAndPermissionsWithObjectPrefixResource() {
832873
final Set<S3Action> actions = Collections.singleton(S3Action.GET_OBJECT);
@@ -983,20 +1024,22 @@ public void testCreatePathsAndPermissionsDeduplicatesAcrossSameResourceTypes() {
9831024
.collect(Collectors.toSet());
9841025
final Set<IamSessionPolicyResolver.ResourceSpec> resourceSpecs = Collections.singleton(
9851026
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_EXACT, "bucket1", null, "key.txt"));
986-
final Set<IOzoneObj> readAndDeleteObject = objSet(key("bucket1", "key.txt"));
1027+
final Set<IOzoneObj> readAndDeleteAndWriteObject = objSet(key("bucket1", "key.txt"));
9871028
final Set<IOzoneObj> readObjects = objSet(bucket("bucket1"), volume());
9881029

9891030
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
9901031
createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
9911032
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
9921033
assertThat(resultNative).containsExactlyInAnyOrder(
993-
new OzoneGrant(readAndDeleteObject, acls(READ, DELETE)), new OzoneGrant(readObjects, acls(READ)));
1034+
new OzoneGrant(readAndDeleteAndWriteObject, acls(READ, DELETE, WRITE)),
1035+
new OzoneGrant(readObjects, acls(READ)));
9941036

9951037
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
9961038
createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
9971039
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
9981040
assertThat(resultRanger).containsExactlyInAnyOrder(
999-
new OzoneGrant(readAndDeleteObject, acls(READ, DELETE)), new OzoneGrant(readObjects, acls(READ)));
1041+
new OzoneGrant(readAndDeleteAndWriteObject, acls(READ, DELETE, WRITE)),
1042+
new OzoneGrant(readObjects, acls(READ)));
10001043
}
10011044

10021045
@Test
@@ -1976,9 +2019,9 @@ public void testWildcardActionGroupPutStar() throws OMException {
19762019

19772020
// Ensure what we got is what we expected
19782021
final Set<OzoneGrant> expectedResolvedNative = new LinkedHashSet<>();
1979-
// Expected for native: bucket READ, WRITE_ACL acl
2022+
// Expected for native: bucket READ, READ_ACL, WRITE_ACL acl
19802023
final Set<IOzoneObj> bucketSet = objSet(bucket("my-bucket"));
1981-
final Set<ACLType> bucketAcl = acls(READ, WRITE_ACL);
2024+
final Set<ACLType> bucketAcl = acls(READ, READ_ACL, WRITE_ACL);
19822025
expectedResolvedNative.add(new OzoneGrant(bucketSet, bucketAcl));
19832026
// Expected for native: CREATE, WRITE acls on prefix "" under bucket
19842027
final Set<IOzoneObj> keyPrefixSet = objSet(prefix("my-bucket", ""));
@@ -1989,7 +2032,7 @@ public void testWildcardActionGroupPutStar() throws OMException {
19892032
assertThat(resolvedFromNativeAuthorizer).isEqualTo(expectedResolvedNative);
19902033

19912034
final Set<OzoneGrant> expectedResolvedRanger = new LinkedHashSet<>();
1992-
// Expected for Ranger: bucket READ, WRITE_ACL acl
2035+
// Expected for Ranger: bucket READ, READ_ACL, WRITE_ACL acl
19932036
expectedResolvedRanger.add(new OzoneGrant(bucketSet, bucketAcl));
19942037
// Expected for Ranger: CREATE, WRITE key acls for resource type KEY with key name "*"
19952038
final Set<IOzoneObj> rangerKeySet = objSet(key("my-bucket", "*"));
@@ -2017,17 +2060,17 @@ public void testWildcardActionGroupDeleteStar() throws OMException {
20172060

20182061
// Ensure what we got is what we expected
20192062
final Set<OzoneGrant> expectedResolvedNative = new LinkedHashSet<>();
2020-
// Expected for native: DELETE on prefix "" under bucket; bucket READ, DELETE; volume READ
2063+
// Expected for native: DELETE and WRITE on prefix "" under bucket; bucket READ, DELETE; volume READ
20212064
final Set<IOzoneObj> resourceSetNative = objSet(prefix("my-bucket", ""));
2022-
expectedResolvedNative.add(new OzoneGrant(resourceSetNative, acls(DELETE)));
2065+
expectedResolvedNative.add(new OzoneGrant(resourceSetNative, acls(DELETE, WRITE)));
20232066
expectedResolvedNative.add(new OzoneGrant(objSet(bucket("my-bucket")), acls(READ, DELETE)));
20242067
expectedResolvedNative.add(new OzoneGrant(objSet(volume()), acls(READ)));
20252068
assertThat(resolvedFromNativeAuthorizer).isEqualTo(expectedResolvedNative);
20262069

20272070
final Set<OzoneGrant> expectedResolvedRanger = new LinkedHashSet<>();
2028-
// Expected for Ranger: DELETE on resource type KEY with key name "*"; bucket READ, DELETE; volume READ
2071+
// Expected for Ranger: DELETE and WRITE on resource type KEY with key name "*"; bucket READ, DELETE; volume READ
20292072
final Set<IOzoneObj> resourceSetRanger = objSet(key("my-bucket", "*"));
2030-
expectedResolvedRanger.add(new OzoneGrant(resourceSetRanger, acls(DELETE)));
2073+
expectedResolvedRanger.add(new OzoneGrant(resourceSetRanger, acls(DELETE, WRITE)));
20312074
expectedResolvedRanger.add(new OzoneGrant(objSet(bucket("my-bucket")), acls(READ, DELETE)));
20322075
expectedResolvedRanger.add(new OzoneGrant(objSet(volume()), acls(READ)));
20332076
assertThat(resolvedFromRangerAuthorizer).isEqualTo(expectedResolvedRanger);

0 commit comments

Comments
 (0)