How to match S3 bucket name suffix against usename prefix - amazon-web-services

I want to setup a policy inside AWS IAM service to allow users following specific pattern to connect to S3 buckets which names are following the specific pattern.
My users looks like archiver_clientname, my buckets look like clientname_archive. So far I read through this and this
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "arn:aws:s3:::*"
"Condition": {"StringLike": {"${s3:prefix}": ["${aws:username:suffix}/*"]}}
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::EXAMPLE-BUCKET-NAME"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::EXAMPLE-BUCKET-NAME/*"
}
]
}
${s3:prefix} and ${aws:username:suffix} are some variables which I made up, well ${s3:prefix} actually exists but I'm not sure if that does what I expect it to be doing. It would be great to be able to match my bucket names against my user names without renaming them because otherwise names will not be speaking and be just client-names, though I have other buckets with different purposes. It will be Ok to swap user prefix and suffix or use different separator though. And looks like the policy tool has enough flexibility to solve my task I just can't find the right documentation somehow.
I also do not want to setup a new policy for each user.
I will be happy with the answer that my approach is wrong with a good explanation why it is wrong and what I can do instead.

First off, when a user gets the list of buckets, it's not possible to limit the list that is returned to the user. So, don't put a condition on the "s3:ListAllMyBuckets" action. Either they see all the buckets, or they see none.
Next, you cannot "split apart" the username. The IAM policy language isn't that sophisticated. If your username is "archiver_username", then you should be able to match it to a bucket "archiver_username_archive" by using the `${aws:username} variable in the resource:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::${aws:username}_archive"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::${aws:username}_archive/*"
}
]
}
But the language does not permit you to match a bucket called "username_archive".

Related

AWS S3 Permissios - Create Folder while only being able to upload certain extensions

I'm trying to write an IAM policy to do the following:
Allow user to access a specific bucket
Only be able to upload a selected few types of files.. based on extensions
Allow to create a folder in that bucket
I've managed to do the first two, but I'm unable to get the third requirement to work.
This is what I've tried:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucketxxx"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::bucketxxx/*.mp4",
"arn:aws:s3:::bucketxxx/*.pdf",
"arn:aws:s3:::bucketxxx/*.jpg",
"arn:aws:s3:::bucketxxx/*.png",
"arn:aws:s3:::bucketxxx/*.xlsx",
"arn:aws:s3:::bucketxxx/*.csv"
]
}
]
}
You might add "arn:aws:s3:::bucketxxx/*/", to your list of resources. As #marcin mentions, "folders" are just 0-byte objects whose name happens to end in a trailing slash.

How to restrict user to view only specific buckets

I have a set of users: user1 and user2. Ideally they should have access to read and write in their own buckets.
I want to give them console access so they can login and upload the data in S3 through drag and drop.
So I want to the ability of one user to view buckets of other users.
I am using the following IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:ListBucketMultipartUploads"
],
"Resource": "arn:aws:s3:::user1_bucket",
"Condition": {}
},
{
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl"
],
"Resource": "arn:aws:s3:::user1_bucket/*",
"Condition": {}
}
]
}
But it does not show any bucket for the user. All the user can see is Access Denied .
I tried to add principal in the policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::9xxxxxxxxxx:user/user1"},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::user1_bucket"
]
}
]
}
This gives an error.
This policy contains the following error: Has prohibited field Principal For more information about the IAM policy grammar, see AWS IAM Policies
What can I do ?
There are two ways you can do this.
Bucket policies: You select who can access and control said bucket, by attaching a policy. Example for your case:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "bucketAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AWS-account-ID:user/user-name"
},
"Action": [
"s3:GetObject",
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObjectAcl",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl"
],
"Resource": [
"arn:aws:s3:::examplebucket/*"
]
}
]
}
Source: Bucket Policy Examples - Amazon Simple Storage Service
Or you can give access through role policies, which I think is better. You almost had it, but you messed up at the end. Your policy should look something like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::examplebucket"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::examplebucket/"
}
]
}
Source: User Policy Examples - Amazon Simple Storage Service
I hope this helps.
It appears that your requirement is:
Users should be able to use the Amazon S3 management console to access (view, upload, download) their own S3 bucket
They should not be able to view the names of other buckets, nor access those buckets
With listing buckets
The first requirement can be met with a policy like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccessThisBucket",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
},
{
"Sid": "ListAllBucketForS3Console",
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "arn:aws:s3:::*"
}
]
}
This allow them to access their specific bucket, but it also allows them to list all bucket names. This is a requirement of the Amazon S3 management console, since the first thing it does is list all of the buckets.
Without listing buckets
However, since you do not want to give these users the ability to list the names of all buckets, you could use a policy like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}
This gives them full access to their own bucket, but they cannot list the names of other buckets.
To use this in the management console, they will need to jump directly to their bucket using a URL like this:
https://console.aws.amazon.com/s3/buckets/my-bucket
This will then allow them to access and use their bucket.
They will also be able to use AWS Command-Line Interface (CLI) commands like:
aws s3 ls s3://my-bucket
aws s3 cp foo.txt s3://my-bucket/foo.txt
Bottom line: To use the management console without permission to list all buckets, they will need to use a URL that jumps straight to their bucket.

S3 Bucket action doesn't apply to any resources

I'm following the instructions from this answer to generate the follow S3 bucket policy:
{
"Id": "Policy1495981680273",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1495981517155",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::surplace-audio",
"Principal": "*"
}
]
}
I get back the following error:
Action does not apply to any resource(s) in statement
What am I missing from my policy?
From IAM docs, http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Action
Some services do not let you specify actions for individual resources; instead, any actions that you list in the Action or NotAction element apply to all resources in that service. In these cases, you use the wildcard * in the Resource element.
With this information, resource should have a value like below:
"Resource": "arn:aws:s3:::surplace-audio/*"
Just removing the s3:ListBucket permission wasn't really a good enough solution for me, and probably isn't for many others.
If you want the s3:ListBucket permission, you need to just have the plain arn of the bucket (without the /* at the end) as this permission applies to the bucket itself and not items within the bucket.
As shown below, you have to have the s3:ListBucket permission as a separate statement from the permissions pertaining to items within the bucket like s3:GetObject and s3:PutObject:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Principal": {
"AWS": "[IAM ARN HERE]"
},
"Resource": "arn:aws:s3:::my-bucket-name"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Principal": {
"AWS": "[IAM ARN HERE]"
},
"Resource": "arn:aws:s3:::my-bucket-name/*"
}
]
}
Error Action does not apply to any resource(s) in statement
Simply it means that the action (you wrote in policy) doesn't apply to the resource. I was trying to make public my bucket so that anybody can download from my bucket. I was getting error until I remove ( "s3:ListBucket") from my statement.
{
"Id": "Policyxxxx961",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmtxxxxx4365",
"Action": [
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket-name/*",
"Principal": "*"
}
]
}
Because list bucket doesn't apply inside the bucket, thus by deleting this action policy worked fine.
Just ran into this issue and found a shorter solution for those that want to have ListBucket and GetObject in the same policy. The important thing is to list both the bucket-name and bucket-name/* under Resource.
{
"Id": "Policyxxxx961",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmtxxxxx4365",
"Action": [
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::bucket-name",
"arn:aws:s3:::bucket-name/*"
],
"Principal": "*"
}
]
}
To fix this issue, what you need to do in policy rule, locate the Resource, and add your arn bucket in array, one with * and the second on without * at the end. This will fix the error.
{
"Version": "2012-10-17",
"Id": "Policy3783783783738",
"Statement": [
{
"Sid": "Stmt1615891730703",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::76367367633:user/magazine-demo-root-user"
},
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetBucketLocation",
"s3:DeleteObject",
"s3:AbortMultipartUpload",
"s3:Get*",
"s3:Put*"
],
"Resource": [
"arn:aws:s3:::magazine-demo",
"arn:aws:s3:::magazine-demo/*"
]
}
]
}
Just do one change in json policy resource.
"Resource": ["arn:aws:s3:::bucket-name/*"]
Note : Add /* after bucket-name
Ref Docs :
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html
I have also faced the similar issue while creating the bucket
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mrt9949"
]
}
]
}
I have changed the above code to
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mrt9949/*"
]
}
]
}
add /* to your bucket name it will solve the issue
Here my bucket name is mrt9949
In my case the solution to this error was trying to remove some of Actions that I was applying. Some of them are not relevant to, or cannot work with this resource.
In this case it wouldn't let me include these:
GetBucketAcl
ListBucket
ListBucketMultipartUploads
Whenever you are trying to apply use bucket policies. Remember this thing, If you are using actions like "s3:ListBucket", "s3:GetBucketPolicy", "s3:GetBucketAcl" etc. which are related to bucket, the resource attribute in policy should be mentioned as <"Resource": "arn:aws:s3:::bucket_name">.
Ex.
{
"Version": "2012-10-17",
"Id": "Policy1608224885249",
"Statement": [
{
"Sid": "Stmt1608226298927",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetBucketPolicy",
"s3:GetBucketAcl",
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::bucket_name"
}
]
}
If you are using actions like "s3:GetObject", "s3:DeleteObject", "s3:GetObject" etc. which are related to object, the resource attribute in policy should be mentioned as <"Resource": "arn:aws:s3:::bucket_name/*">.
ex.
{
"Id": "Policy1608228066771",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1608228057071",
"Action": [
"s3:DeleteObject",
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket_name/*",
"Principal": "*"
}
]
}
Finally if you are using actions like "s3:ListBucket", "s3:GetObject" etc. these actions are related to both bucket and object then the resource attribute in policy should be mentioned as <"Resource": ["arn:aws:s3:::bucket_name/*", "Resource": "arn:aws:s3:::bucket_name">.
ex.
{
"Version": "2012-10-17",
"Id": "Policy1608224885249",
"Statement": [
{
"Sid": "Stmt1608226298927",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::bucket_name",
"arn:aws:s3:::bucket_name/*"
]
}
] }
Go to Amazon S3 in your instance.
Go to Permissions -> Public Access tab.
Select Edit and uncheck Block all public access and save.
You will see 'Public' tag in Permission tab and Access Control List.
You might have several policy statements and this error is a very generic one. Best is to comment all other statements except any one (like just GetObject, or ListBuckets, Or PutObject) and execute the code and see. If it works fine, it means the ARN path is right. Else, the ARN should include the bucket name alone or a bucketname with /*.
Some resources like ListBucket accept ARN with the full name like "arn:aws:s3:::bucket_name", while GetObject or PutObject expects a /* after the bucket_name. Change the ARNs according to the service and it should work now!
You have to check the pattern of the arn defined under the Resource tag for the Policy-
"Resource": "arn:aws:s3:::s3mybucketname/*"
With the addition of "/*" at the end would help to resolve the issue if you face it even after having your Public Access Policy Unblocked for your Bucket.
From AWS > Documentation > AWS Identity and Access Management > User Guide
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_resource.html
It is clearly defined in a note, Some services do not let you specify actions for individual resources.
you use the wildcard * in the Resource element
"Resource": "arn:aws:s3:::surplace-audio/*"
You can also configure ListBuckets for each folder, like so
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSESPuts-1521238702575",
"Effect": "Allow",
"Principal": {
"Service": "ses.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::buckets.email/*",
"Condition": {
"StringEquals": {
"aws:Referer": "[red]"
}
}
},
{
"Sid": "Stmt1586754972129",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::596322993031:user/[red]"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::buckets.email",
"Condition": {
"StringEquals": {
"s3:delimiter": "/",
"s3:prefix": [
"",
"domain.co",
"domain.co/user"
]
}
}
},
{
"Sid": "Stmt1586754972129",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::596322993031:user/[red]"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::buckets.email",
"Condition": {
"StringLike": {
"s3:prefix": "domain.co/user/*"
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::596322993031:user/[red]"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::buckets.email/domain.co/user/*"
}
]
}
These rules are used together with SES to receive an email, but allows an external user to view the files that were put in the bucket by SES.
I followed the instructions from here: https://aws.amazon.com/blogs/security/writing-iam-policies-grant-access-to-user-specific-folders-in-an-amazon-s3-bucket/
Also, you must specify prefix as domain.co/user/ WITH slash at the end when using the SDK, otherwise you'll get access denied. hope it helps anyone
This is so simple just add "/*" at the end. You have given only the root directory link, but the action needs to be applied to the object.
Type,
"Resource": "arn:aws:s3:::surplace-audio/*"
I found that my ListBuckets was not working because the IAM Principle did not have ListAllMyBuckets permission.

S3 policy - public write but only authenticated read

What I am trying to do is to let (anonymous) users share files to a specified bucket. However, they should not be possible to READ the files, which are already there (and for all I care not even the ones they submitted themselves). The only account which should be able to list/get objects from the bucket should be the bucket owner.
Here is what I got so far:
{
"Version": "2012-10-17",
"Id": "PutOnlyPolicy",
"Statement": [
{
"Sid": "Allow_PublicPut",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::myputbucket/*"
},
{
"Sid": "Deny_Read",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myputbucket/*"
},
{
"Sid": "Allow_BucketOwnerRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::myAWSAccountID:root"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myputbucket/*"
}
]
}
The above Policy enables me to write files to the bucket (f.e. via the android app S3anywhere), but I can't GET the objects, not even with my authenticated account.
Do you have any hints on how I could accomplish this? Thanks!
Anonymous users are not able to read a bucket content by default. So you should have only these lines in your policy:
{
"Version": "2012-10-17",
"Id": "PutOnlyPolicy",
"Statement": [
{
"Sid": "Allow_PublicPut",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::myputbucket/*"
}
]
}
The deny statement in your policy takes precedence over everything else. The default is to deny everything that isn't specifically allowed, so you should be able to just remove the deny statement and all will work the way you want.
Policy looks good, I guess that problem into Principal, you can look how it use into documentation http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-bucket-user-policy-specifying-principal-intro.html. Probably you should use AccountNumber-WithoutHyphens

AWS: Restricting IAM User to Specific Folder in S3 Bucket

So I've been trying to define a policy to restrict a group of IAM users to a particular folder in an S3 bucket with no success. I've riffed off the policy outlined in this blog post. http://blogs.aws.amazon.com/security/post/Tx1P2T3LFXXCNB5/Writing-IAM-policies-Grant-access-to-user-specific-folders-in-an-Amazon-S3-bucke
Specifically I'm using the following:
{
"Version":"2012-10-17",
"Statement": [
{
"Sid": "AllowUserToSeeBucketListInTheConsole",
"Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::*"]
},
{
"Sid": "AllowRootAndHomeListingOfCompanyBucket",
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket"],
"Condition":{"StringEquals":{"s3:delimiter":["/"]}}
},
{
"Sid": "AllowListingOfUserFolder",
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket"],
"Condition":{"StringLike":{"s3:prefix":["myfolder"]}}
},
{
"Sid": "AllowAllS3ActionsInUserFolder",
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": ["arn:aws:s3:::mybucket/myfolder/*"]
}
]
}
Unfortunately this policy for some reason allows users to navigate not only into the specified folder but other folders present in the same bucket. How do I restrict users in such a way that they can only navigate into the specified folder?
I hope this documentation will help you out, the steps are broken down and quite simple to follow:
http://docs.aws.amazon.com/AmazonS3/latest/dev/walkthrough1.html
You can also use policy variables as well.
It lets you specify placeholders in a policy. When the policy is evaluated, the policy variables are replaced with values that come from the request itself.
For example - ${aws:username}:
Further more you can also check out this Stackoverflow question (if seem relevant):
Preventing a user from even knowing about other users (folders) on AWS S3
I've answered this before, but I'll answer again from here. It's best to create a user then add them to a group then assign the group r/w to the bucket. This is a typical example of how write the policy
{
"Statement": [
{
"Sid": "sidgoeshere",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:ListBucket",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::s3bucket",
"arn:aws:s3:::s3bucket/*"
]
}
]
}