Question on Upload to S3 using cURL and predefined URL - amazon-web-services

I am looking for some assistance on uploading a zip file from an EC2 instance to an S3 bucket using a pre-signed URL. So far, I have a python lambda that creates an S3 bucket and generates a presigned URL (with bucket name and filename), I as well have assigned a custom policy to the bucket after creation (below) for perms to upload. When I SSH to the box and run "curl -X PUT -T filename -L 'PRESIGNED URL'" I am still getting an "Access Denied" error message. Any ideas would be greatly appreciated!
​
Lambda Code to generate presigned URL:
s3_url = s3client.generate_presigned_url('put_object', Params = {
'Bucket': new_s3_label,
'Key': filename
}, ExpiresIn=600)
​
Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PolicyForAllowUploadWithACL",
"Effect": "Allow",
"Principal": {
"AWS": "ACCOUNTID"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::BUCKETNAME/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}

The problem appears to be your CURL command doesn't have the s3:x-amz-acl request header to meet the policy condition.
A better way to upload from an EC2 to an S3 bucket is directly without Pre-Signed URLs.
IAM is much better security than pre-signed URLs, anytime you can do opt for IAM and least privilege principal.
When you spin up an EC2 you provide an IAM Role. It's this role that gives the EC2 permission to talk to other services, such as S3. You should add S3 write permissions into your AWS EC2s' IAM role. You can add the following IAM policy to the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "UploadToS3",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
Other permissions may be required such as KMS permissions if your bucket uses default KMS encryption.

Related

Accessing a S3 bucket through client code is denied

I am trying to access and modify my s3 bucket through my web client. To do so, I've created a bucket and modified it in a way that it would allow public access.
My bucket policy:
{
"Version": "2012-10-17",
"Id": "Policy1646559824301",
"Statement": [
{
"Sid": "Stmt1646559821897",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::airsoftarmory-user-inventory/*"
}
]}
My CORS setting:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"PUT",
"HEAD",
"GET"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}]
ACL is enabled and looks like this:
For uploading an image to bucket, I created a new IAM user and a specific policy for putObject as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::airsoftarmory-user-inventory/*"
}
]
}
Used access keys of this user with policy attached inside my code.
The problem is, I am getting access denied response while both uploading and downloading. Can someone help me, what am I missing?
For me to troubleshoot this problem.
I will check if aws has been configured properly. You could follow this guide, and could try aws sts get-caller-identity to check if credentials works properly.
The IAM role for the user is only given for PutObject, so this will not allow user to be able get any object out from the bucket. Try adding more permission to this user such as GetObject permission. This will give the user authority to pull out data from the bucket.
The bucket policy at the bucket only allow for GetObject and does not allow for any PutObject. Again try adding the PutObject action to the bucket policy. This might also be the problem facing now of not able to upload object to the bucket.
If you are confused with IAM and bucket policy. Try reading these blogs:
https://aws.amazon.com/blogs/security/iam-policies-and-bucket-policies-and-acls-oh-my-controlling-access-to-s3-resources/
https://binaryguy.tech/aws/s3/iam-policies-vs-s3-policies-vs-s3-bucket-acls/
Hope this helps!

Uploading to AWS S3 bucket from a profile in a different environment

I have access to one of two AWS environments and I've created a protected S3 bucket in it to upload files to from an account in the one that I do not. The environment and the account that I don't have access to are what a project's CI uses.
environment I have access to: env1
environment I do not have access to: env2
account I do not have access to: user/ci
bucket name: content
S3 bucket policy:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
...
},
{
"Sid": "Allow access to bucket from profile in env1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:user/ci"
},
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket*"
],
"Resource": "arn:aws:s3:::content"
},
{
"Sid": "Allow access to bucket items from profile in env1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:user/ci"
},
"Action": [
"s3:Get*",
"s3:PutObject",
"s3:ListMultipartUploadParts"
],
"Resource": [
"arn:aws:s3:::content",
"arn:aws:s3:::content/*"
]
}
]
}
From inside a container that's configured for env1 and user/ci I'm testing with the command
aws s3 sync content/ s3://content/
and I get the error:
fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
I have two questions:
Am I even using the correct aws command to upload the data to the bucket?
Am I missing something from my bucket policy?
For the latter, I've basically followed what a load of examples and answers online have suggested.
To test your policy, I did the following:
Created an IAM User with no policies
Created an Amazon S3 bucket
Attached your Bucket Policy to the bucket, and updated the ARN and bucket name
Tested access to the bucket with:
aws s3 ls s3://bucketname
aws s3 sync folder/ s3://bucketname/folder/
It worked fine.
Therefore, the policy you display appears to be giving all necessary permissions. It is possible that you have something else that is Denying access on the bucket.
The solution was to given the ACL
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::content",
"arn:aws:s3:::content/*"
]
}
]
}
to user/ci in env1.

AWS: Could not able to give s3 access via s3 bucket policy

I am the root user of my account and i created one new user and trying to give access to s3 via s3 bucket policy:
Here is my policy details :-
{  "Id": "Policy1542998309644",  "Version": "2012-10-17",  "Statement": [    {      "Sid": "Stmt1542998308012",      "Action": [        "s3:ListBucket"      ],      "Effect": "Allow",      "Resource": "arn:aws:s3:::aws-bucket-demo-1",      "Principal": {        "AWS": [          "arn:aws:iam::213171387512:user/Dave"        ]      }    }  ]}
in IAM i have not given any access to the new user. I want to provide him access to s3 via s3 bucket policy. Actually i would like to achieve this : https://aws.amazon.com/premiumsupport/knowledge-center/s3-console-access-certain-bucket/ But not from IAM , I want to use only s3 bucket policy.
Based on the following AWS blog post (the blog shows IAM policy, but it can be adapted to a bucket policy):
How can I grant a user Amazon S3 console access to only a certain bucket?
you can make the following bucket policy:
{
"Id": "Policy1589632516440",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1589632482887",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::aws-bucket-demo-1",
"Principal": {
"AWS": [
"arn:aws:iam::213171387512:user/Dave"
]
}
},
{
"Sid": "Stmt1589632515136",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::aws-bucket-demo-1/*",
"Principal": {
"AWS": [
"arn:aws:iam::213171387512:user/Dave"
]
}
}
]
}
This will require user to url directly to the bucket:
https://s3.console.aws.amazon.com/s3/buckets/aws-bucket-demo-1/
The reason is that the user does not have permissions to list all buckets available. Thus he/she has to go directly to the one you specify.
Obviously the IAM user needs to have AWS Management Console access enabled when you create him/her in the IAM service. With Programmatic access only, IAM users can't use console and no bucket policy can change that.
You will need to use ListBuckets.
It seems like you want this user to only be able to see your bucket but not access anything in it.

How can I allow cognito users to access their own S3 folders

What I want is to let groups (families) of aws cognito users to read/write to S3 buckets which should be only available for those families of users.
I created a user with boto3 python library. Now I need to grant this user access to their folder in the bucket.
I found a few posts which suggested to create bucket policy like this:
policy = {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Grant user access to his folder",
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::BUCKET/users/${cognito-identity.amazonaws.com:sub}",
"Condition": {
"StringLike": {
"cognito-identity.amazonaws.com:sub": [
"us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx",
"us-east-1:yyyyyyyy-xxxx-xxxx-xxxx-xxxxxxxxxx"
]
}
}
}
]}
But it turns out we can not specify "cognito-identity.amazonaws.com:sub" in bucket's policy condition.
Any help is highly appreciated.
I think the policy you have above needs to be in the IAM role for an authenticated user, not part of a bucket policy.

S3 Static Webpage Access Denied Error for ACL policy

I have a webpage hosted in S3 which is to be accessed only by specific users within the account. For testing purpose, I added below bucket policy which has my iam arn specified in the Principal but I'm getting access denied error when trying to access the page (which is in that bucket) via S3 url https://s3.amazonaws.com/..... despite being signed in.
Can you please let me know what i'm doing wrong here.
Bucket Policy:
{
"Version": "2012-10-17",
"Id": "Policy1484430450679",
"Statement": [
{
"Sid": "Stmt1484430445422",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123:user/testuser"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::testbucket/*"
}
]}
If I give Principal as '*', then the webpage is accessible via S3 url.