From b6a0bde16bf8b1efbd3c30226be6e6deedd7262f Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Tue, 2 Jun 2026 18:41:10 -0700 Subject: [PATCH] test(s3/iam): scope ListBucket isolation via s3:prefix condition (#9805) The username-isolation policy denied s3:ListBucket through an object-path NotResource. ListBucket is bucket-level, so its resource ARN is the bucket and never matches an object path: the Deny always fired and a user could not list their own prefix. Scope the per-user List deny with a StringNotLike s3:prefix condition instead, the same mechanism the matching Allow uses. --- test/s3/iam/s3_policy_variables_test.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/s3/iam/s3_policy_variables_test.go b/test/s3/iam/s3_policy_variables_test.go index 581bdf82e..666575249 100644 --- a/test/s3/iam/s3_policy_variables_test.go +++ b/test/s3/iam/s3_policy_variables_test.go @@ -210,10 +210,21 @@ func TestS3PolicyVariablesUsernameIsolation(t *testing.T) { "Sid": "DenyOtherFolders", "Effect": "Deny", "Principal": "*", - "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"], + "Action": ["s3:GetObject", "s3:PutObject"], "NotResource": "arn:aws:s3:::%s/${aws:username}/*" + }, { + "Sid": "DenyListOtherPrefixes", + "Effect": "Deny", + "Principal": "*", + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::%s", + "Condition": { + "StringNotLike": { + "s3:prefix": ["${aws:username}/*", "${aws:username}"] + } + } }] - }`, bucketName, bucketName, bucketName) + }`, bucketName, bucketName, bucketName, bucketName) _, err = adminClient.PutBucketPolicy(&s3.PutBucketPolicyInput{ Bucket: aws.String(bucketName),