IAM Policy for AWS File Transfer - amazon-web-services

I am trying to setup IAM policy on S3 based for aws file transfer (SFTP) protocol. Here is the requirement:
User should be able to put files to his/her own folder is. {transfer:username}/
While uploading, lambda will add tag "allowdownload":"no" by default.
We have some third party integration to carry approvals and once approved, new tag will be added to file "allowdownload":"Yes"
Business logic complete Step_1 through 3 are working except tag based policy which I have attached to AWS File Transfer server. Policy has conditions to allow/deny get files based on tag value but it seems not working.
As per requirement: files with tag "allowdownload":"Yes" should be allowed
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::mybucket"
],
"Effect": "Allow",
"Sid": "ReadWriteS3"
},
{
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::mybucket/${transfer:UserName}/*"
],
"Effect": "Allow",
"Sid": ""
},
{
"Sid": "DenyMkdir",
"Action": [
"s3:PutObject"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::mybucket/*/"
}
]
}
Here is bucket Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/${transfer:UserName}/*",
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/allowdownload": "yes"
}
}
},
{
"Sid": "Statement1",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/${transfer:UserName}/*",
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/allowdownload": "no"
}
}
}
]
}
Also, I have block all public access is ON but still user is able to get files with allowdownload tag = no.
Anything wrong with below policy: Please advise.

Related

AWS S3 Allows reading of all objects except a specific folder

How can I allow reading of all objects except a single folder and its contents?
The rule below blocks me the whole bucket.. (can't read the bucket)
If this feature isn't possible, how can I allow reading on files at the root but deny on all subfolders?
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket"
},
{
"Sid": "ReadOnly",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Sid": "DenyOneFolder",
"Effect": "Deny",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::my-bucket/my-folder",
"arn:aws:s3:::my-bucket/my-folder/*"
]
}
]
}
My bucket strcture:
my-bucket
my-folder
object3
object1
object2
You can add an explicit Deny in your bucket policy for Listing objects that matches the prefix my-folder.
Edit: This policy will work only if the list bucket request contains the prefix.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket"
},
{
"Sid": "ReadOnly",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Sid": "DenyOneFolderRead",
"Effect": "Deny",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::my-bucket/my-folder/*"
]
},
{
"Sid": "DenyOneFolderList",
"Effect": "Deny",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket",
"Condition" : {
"StringEquals" : {
"s3:prefix": "my-folder"
}
}
}
]
}
The policy works correctly, though I would remove the Deny on arn:aws:s3:::my-bucket/my-folder because it's not useful.
I think the confusion here is that you are expecting this policy to prevent the IAM user listing and/or getting the objects under s3://my-bucket/my-folder/. It won't do that, specifically the listing part, and in fact you cannot do that. You can't control a user's ability to list the bucket at a granular level (e.g. below a specific prefix).
The policy will successfully prevent the user getting (as in downloading) objects under s3://my-bucket/my-folder/.

Granting full control permission on all sub-folders inside S3 bucket (excluding parent )

I have an S3 bucket called my-bucket... I have several sub-folders inside this bucket, let's call them: sub-folder1, sub-folder2, etc
I want my-bucket-user to have read permission to the bucket and full control permission to all of the sub-folders (so this user cannot write at the root level).
I have tried the following bucket policy, which specifically grants permission on each of the sub folders... but this policy would become too long if I have a lot of sub-folders.
{
"Id": "MyBucketPolicy",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListPermissionOnMyBucket",
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-bucket/*",
"Principal": {
"AWS": [
"arn:aws:iam::773643377756:user/my-bucket-user"
]
}
},
{
"Sid": "FullControlAccessOnSubFolder1",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-bucket/sub-folder1/*",
"Principal": {
"AWS": [
"arn:aws:iam::773643377756:user/my-bucket-user"
]
}
},
{
"Sid": "FullControlAccessOnSubFolder2",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-bucket/sub-folder2/*",
"Principal": {
"AWS": [
"arn:aws:iam::773643377756:user/my-bucket-user"
]
}
}
]
}
Is there a better way of writing this policy?
This policy permits listing the entire contents of the bucket, but only uploading/downloading to a sub-folder (not the root of the bucket):
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:ListBucket",
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-bucket"
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-bucket/*/*"
}
]
}
Basically, the expression my-bucket/*/* forces the requirement of a / in the Key of the object, meaning it is in a sub-folder.

how to write a IAM policy to give full s3 access but one directory

I am trying to give all permissions on a single s3 bucket but a single folder. I am trying to use explicit deny the folder name being Beijing path is like
buck123-test/china/Beijing/. bucket name is buck123-test.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1561641021576",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::buck123-test"
},
{
"Sid": "Stmt1561639869054",
"Action": "s3:*",
"Effect": "Deny",
"Resource": "arn:aws:s3:::buck123-test/china/Beijing"
}
]
}
how can i achieve my requirement as the above policy is not working
Your policy is missing Allow actions for objects in your bucket.
What about ? (not tested myself, let's report if this works)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1561641021576",
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::buck123-test", "arn:aws:s3:::buck123-test/*"]
},
{
"Sid": "Stmt1561639869054",
"Action": "s3:*",
"Effect": "Deny",
"Resource": "arn:aws:s3:::buck123-test/china/Beijing/*"
}
]
}
Note that you need the two resources. The bucket name only resource is required for ListBucket and other bucket level operations. The /* resource is required for object level operations like Put and Get
Revised answer, you were missing some critical pieces to the policy document, try this as it should work, but I have not tested this.
You can add additional actions if you want to allow users to GetObject, PutObject etc.
{
"Id": "Policy1561648158487",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1561648106618",
"Action": "s3:*",
"Effect": "Deny",
"Resource": "arn:aws:s3:::buck123-test/china/Beijing/*",
"Principal": "*"
},
{
"Sid": "Stmt1561648156125",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::buck123-test/*",
"Principal": "*"
}
]
}

How I can upload files to Amazon S3 without listing bucket

I am uploading files to S3 using Angular front-end with S3 Bucket policy as:
{
"Id": "Policy1499245520254",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1499245493674",
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::test-dev/*",
"arn:aws:s3:::test-dev"],
"Principal": "*"
}
]
}
But if I change the above policy to
{
"Id": "Policy1499245520254",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1499245493674",
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::test-dev/*",
"arn:aws:s3:::test-dev"],
"Principal": "*"
},
{
"Sid": "Stmt1499245517941",
"Action": [
"s3:ListBucket"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::test-dev",
"Principal": "*"
}
]
}
Where I added:
{
"Sid": "Stmt1499245517944",
"Action": [
"s3:ListBucket"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::test-dev",
"Principal": "*"
}
adding bucket list deny, the upload fails. Any way how I can upload files without listing bucket.
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:GetObjectACL",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectTagging",
"s3:PutObjectVersionAcl",
"s3:PutObjectVersionTagging"
],
"Resource": [
"arn:aws:s3:::test-dev",
"arn:aws:s3:::test-dev/*"
]
}
]
}
I solved it by just allowing these permissions, apparently bucket list is not needed in this and solves the problem.
That's because the s3:ListBucket actions covers the GET Bucket (List Objects) and HEAD Bucket operations. The HEAD Bucket operation determines if the bucket exists and you have permission to access it, which seems to be called before any action on objects (such as the s3:PutObject action). See Specifying Permissions in a Policy.

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.