You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by sa...@apache.org on 2026/04/13 09:38:41 UTC
(ozone) branch HDDS-13323-sts updated: HDDS-14808. [STS] Part 4 - IAM Session Policy and ListBucket improvements (#9899)
This is an automated email from the ASF dual-hosted git repository.
sammichen pushed a commit to branch HDDS-13323-sts
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/HDDS-13323-sts by this push:
new 2a855ae8a72 HDDS-14808. [STS] Part 4 - IAM Session Policy and ListBucket improvements (#9899)
2a855ae8a72 is described below
commit 2a855ae8a7274036006f591cc5226035ebd8b598
Author: fmorg-git <fm...@gmail.com>
AuthorDate: Mon Apr 13 02:38:34 2026 -0700
HDDS-14808. [STS] Part 4 - IAM Session Policy and ListBucket improvements (#9899)
---
.../security/acl/iam/IamSessionPolicyResolver.java | 76 +++++++++++++------
.../acl/iam/TestIamSessionPolicyResolver.java | 85 ++++++++++++++--------
2 files changed, 106 insertions(+), 55 deletions(-)
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java
index b8b032f1b35..e45c9662952 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java
@@ -97,6 +97,8 @@ public final class IamSessionPolicyResolver {
private static final String[] S3_ACTION_PREFIXES = {"s3:Get", "s3:Put", "s3:List", "s3:Delete", "s3:Create"};
private static final String ERROR_PREFIX = "IAM session policy: ";
+ private static final String STRING_EQUALS = "StringEquals";
+ private static final String STRING_LIKE = "StringLike";
@VisibleForTesting
static final Map<String, Set<S3Action>> S3_ACTION_MAP_CI = buildCaseInsensitiveS3ActionMap();
@@ -143,7 +145,7 @@ public static Set<AssumeRoleRequest.OzoneGrant> resolve(String policyJson, Strin
final Set<String> resources = readStringOrArray(stmt.get("Resource"));
// Parse prefixes from conditions, if any
- final Set<String> prefixes = parsePrefixesFromConditions(stmt);
+ final Condition condition = parsePrefixesFromConditions(stmt);
// Map actions to S3Action enum if possible
final Set<S3Action> mappedS3Actions = mapPolicyActionsToS3Actions(actions);
@@ -156,7 +158,7 @@ public static Set<AssumeRoleRequest.OzoneGrant> resolve(String policyJson, Strin
final Set<ResourceSpec> resourceSpecs = validateAndCategorizeResources(authorizerType, resources);
// For each action, map to Ozone objects (paths) and acls based on resource specs and prefixes
- createPathsAndPermissions(volumeName, authorizerType, mappedS3Actions, resourceSpecs, prefixes, objToAclsMap);
+ createPathsAndPermissions(volumeName, authorizerType, mappedS3Actions, resourceSpecs, condition, objToAclsMap);
}
// Group accumulated objects by their ACL sets to create final result
@@ -263,10 +265,10 @@ private static Set<String> readStringOrArray(JsonNode node) {
* that if there is a Condition, there is only one and that the Condition
* operator and key name are supported.
* <p>
- * Only the StringEquals operator and s3:prefix key name are supported.
+ * Only the StringEquals and StringLike operators and s3:prefix key name are supported.
*/
- private static Set<String> parsePrefixesFromConditions(JsonNode stmt) throws OMException {
- Set<String> prefixes = Collections.emptySet();
+ private static Condition parsePrefixesFromConditions(JsonNode stmt) throws OMException {
+ Condition condition = null;
final JsonNode cond = stmt.get("Condition");
if (cond != null && !cond.isMissingNode() && !cond.isNull()) {
if (cond.size() != 1) {
@@ -275,12 +277,12 @@ private static Set<String> parsePrefixesFromConditions(JsonNode stmt) throws OME
if (!cond.isObject()) {
throw new OMException(
- ERROR_PREFIX + "Invalid Condition (must have operator StringEquals or StringLike " +
- "and key name s3:prefix) - " + cond, MALFORMED_POLICY_DOCUMENT);
+ ERROR_PREFIX + "Invalid Condition (must have operator " + STRING_EQUALS + " or " + STRING_LIKE +
+ " and key name s3:prefix) - " + cond, MALFORMED_POLICY_DOCUMENT);
}
final String operator = cond.fieldNames().next();
- if (!"StringEquals".equals(operator) && !"StringLike".equals(operator)) {
+ if (!STRING_EQUALS.equals(operator) && !STRING_LIKE.equals(operator)) {
throw new OMException(ERROR_PREFIX + "Unsupported Condition operator - " + operator, NOT_SUPPORTED_OPERATION);
}
@@ -300,10 +302,11 @@ private static Set<String> parsePrefixesFromConditions(JsonNode stmt) throws OME
throw new OMException(ERROR_PREFIX + "Unsupported Condition key name - " + keyName, NOT_SUPPORTED_OPERATION);
}
- prefixes = readStringOrArray(operatorValue.get(keyName));
+ final Set<String> prefixes = readStringOrArray(operatorValue.get(keyName));
+ condition = new Condition(operator, prefixes);
}
- return prefixes;
+ return condition;
}
/**
@@ -427,10 +430,11 @@ static Set<ResourceSpec> validateAndCategorizeResources(AuthorizerType authorize
*/
@VisibleForTesting
static void createPathsAndPermissions(String volumeName, AuthorizerType authorizerType, Set<S3Action> mappedS3Actions,
- Set<ResourceSpec> resourceSpecs, Set<String> prefixes, Map<IOzoneObj, Set<ACLType>> objToAclsMap) {
+ Set<ResourceSpec> resourceSpecs, Condition condition, Map<IOzoneObj, Set<ACLType>> objToAclsMap) {
// Process each resource spec with the given actions
for (ResourceSpec resourceSpec : resourceSpecs) {
- processResourceSpecWithActions(volumeName, authorizerType, mappedS3Actions, resourceSpec, prefixes, objToAclsMap);
+ processResourceSpecWithActions(
+ volumeName, authorizerType, mappedS3Actions, resourceSpec, condition, objToAclsMap);
}
}
@@ -461,7 +465,7 @@ static Set<AssumeRoleRequest.OzoneGrant> groupObjectsByAcls(Map<IOzoneObj, Set<A
* IOzoneObj to ACLType mappings to the provided map.
*/
private static void processResourceSpecWithActions(String volumeName, AuthorizerType authorizerType,
- Set<S3Action> mappedS3Actions, ResourceSpec resourceSpec, Set<String> prefixes,
+ Set<S3Action> mappedS3Actions, ResourceSpec resourceSpec, Condition condition,
Map<IOzoneObj, Set<ACLType>> objToAclsMap) {
// Process based on ResourceSpec type
@@ -473,13 +477,13 @@ private static void processResourceSpecWithActions(String volumeName, Authorizer
processResourceTypeAny(volumeName, mappedS3Actions, objToAclsMap);
break;
case BUCKET:
- processBucketResource(volumeName, mappedS3Actions, resourceSpec, prefixes, authorizerType, objToAclsMap);
+ processBucketResource(volumeName, mappedS3Actions, resourceSpec, condition, authorizerType, objToAclsMap);
break;
case BUCKET_WILDCARD:
Preconditions.checkArgument(
authorizerType != AuthorizerType.NATIVE,
"ResourceSpec type BUCKET_WILDCARD not supported for OzoneNativeAuthorizer");
- processBucketResource(volumeName, mappedS3Actions, resourceSpec, prefixes, authorizerType, objToAclsMap);
+ processBucketResource(volumeName, mappedS3Actions, resourceSpec, condition, authorizerType, objToAclsMap);
break;
case OBJECT_EXACT:
processObjectExactResource(volumeName, mappedS3Actions, resourceSpec, objToAclsMap);
@@ -520,7 +524,7 @@ private static void processResourceTypeAny(String volumeName, Set<S3Action> mapp
* "Resource": "arn:aws:s3:::*"
*/
private static void processBucketResource(String volumeName, Set<S3Action> mappedS3Actions,
- ResourceSpec resourceSpec, Set<String> prefixes, AuthorizerType authorizerType,
+ ResourceSpec resourceSpec, Condition condition, AuthorizerType authorizerType,
Map<IOzoneObj, Set<ACLType>> objToAclsMap) {
for (S3Action action : mappedS3Actions) {
// The s3:ListAllMyBuckets action can use either "*" or
@@ -548,12 +552,16 @@ private static void processBucketResource(String volumeName, Set<S3Action> mappe
if (action == S3Action.LIST_BUCKET || action == S3Action.ALL_S3) {
// If condition prefixes are present, these would constrain the object permissions if the action
// is s3:ListBucket or s3:* (which includes s3:ListBucket)
- if (prefixes != null && !prefixes.isEmpty()) {
- for (String prefix : prefixes) {
+ if (condition != null && condition.prefixes != null && !condition.prefixes.isEmpty()) {
+ for (String prefix : condition.prefixes) {
+ // If operator is StringEquals, we should ignore any prefix containing wildcards - this is AWS behavior
+ if (STRING_EQUALS.equals(condition.operator) && hasWildcard(prefix)) {
+ continue;
+ }
createObjectResourcesFromConditionPrefix(
volumeName, authorizerType, resourceSpec, prefix, objToAclsMap, EnumSet.of(READ));
}
- } else {
+ } else if (condition == null) {
// No condition prefixes, but we need READ access to all objects, so use "*" as the prefix
createObjectResourcesFromConditionPrefix(
volumeName, authorizerType, resourceSpec, "*", objToAclsMap, EnumSet.of(READ));
@@ -590,19 +598,21 @@ private static void processObjectExactResource(String volumeName, Set<S3Action>
private static void processObjectPrefixResource(String volumeName, AuthorizerType authorizerType,
Set<S3Action> mappedS3Actions, ResourceSpec resourceSpec, Map<IOzoneObj, Set<ACLType>> objToAclsMap) {
for (S3Action action : mappedS3Actions) {
- // Object actions apply to prefix/key resources
+ // Object actions apply to prefix/key resources - ensure to add the acls only for the appropriate action type
if (action.kind == ActionKind.OBJECT) {
addAclsForObj(objToAclsMap, volumeObj(volumeName), action.volumePerms);
addAclsForObj(objToAclsMap, bucketObj(volumeName, resourceSpec.bucket), action.bucketPerms);
+ // Handle the resource prefix itself (e.g., my-bucket/*)
+ createObjectResourcesFromResourcePrefix(
+ volumeName, authorizerType, resourceSpec, objToAclsMap, action.objectPerms);
} else if (action == S3Action.ALL_S3) {
addAclsForObj(objToAclsMap, volumeObj(volumeName), EnumSet.of(READ));
// For s3:*, ALL should only apply at the object/prefix level; grant READ at bucket level for navigation
addAclsForObj(objToAclsMap, bucketObj(volumeName, resourceSpec.bucket), EnumSet.of(READ));
+ // Handle the resource prefix itself (e.g., my-bucket/*)
+ createObjectResourcesFromResourcePrefix(
+ volumeName, authorizerType, resourceSpec, objToAclsMap, action.objectPerms);
}
-
- // Handle the resource prefix itself (e.g., my-bucket/*)
- createObjectResourcesFromResourcePrefix(
- volumeName, authorizerType, resourceSpec, objToAclsMap, action.objectPerms);
}
}
@@ -708,6 +718,20 @@ enum S3ResourceType {
OBJECT_EXACT
}
+ /**
+ * Encapsulates the Condition operator and values.
+ */
+ @VisibleForTesting
+ public static final class Condition {
+ private final String operator;
+ private final Set<String> prefixes;
+
+ public Condition(String operator, Set<String> prefixes) {
+ this.operator = operator;
+ this.prefixes = prefixes;
+ }
+ }
+
/**
* Utility to help categorize IAM policy resources, whether for bucket, key, wildcards, etc.
*/
@@ -902,4 +926,8 @@ private static IOzoneObj volumeObj(String volumeName) {
.setVolumeName(volumeName)
.build();
}
+
+ private static boolean hasWildcard(String prefix) {
+ return ((prefix.contains("*") || prefix.contains("?")));
+ }
}
diff --git a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java
index 41d2fc338f3..ae066686e70 100644
--- a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java
+++ b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java
@@ -707,11 +707,11 @@ public void testCreatePathsAndPermissionsWithResourceAny() {
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.ANY, "*", null, null));
expectIllegalArgumentException(
- () -> createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), new LinkedHashMap<>()),
+ () -> createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, new LinkedHashMap<>()),
"ResourceSpec type ANY not supported for OzoneNativeAuthorizer");
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
final Set<IOzoneObj> readAndListObjects = objSet(volume(), bucket("*")); // volume, bucket level have READ, LIST
final Set<IOzoneObj> readObject = objSet(key("*", "*")); // key level has READ
@@ -729,14 +729,14 @@ public void testCreatePathsAndPermissionsWithBucketResourceThatIsListBucket() {
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
final Set<IOzoneObj> nativeReadObjects = objSet(volume(), prefix("bucket1", ""));
- createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactlyInAnyOrder(
new OzoneGrant(readAndListObject, acls(READ, LIST)), new OzoneGrant(nativeReadObjects, acls(READ)));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
final Set<IOzoneObj> rangerReadObjects = objSet(volume(), key("bucket1", "*"));
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactlyInAnyOrder(
new OzoneGrant(readAndListObject, acls(READ, LIST)), new OzoneGrant(rangerReadObjects, acls(READ)));
@@ -751,13 +751,13 @@ public void testCreatePathsAndPermissionsWithBucketResourceThatIsNotListBucket()
final Set<IOzoneObj> readObject = objSet(volume());
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactlyInAnyOrder(
new OzoneGrant(createObject, acls(CREATE)), new OzoneGrant(readObject, acls(READ)));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactlyInAnyOrder(
new OzoneGrant(createObject, acls(CREATE)), new OzoneGrant(readObject, acls(READ)));
@@ -772,11 +772,11 @@ public void testCreatePathsAndPermissionsWithBucketWildcardResource() {
final Set<IOzoneObj> readVolume = objSet(volume());
expectIllegalArgumentException(
- () -> createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), new LinkedHashMap<>()),
+ () -> createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, new LinkedHashMap<>()),
"ResourceSpec type BUCKET_WILDCARD not supported for OzoneNativeAuthorizer");
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactlyInAnyOrder(
new OzoneGrant(writeAclObject, acls(WRITE_ACL)), new OzoneGrant(readVolume, acls(READ)));
@@ -794,11 +794,11 @@ public void testCreatePathsAndPermissionsWithBucketsWildcardResourceAll() {
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.BUCKET_WILDCARD, "*", null, null));
expectIllegalArgumentException(
- () -> createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), new LinkedHashMap<>()),
+ () -> createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, new LinkedHashMap<>()),
"ResourceSpec type BUCKET_WILDCARD not supported for OzoneNativeAuthorizer");
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
// Both the volume and the wildcard bucket should end up with READ + LIST permissions.
// We also need READ access on the keys
@@ -817,12 +817,12 @@ public void testCreatePathsAndPermissionsWithObjectExactResource() {
final Set<IOzoneObj> readObjects = objSet(key("bucket1", "key.txt"), bucket("bucket1"), volume());
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactly(new OzoneGrant(readObjects, acls(READ)));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactly(new OzoneGrant(readObjects, acls(READ)));
}
@@ -835,12 +835,12 @@ public void testCreatePathsAndPermissionsWithObjectPrefixResource() {
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_PREFIX, "bucket1", "prefix/", null));
final Set<IOzoneObj> nativeReadObjects = objSet(prefix("bucket1", "prefix/"), bucket("bucket1"), volume());
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactly(new OzoneGrant(nativeReadObjects, acls(READ)));
expectIllegalArgumentException(
- () -> createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), new LinkedHashMap<>()),
+ () -> createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, new LinkedHashMap<>()),
"ResourceSpec type OBJECT_PREFIX not supported for RangerOzoneAuthorizer");
}
@@ -851,12 +851,12 @@ public void testCreatePathsAndPermissionsWithObjectPrefixWildcardResource() {
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_PREFIX_WILDCARD, "bucket1", "prefix/*", null));
expectIllegalArgumentException(
- () -> createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), new LinkedHashMap<>()),
+ () -> createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, new LinkedHashMap<>()),
"ResourceSpec type OBJECT_PREFIX_WILDCARD not supported for OzoneNativeAuthorizer");
final Set<IOzoneObj> rangerReadObjects = objSet(key("bucket1", "prefix/*"), bucket("bucket1"), volume());
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactly(new OzoneGrant(rangerReadObjects, acls(READ)));
}
@@ -865,12 +865,14 @@ public void testCreatePathsAndPermissionsWithObjectPrefixWildcardResource() {
public void testCreatePathsAndPermissionsWithConditionPrefixesForObjectActionMustIgnoreConditionPrefixes() {
final Set<S3Action> actions = Collections.singleton(S3Action.GET_OBJECT);
final Set<String> prefixes = strSet("folder1/", "folder2/");
+ final IamSessionPolicyResolver.Condition condition = new IamSessionPolicyResolver.Condition(
+ "StringEquals", prefixes);
final Set<IamSessionPolicyResolver.ResourceSpec> nativeResourceSpecs = Collections.singleton(
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_PREFIX, "bucket1", "", null));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
final Set<IOzoneObj> nativeReadObjects = objSet(prefix("bucket1", ""), bucket("bucket1"), volume());
- createPathsAndPermissions(VOLUME, NATIVE, actions, nativeResourceSpecs, prefixes, objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, nativeResourceSpecs, condition, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactly(new OzoneGrant(nativeReadObjects, acls(READ)));
@@ -878,7 +880,7 @@ public void testCreatePathsAndPermissionsWithConditionPrefixesForObjectActionMus
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_PREFIX_WILDCARD, "bucket1", "*", null));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
final Set<IOzoneObj> rangerReadObjects = objSet(key("bucket1", "*"), bucket("bucket1"), volume());
- createPathsAndPermissions(VOLUME, RANGER, actions, rangerResourceSpecs, prefixes, objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, rangerResourceSpecs, condition, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactly(new OzoneGrant(rangerReadObjects, acls(READ)));
}
@@ -887,6 +889,8 @@ public void testCreatePathsAndPermissionsWithConditionPrefixesForObjectActionMus
public void testCreatePathsAndPermissionsWithConditionPrefixesForBucketActionWhenActionIsListBucket() {
final Set<S3Action> actions = Collections.singleton(S3Action.LIST_BUCKET);
final Set<String> prefixes = strSet("folder1/", "folder2/");
+ final IamSessionPolicyResolver.Condition condition = new IamSessionPolicyResolver.Condition(
+ "StringEquals", prefixes);
final Set<IamSessionPolicyResolver.ResourceSpec> nativeResourceSpecs = Collections.singleton(
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.BUCKET, "bucket1", null, null));
@@ -894,7 +898,7 @@ public void testCreatePathsAndPermissionsWithConditionPrefixesForBucketActionWhe
prefix("bucket1", "folder1/"), prefix("bucket1", "folder2/"), volume());
final Set<IOzoneObj> nativeReadAndListObject = objSet(bucket("bucket1"));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, nativeResourceSpecs, prefixes, objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, nativeResourceSpecs, condition, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactlyInAnyOrder(
new OzoneGrant(nativeReadObjects, acls(READ)), new OzoneGrant(nativeReadAndListObject, acls(READ, LIST)));
@@ -905,7 +909,7 @@ public void testCreatePathsAndPermissionsWithConditionPrefixesForBucketActionWhe
key("bucket1", "folder1/"), key("bucket1", "folder2/"), volume());
final Set<IOzoneObj> rangerReadAndListObject = objSet(bucket("bucket1"));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, rangerResourceSpecs, prefixes, objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, rangerResourceSpecs, condition, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactlyInAnyOrder(
new OzoneGrant(rangerReadObjects, acls(READ)), new OzoneGrant(rangerReadAndListObject, acls(READ, LIST)));
@@ -915,13 +919,15 @@ public void testCreatePathsAndPermissionsWithConditionPrefixesForBucketActionWhe
public void testCreatePathsAndPermissionsWithConditionPrefixesForBucketActionWhenActionIsNotListBucket() {
final Set<S3Action> actions = Collections.singleton(S3Action.GET_BUCKET_ACL);
final Set<String> prefixes = strSet("folder1/", "folder2/");
+ final IamSessionPolicyResolver.Condition condition = new IamSessionPolicyResolver.Condition(
+ "StringEquals", prefixes);
final Set<IOzoneObj> readObject = objSet(volume());
final Set<IOzoneObj> readAndReadAclObject = objSet(bucket("bucket1"));
final Set<IamSessionPolicyResolver.ResourceSpec> nativeResourceSpecs = Collections.singleton(
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.BUCKET, "bucket1", null, null));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, nativeResourceSpecs, prefixes, objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, nativeResourceSpecs, condition, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactlyInAnyOrder(
new OzoneGrant(readObject, acls(READ)), new OzoneGrant(readAndReadAclObject, acls(READ, READ_ACL)));
@@ -929,7 +935,7 @@ public void testCreatePathsAndPermissionsWithConditionPrefixesForBucketActionWhe
final Set<IamSessionPolicyResolver.ResourceSpec> rangerResourceSpecs = Collections.singleton(
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.BUCKET, "bucket1", null, null));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, rangerResourceSpecs, prefixes, objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, rangerResourceSpecs, condition, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactlyInAnyOrder(
new OzoneGrant(readObject, acls(READ)), new OzoneGrant(readAndReadAclObject, acls(READ, READ_ACL)));
@@ -942,14 +948,14 @@ public void testCreatePathsAndPermissionsWithNoMappedActions() {
final Set<IamSessionPolicyResolver.ResourceSpec> nativeResourceSpecs = Collections.singleton(
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_PREFIX, "bucket1", null, null));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, nativeResourceSpecs, emptySet(), objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, nativeResourceSpecs, null, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).isEmpty();
final Set<IamSessionPolicyResolver.ResourceSpec> rangerResourceSpecs = Collections.singleton(
new IamSessionPolicyResolver.ResourceSpec(S3ResourceType.OBJECT_PREFIX_WILDCARD, "bucket1", null, null));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, rangerResourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, rangerResourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).isEmpty();
}
@@ -960,12 +966,12 @@ public void testCreatePathsAndPermissionsWithNoMappedResources() {
final Set<IamSessionPolicyResolver.ResourceSpec> resourceSpecs = emptySet();
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).isEmpty();
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).isEmpty();
}
@@ -981,13 +987,13 @@ public void testCreatePathsAndPermissionsDeduplicatesAcrossSameResourceTypes() {
final Set<IOzoneObj> readObjects = objSet(bucket("bucket1"), volume());
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactlyInAnyOrder(
new OzoneGrant(readAndDeleteObject, acls(READ, DELETE)), new OzoneGrant(readObjects, acls(READ)));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactlyInAnyOrder(
new OzoneGrant(readAndDeleteObject, acls(READ, DELETE)), new OzoneGrant(readObjects, acls(READ)));
@@ -1006,14 +1012,14 @@ public void testCreatePathsAndPermissionsWithAllS3ActionsOverridesAnyOtherAction
final Set<IOzoneObj> nativeReadObjects = objSet(volume(), bucket("bucket1"), prefix("bucket2", ""));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapNative = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, emptySet(), objToAclsMapNative);
+ createPathsAndPermissions(VOLUME, NATIVE, actions, resourceSpecs, null, objToAclsMapNative);
final Set<OzoneGrant> resultNative = groupObjectsByAcls(objToAclsMapNative);
assertThat(resultNative).containsExactlyInAnyOrder(
new OzoneGrant(allObjects, acls(ALL)), new OzoneGrant(nativeReadObjects, acls(READ)));
final Set<IOzoneObj> rangerReadObjects = objSet(volume(), bucket("bucket1"), key("bucket2", "*"));
final Map<IOzoneObj, Set<ACLType>> objToAclsMapRanger = new LinkedHashMap<>();
- createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, emptySet(), objToAclsMapRanger);
+ createPathsAndPermissions(VOLUME, RANGER, actions, resourceSpecs, null, objToAclsMapRanger);
final Set<OzoneGrant> resultRanger = groupObjectsByAcls(objToAclsMapRanger);
assertThat(resultRanger).containsExactlyInAnyOrder(
new OzoneGrant(allObjects, acls(ALL)), new OzoneGrant(rangerReadObjects, acls(READ)));
@@ -1519,7 +1525,7 @@ public void testIgnoresUnsupportedActionsWhenSupportedActionsAreIncluded() throw
" ],\n" +
" \"Resource\": \"arn:aws:s3:::bucket1\",\n" +
" \"Condition\": {\n" +
- " \"StringEquals\": {\n" +
+ " \"StringLike\": {\n" +
" \"s3:prefix\": [ \"team/folder\", \"team/folder/*\" ]\n" +
" }\n" +
" }\n" +
@@ -1577,6 +1583,23 @@ public void testMultiplePrefixesWithWildcards() throws OMException {
assertThat(resolvedFromRangerAuthorizer).isEqualTo(expectedResolvedRanger);
}
+ @Test
+ public void testListBucketOnObjectResourceReturnsEmpty() throws OMException {
+ final String json = "{\n" +
+ " \"Statement\": [{\n" +
+ " \"Effect\": \"Allow\",\n" +
+ " \"Action\": \"s3:ListBucket\",\n" +
+ " \"Resource\": \"arn:aws:s3:::logs/*\"\n" +
+ " }]\n" +
+ "}";
+
+ final Set<OzoneGrant> resolvedFromNativeAuthorizer = resolve(json, VOLUME, NATIVE);
+ final Set<OzoneGrant> resolvedFromRangerAuthorizer = resolve(json, VOLUME, RANGER);
+
+ assertThat(resolvedFromNativeAuthorizer).isEmpty();
+ assertThat(resolvedFromRangerAuthorizer).isEmpty();
+ }
+
@Test
public void testObjectResourceWithWildcardInMiddle() throws OMException {
final String json = "{\n" +
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org