Getting 403 forbidden from s3 when attempting to download a file - amazon-web-services

I have a bucket on s3, and a user given full access to that bucket.
I can perform an ls command and see the files in the bucket, but downloading them fails with:
A client error (403) occurred when calling the HeadObject operation: Forbidden
I also attempted this with a user granted full S3 permissions through the IAM console. Same problem.
For reference, here is the IAM policy I have:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::mybucket",
"arn:aws:s3:::mybucket/*"
]
}
]
}
I also tried adding a bucket policy, even making the bucket public, and still no go...also, from the console, I tried to set individual permissions on the files in the bucket, and got an error saying I cannot view the bucket, which is strange, since I was viewing it from the console when the message appeared, and can ls anything in the bucket.
EDIT the files in my bucket were copied there from another bucket belonging to a different account, using credentials from my account. May or may not be relevant...
2nd EDIT just tried to upload, download and copy my own files to and from this bucket from other buckets, and it works fine. The issue is specifically with the files placed there from another account's bucket.
Thanks!

I think you need to make sure that the permissions are applied to objects when moving/copying them between buckets with the "bucket-owner-full-control" acl.
Here are the details about how to do this when moving or copying files as well as retroactively:
https://aws.amazon.com/premiumsupport/knowledge-center/s3-bucket-owner-access/
Also, you can read about the various predefined grants here:
http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl

The problem here stems from how you get the files into the bucket. Specifically the credentials you have and/or privileges you grant at the time of upload. I ran into a similar permissions issue issue when I had multiple AWS accounts, even though my bucket policy was quite open (as yours is here). I had accidentally used credentials from one account (call it A1) when uploading to a bucket owned by a different account (A2). Because of this A1 kept the permissions on the object and the bucket owner did not get them. There are at least 3 possible ways to fix this in this scenario at time of upload:
Switch accounts. Run $export AWS_DEFAULT_PROFILE=A2 or, for a more permanent change, go modify ~/.aws/credentials and ~/.aws/config to move the correct credentials and configuration under [default]. Then re-upload.
Specify the other profile at time of upload: aws s3 cp foo s3://mybucket --profile A2
Open up the permissions to bucket owner (doesn't require changing profiles): aws s3 cp foo s3://mybucket --acl bucket-owner-full-control
Note that the first two ways involve having a separate AWS profile. If you want to keep two sets of account credentials available to you, this is the way to go. You can set up a profile with your keys, region etc by doing aws configure --profile Foo. See here for more info on Named Profiles.
There are also slightly more involved ways to do this retroactively (post upload) which you can read about here.

To correctly set the appropriate permissions for newly added files, add this bucket policy:
[...]
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012::user/their-user"
},
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
Your bucket policy is even more open, so that's not what's blocking you.
However, the uploader needs to set the ACL for newly created files. Python example:
import boto3
client = boto3.client('s3')
local_file_path = '/home/me/data.csv'
bucket_name = 'my-bucket'
bucket_file_path = 'exports/data.csv'
client.upload_file(
local_file_path,
bucket_name,
bucket_file_path,
ExtraArgs={'ACL':'bucket-owner-full-control'}
)
source: https://medium.com/artificial-industry/how-to-download-files-that-others-put-in-your-aws-s3-bucket-2269e20ed041 (disclaimer: written by me)

Related

AWS S3 bucket policy to external account denies access

I have created an S3 bucket which we will call mytest-bucket where I am trying to grant access to the bucket and its objects to an IAM user at a different company, not within my organization. The user, which we call Bob has given me their account ID, IAM username, and canonical ID. I've done the following to attempt to grant Bob access:
1) I have set the bucket policy for mytest-bucket as such:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::111111111111:root",
"arn:aws:iam::111111111111:user/Bob"
]
},
"Action": [
"s3:*",
"s3:ListBucket",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::mytest-bucket",
"arn:aws:s3:::mytest-bucket/*"
]
}
]
}
2) I have set my Individual Block Public Access settings for this bucket to the following:
3) I have also granted List, Write ACL permissions to the External account using the Canonical ID provided, as well as Read, Write Bucket ACL permissions. For object ownership, I have ACLs are enabled and can be used to grand access to this bucket and its objects.
Yet, still, Bob is unable to both 1) see the bucket listed under their account, 2) access any objects or the bucket itself due to Access Denied error.
Is there something I can change in the above configuration to provide Bob access to this one bucket and it's objects?
How can I help them get access?
Edit: Bob will not be uploading objects, but only reading and downloading objects from this bucket.
You say that "bob is unable to see the bucket listed under their account". This is normal -- the bucket does not belong to his account, so it will not be listed when he uses the S3 management console. However, Bob should be able to access it when using the AWS CLI, such as:
aws s3 ls s3://mytest-bucket
If Bob really wants to see it in the console, he can 'cheat' by using a URL that will show the bucket, but Bob would need to paste the URL directly rather than going through the bucket hierarchy. To demonstrate, here is a URL that would normally show a bucket:
https://us-east-1.console.aws.amazon.com/s3/buckets/mytest-bucket
You can change the bucket name at the end to 'jump' directly to a desired bucket.

Access permission denied for the objects created by someone else in my AWS S3 bucket

We have an application that writes files to an Amazon S3 bucket. I am not able to download or copy the files to different bucket. I am getting access denied error. The owner of the file is someone else but the bucket is owned by us. That person is not accessible and is not there in the organization. How do I access the files and change the access permission or change the owner of the files?
I tried copying the objects from source bucket to destination bucket but Error 403.
Here is the bucket policy:
{
"Version": "2012-10-17",
"Id": "abcd",
"Statement": [
{
"Sid": "abcd",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:user/xxx"
]
},
"Action": [
"s3:GetObject",
"s3:GetBucketLocation",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::xyz/*",
"arn:aws:s3:::xyz"
]
}
]
}
Expected: I want to move these files to different bucket or download these files. It is giving error Access denied 403.
The uploader of the files needs to grant full control over the objects to the bucket owner.
How you do this depends on which tool or SDK you are using to upload files. For example, if you are using the awscli then you would append --acl bucket-owner-full-control to the aws s3 cp command.
As an S3 bucket owner, you can require uploaders to give you full control by specifying an appropriate S3 bucket policy.
Note that giving the bucket owner full control does not make the bucket owner the owner of the objects. They are still owned by the uploader. However, if the bucket owner has full control and wants ownership, then the bucket owner can simply copy each file over itself, and that will transfer the ownership.

What is the cheapest way to transfer files from one S3 bucket to another?

I was going to straight up copy paste everything via a Commander One file manager, but turns out that's going to cost a fortune. Cuz I guess that counts as downloading and then reuploading everything. I was told to use an instance instead and transfer them that way (still trying to figure out how to do that). But are there any other simple(r) ways maybe?
trying to attach this policy to the destination bukkit:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS":"arn:aws:iam::<id number here>:user/<username here>"},
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::<bucket to get files from>/*"
]
},
{
"Effect": "Allow",
"Principal": {"AWS":"arn:aws:iam::<id number here>:user/<username here>"},
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::<bucket to put files in>"
]
}
]
}
getting policy has invalid resource error
You should use the CopyObject() command, which copies objects directly between Amazon S3 buckets with no need to download/upload. Since the buckets are in the same region, the only cost is a few API request ($0.005 per 1,000 requests).
The easiest way to do this is with the AWS Command-Line Interface (CLI), using either the aws s3 cp or aws s3 sync command. It will call CopyObject() on your behalf. For example:
aws s3 sync s3://bucket-a/folder/ s3://bucket-b/folder/
Please note that the credentials you use to perform the copy must have read permission on the source bucket and write permission on the destination bucket.
Let's say you are copying from Bucket-A in Account-A to Bucket-B in Account-B. This can be done either by:
Using credentials from an IAM User (User-B) from Account-B. Add a bucket policy on Bucket-A allowing User-B to read from the bucket, OR
Using credentials from an IAM User (User-A) from Account-A. Add a bucket policy on Bucket-A allowing User-A to write to the bucket. When copying, be sure to add --acl bucket-owner-full-control to grant object ownership to Account-B.
I prefer the first option, since the destination account is 'pulling' the files into its own account, so it owns the files by default.
The easiest way to do it is using sync, it's pretty straight forward:
aws s3 sync s3://sourcebucket s3://destinationbucket
Read more at: https://aws.amazon.com/premiumsupport/knowledge-center/copy-s3-objects-account/
You also do have to adjust the bucket policies of the source and destination bucket to allow gets & puts respectively.
As for cost, if its in the same region, it's free. You are technically not transferring data out to the internet, you are transferring it to another s3 bucket within the same region.

S3 to S3 transfer using different accounts?

I've been reading multiple posts like this one about how to transfer data with aws cli from one S3 bucket to another using different accounts but I am still unable to do so. I'm sure it's because I haven't fully grasp the concepts of account + permission settings in AWS yet (e.g. iam account vs access key).
I have a vendor that gave me a user called "Foo" and account number "123456789012" with 2 access keys to access their S3 bucket "SourceBucket" in eu-central-1. I created a profile on my machine with the access key provided by the vendor called "sourceProfile". I have my S3 called "DestinationBucket" in us-east-1 and I set the bucket policy to the following.
{
"Version": "2012-10-17",
"Id": "Policy12345678901234",
"Statement": [
{
"Sid": "Stmt1487222222222",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/Foo"
},
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::DestinationBucket/",
"arn:aws:s3:::DestinationBucket/*"
]
}
]
}
Here comes the weird part. I am able to list the files and even download files from the "DestinationBucket" using the following command lines.
aws s3 ls s3://DestinationBucket --profile sourceProfile
aws s3 cp s3://DestinationBucket/test ./ --profile sourceProfile
But when I try to put copy anything to the "DestinationBucket" using the profile, I got Access Denied error.
aws s3 cp test s3://DestinationBucket --profile sourceProfile --region us-east-1
upload failed: ./test to s3://DestinationBucket/test An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
Did I set up the bucket policy especially the list of action right? How could ls and cp from destination to local work but cp from local to destination bucket doesn't work?
Because AWS make it a way that parent account holder must do the delegation.
Actually, beside delegates access on to that particular access key user, you can choose to do replication on the bucket as stated here.

Client error (403) when downloading file from AWS S3 to local file

I uploaded several .zip files to my AWS S3 bucket a while back using the AWS CLI. Now I can't seem to download those files when using the following command:
aws s3 cp s3://mybucket/test.zip test2.zip
because it yields the following error:
A client error (403) occurred when calling the HeadObject operation: Forbidden
Completed 1 part(s) with ... file(s) remaining
How can I resolve this issue?
Edit:
Running the following command shows the existing bucket policies
aws s3api get-bucket-policy --bucket mybucket
{
"Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Example permissions\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::221234567819:root\"},\"Action\":[\"s3:ListBucket\",\"s3:GetBucketLocation\"],\"Resource\":\"arn:aws:s3:::mybucket\"},{\"Sid\":\"Examplepermissions\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::221234567819:root\"},\"Action\":[\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:PutObjectAcl\",\"s3:GetObject\",\"s3:DeleteObject\",\"s3:GetObjectAcl\",\"s3:ListMultipartUploadParts\",\"s3:PutObjectAcl\"],\"Resource\":\"arn:aws:s3:::mybucket/*\"}]}"
}
This is most likely one of three causes:
either that one of your policies is not permitting you to read the resources (yes, it's possible to have write permissions but not read permissions), or
that your client environment is no longer setup with the correct credentials.
you don't have ListBucket permission and the file is not present (it returns 403 instead of 404, as if you don't have ListBucket, you shouldn't be able to tell if a file exists or not).
For 1, S3 objects can be secured by either Bucket Policies, User Policies or ACLs and there are complex interactions between the 3. See http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-access-control.html for more details.
If you update your question with details of relevant user polices, bucket policies and ACLs I could take a look and see if anything explains the symptom.
Edit:
Reviewing the included bucket policy, it appears to be tied to the root principal. Are you using root credentials for the aws s3 cli? If you are using an IAM user, you will need to modify the Principal (See http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-bucket-user-policy-specifying-principal-intro.html)
Add "arn:aws:s3:::your-bucket-name" together with "arn:aws:s3:::your-bucket-name/*" to Recourses in your policy. Also, you may need non-obvious "s3:ListBucket" permission and maybe some other permissions.
My policy that works for downloading files in lambda function:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::XXXXX-pics",
"arn:aws:s3:::XXXXX-pics/*"
]
}
]
}
It is attached to the Lambda function role. No bucket policy attached to the bucket was needed.