I have a question about writing IAM policies on AWS S3 that was partially answered here, in this nice post by Jim Scharf:
Taking Jim's post as a starting point, what I am trying to achieve is preventing a user from even knowing about the existence of other users that have access to the same bucket while using S3's console. Jim's solution, as well as others I've found, restrict a given user from accessing the contents inside another user's folder. But none of the solutions prevent a user "u" from doing what I call a "partial listing", ie., not even displaying folders whose contents are not allowed to "u".
The following post is also very similar to my question:
But unlike the setting in such post, I need to resemble a file system structure that has an "intermediate" home folder between the bucket name and the user-specific folder (just like in Jim's post):
mybucket/home/user1
mybucket/home/user2
What I've done so far is as follows:
- Created a single bucket as well as a number of "folders" inside it
- Created a number of users that I've grouped together in a group. Each user has a corresponding folder inside the bucket with the same name
Setup an IAM policy that I have attached to the group as follows:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowUsersToSeeBucketListInTheConsole", "Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"], "Effect": "Allow", "Resource": ["arn:aws:s3:::*"] }, { "Sid": "AllowRootAndHomeListingOfMyBucket", "Action": ["s3:ListBucket"], "Effect": "Allow", "Resource": ["arn:aws:s3:::mybucket"], "Condition":{"StringEquals":{"s3:prefix":["","home/"],"s3:delimiter":["/"]}} }, { "Sid": "AllowListingOfUserFolder", "Action": ["s3:ListBucket"], "Effect": "Allow", "Resource": ["arn:aws:s3:::mybucket"], "Condition":{"StringLike":{"s3:prefix":["home/${aws:username/*"]}} } ] }
I understand that the Sid "AllowRootAndHomeListingOfMyBucket" above grants permission to "ListBucket" when the prefix is "home/". Which in effect allows any user "u" in the group to list the entire set of folders "f" inside the "home" folder, regardless of whether "u" would have access to a given element of "f" or not. What I don't know is whether there is any cleverly designed "Deny" rule that would restrict even listing those folders whose contents "u" is not allowed to see.
According to Bob Kinney this was not possible back in 2013:
IAM Policy to list specific folders inside a S3 bucket for an user
However I am not sure if things have evolved in the meantime. Any suggestion is greatly appreciated.
Thank you.
No, this isn't possible, because what the policy allows is not what you can see, but rather what you can ask to see. And asking S3 to see object lists is done with prefix and delimeter.
When navigating a bucket, behind the scenes, the console asks for these things:
Click on bucket: List the root of the bucket (prefix empty string with delimiter
/
) -- returns all common prefixes ("folders") and all objects in the root up to one/
deep. (It isn't shown, but folder names actually end with/
when you create folders using the console -- that's the sole reason the console shows them as folders -- the hidden/
at the end of what is actually an ordinary empty object).Click on
home
: List all at prefixhome/
with delimiter/
-- returns all common prefixes and objects underhome/
up to one more/
-- so, this returnshome/david/
,home/emily
,home/genevieve/
,home/james/
, etc.click on
david
: List all at prefixhome/david/
with delimiter/
... you perhaps get the idea.Note how these three clicks correspond with the allowed actions in the blog post -- list the root, list home, list the user's specific directory under home.
Lacking permisson to list other users' home directories, you can see that they exist, but you can't drill dowm into them.
Reiterating... policies control what you can ask for, not what you can see. In order to navigate to your own home directory, you have to be able to list the home directories, or you can't navigate to yours. That's the fundamental reason why this can't be done with the console -- there is no policy you can write that prevents users from seeing other entries within a single level of the
/
-delimited hierarchy that they are allowed to see, because the permission is applied to the request, not the response.