AWS Transfer service - SFTP - deny ability to list directory is affecting ability to put file to the directory - amazon-web-services

I'm attempting to set up permissions for a user account on AWS Transfer Service with SFTP protocol. I have a use case where a user should be able to add a file to a directory but not list the files in it.
When I tweak the IAM role to deny 's3:ListBucket' for a specific subdirectory the put operation fails as well. Theoretically s3 does allow to Put object without having the ability to list the prefixes. AWS transfer service however seems to be implicitly using the list bucket operation before put. Has anyone managed to deny listing ability while still being able to upload.
IAM policy :
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:ListBucket",
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<my-bucket>"
],
"Sid": "AllowListDirectories",
"Condition": {
"StringLike": {
"s3:prefix": [
"data/partner_2/*"
]
}
}
},
{
"Sid": "DenyMkdir",
"Action": [
"s3:PutObject"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::<my-bucket>/*/"
},
{
"Sid": "DenyListFilesInSubDirectory",
"Action": [
"s3:ListBucket"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::<my-bucket>",
"Condition": {
"StringLike": {
"s3:prefix": [
"data/partner_2/data/incoming/*"
]
}
}
},
{
"Effect": "AllowReadWirteInSubDirectory",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectTagging",
"s3:PutObjectVersionAcl",
"s3:PutObjectVersionTagging"
],
"Resource": "arn:aws:s3:::<my-bucket>/data/partner_2/data/incoming/*"
},
{
"Effect": "AllowOnlyReadInADifferentDirectory",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::<my-bucket>/data/partner_2/data/outgoing/*"
}
]
}
The output from SFTP client:
sftp> cd data/incoming
sftp> ls
Couldn't read directory: Permission denied
sftp> put /Users/foo/Downloads/test.log
Uploading /Users/foo/Downloads/test.log to /data/incoming/test.log
remote open("/data/incoming/test.log"): Permission denied
sftp> get test-one.txt
Fetching /data/incoming/test-one.txt to test-one.txt
sftp> exit

Since you will have to allow the upload to your s3 bucket through SFTP, this answer doesn't quite meet your requirements. If the SFTP requirement wasn't there, you may be able to provide pre-signed urls to the client to upload files securely.
I couldn't manage to find an exact solution, however, a workaround could be allowing list+upload permission to a directory in your bucket that is specific to the client/user. Got a helpful video here to share, and corresponding medium article.
Basically, the IAM policy the user is attached to will have the following permissions to a specific folder while you block all public access to your bucket.
{
"Version": "2023-02-16",
"Statement": [
{
"Sid": "AllowListingOfUserFolder",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<my-bucket>"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"restricted-folder-user-1/*",
"restricted-folder-user-1"
]
}
}
},
{
"Sid": "HomeDirObjectAccess",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::<arn of restricted-folder-user-1>*"
}
]
}

Related

How to deny all actions to a specific folder inside S3 bucket?

Basically, this policy is for AWS Transfer Family. I need to deny all access to a specific folder inside the S3 bucket. I tried the below policy, but still I was able to list the contents of the folder. But it was denied for PUT and DELETE operations.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetBucketAcl"
],
"Resource": [
"arn:aws:s3:::${bucket_name}"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:GetObjectAcl",
"s3:GetObjectVersionTagging",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::${bucket_name}/*"
]
},
{
"Effect": "Deny",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::${bucket_name}/app/restricted",
"arn:aws:s3:::${bucket_name}/app/restricted/*"
]
}
]
}
Expected:
aws s3 ls s3://sample_bucket/app/restricted/data - Access Denied
Behaviour:
aws s3 ls s3://sample_bucket/app/restricted/data - Listing all the contents of the folder
The ListBucket operation (which lists objects within a bucket) is a bucket-level permission, so it ignores the path in the supplied Resource.
Instead, you can specify the path in a Condition parameter.
From Amazon S3 Bucket: Deny List, Read, Write to specific folder - Stack Overflow:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::${bucket_name}",
"Condition": {
"StringLike": {
"s3:prefix": "app/restricted/*"
}
}
}
]
}
This will Deny listing the contents of the bucket when the prefix is app/restricted/*. Add this statement to your existing policy, since it specifically applies to ListBucket. Keep your existing Deny statement since it applies to other operations, such as GetObject and PutObject (which do accept paths in the resource).

AWS set policy to specific S3 bucket folder

I have this policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::static.MYURL.com",
"arn:aws:s3:::static.MYURL.com/images/carousel/*"
]
}
]
}
And currently the user under that policy can List all the object inside the static.MYURL.com bucket.
How can I restrict to only see the object under static.MYURL.com/images/carousel/ ?
I just want that the user can list, delete, get and read object inside that folder
Yes, you can check out some helpful links provided by #amitd. Here is a sample policy that will hopefully meet your needs:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::static.MYURL.com",
"arn:aws:s3:::static.MYURL.com/images/carousel/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::static.MYURL.com"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"images/carousel/*"
]
}
}
}
]
}
Please refer following documents from AWS;
Grant Access to User-Specific Folders in an Amazon S3 Bucket
OR
How can I grant a user access to a specific folder in my Amazon S3 bucket?
OR
How can I use IAM policies to grant user-specific access to specific folders?
You can use AWS Policy Generator

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.

Restrict (Deny) Bucket List by IP

I have a bucket policy that works properly to restrict access to a bucket to certain IP's, but I actually want to deny listing the bucket itself or bucket(s) to only certain IP's.
I got it working with everything except the listing. I can deny listing the bucket contents, uploading, downloading, but can't deny doing a simple command like Get-S3Bucket -BucketName "bucket"
My current policy:
{
"Version": "2012-10-17",
"Id": "bucket-policy",
"Statement": [
{
"Sid": "IPDeny",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::bucketName/*",
"arn:aws:s3:::bucketName"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": ["1.2.3.4.5","6.7.8.9"]
}
}
}
]
}
The issue was specific to PowerShell Toolkit. Which I learned the Get-S3Bucket actually runs an "s3 collection" which I believe to include the following:
s3:ListBucket,
s3:ListAllMyBuckets,
s3:HeadBucket
So the issue for me wasn't the bucket policy, it was the IAM user policy.
I solved it via the user policy like follows:
{
"Sid": "listBuckets",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListAllMyBuckets",
"s3:HeadBucket"
],
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": ["1.2.3.4","5.6.7.8"]
}
}
}

Can't use sync to move objects in a folder to another folder within the same bucket using s3cmd

I have been trying to move all the objects in a folder bucketA/product/pic/ up one level within the same bucket bucketA/pic/
I can sync files between local host and the s3 server with
s3cmd sync /script/ s3://bucketA/
as well as put an object:
s3cmd put zip.sh s3://bucketA/
But I'm getting Access Denied error when syncing files within the same bucket:
[root]s3cmd sync s3://bucketA/product/pic s3://bucketA/pic/
WARNING: Empty object name on S3 found, ignoring.
Summary: 441 source files to copy, 0 files at destination to delete
ERROR: S3 error: Access Denied
Is it possible to change the locations of the objects in a folder within the same bucket?
Here's my IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt123456",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets"
],
"Resource": [
"arn:aws:s3:::*"
]
},
{
"Sid": "Stmt123457",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::bucketA",
"arn:aws:s3:::bucketA/*"
]
}
]
}
Here's my bucket policy which is set to prevent hotlinking:
{
"Version": "2012-10-17",
"Id": "HTTP referrer policy",
"Statement": [
{
"Sid": "Allow in my domains",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketA/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"https://mylocalhostip/*",
"http://mylocalhostip/*"
]
}
}
},
{
"Sid": "Deny access if referer is not my sites",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketA/*",
"Condition": {
"StringNotLike": {
"aws:Referer": [
"http://mylocalhostip/*",
"https://mylocalhostip/*"
]
}
}
}
]
}
These days, it is recommended to use the AWS Command-Line Interface (CLI).
The AWS CLI includes a sync command. See: https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html