AWS Lambda Access Denied - amazon-web-services

A brief explanation of my setup.
I have an AWS S3 bucket with access set to Not Public which is called myBucket
I have a CloudFront distribution over the myBucket
I have created a lambda function (serverless image handler)
The desired behaviour is that my images are only accessible through my CloudFront distribution (and not directly using the S3 URL), and that I should be able to call my lambda function through the CloudFront URL.
Now what happens is that I am able to get my image like this:
https://d32by75bmg47jh.cloudfront.net/portrait.jpeg
But, I am not able to get the image by calling lambda:
https://d32by75bmg47jh.cloudfront.net/fit-in/500x500/portrait.jpeg
I am getting the Access Denied error when I try to call it with lambda.
My Bucket Policy looks like this:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2FGH21TNURTU9"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myBucket/*"
}
}
In my Lambda Console have set my Lambda function to use the Execution role: lambda_basic_execution. In the IAM Console it's policy looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": "arn:aws:s3:::myBucket/*"
}
]
}
Why am I still getting the Access Denied when I try to access my image through lambda?

Related

S3 PutObject Access Denied when deploying to

I want to create an IAM user whose sole job is to deploy to AWS S3 Static Website.
I have this policy given to my DeployUser:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::www.<my-site-name>.com"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:PutBucketAcl",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::www.<my-site-name>.com/*"
}
]
}
And this is my bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::www.<my-site-name>.com/*"
}
]
}
And this is the issue I get when I deploy (I am using Github Actions for this):
upload failed: public/404.html to s3://www.<my-site-name>.com/404.html An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
In Github, I passed the access key and secret of the user to my Action. I am pretty sure it is using that user to do the transaction. When I give S3FullAccess, my user is able to do it just fine. But I want to create a user with the AWS actions it only needs.
Where can I see better logs of this IAM user's actions?
Based on the comments, the solution was to add PutObject in the backed policy for the DeployUser.

403 on S3 bucket object in browser

I've a private bucket with OAI and CloudFront. When I upload an item to the bucket I can visit it using the CloudFront URL but not via the S3 url:
My policy looks like this
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity xxx"
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::xxx/*"
}
]
}
My IAM user has the permission to upload and get from the bucket.
Now I want that my user (or my account) can visit the S3 URL (not the CloudFront URL) to access the object in the bucket without the need to make the bucket public.
How can I do this?
I tried to update the bucket policy like this but it didn't work.
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity xxx"
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::xxx/*"
},
{
"Sid": "AllowPolicyRead",
"Effect": "Allow",
"Principal": {
"AWS": "xxxxx"
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::xxx/*"
}
]
}
From the CLI my user can get and upload objects.
IAM or bucket policies give you API level access to S3. It is not possible to download S3 files without making buckets public.

What's the right way to write an amazon s3 bucket policy?

I'm trying to upload an image from a .NET webservice to an amazon s3 bucket.
By using this public policy on the bucket i can do that:
{
"Id": "Policyxxxxxxxx",
"Version": "yyyy-MM-dd",
"Statement": [
{
"Sid": "xxxxxxxxxx",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::(bucketName)/*",
"Principal": "*"
}
] }
But when i try to give access only to my user/credentials like this:
{
"Id": "Policyxxxxxxxx",
"Version": "yyyy-MM-dd",
"Statement": [
{
"Sid": "xxxxxxxxxx",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::(bucketName)/*",
"Principal": {
"AWS": [
"arn:aws:iam::(accountID):user/(userName)"
]
}
}
]
}
i get "Accces Denied".
So what im doing wrong with the policy?
If you wish to grant access to an Amazon S3 bucket to a particular IAM User, you should put the policy on the IAM User itself rather than using a bucket policy.
For example, see: Create a single IAM user to access only specific S3 bucket

AWS S3 - Access denied when getting bucket location

I have a bucket called "my-bucket" in account A and I'm trying to determine it's location from account B.
I have the following bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::11122233344:root"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Sid": "2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::11122233344:root"
},
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::my-bucket"
}
]}
I've also stumbled across this documentation which contains the same policy: https://docs.aws.amazon.com/AmazonS3/latest/dev/example-walkthroughs-managing-access-example2.html
Now using account B, I can successfully execute the command aws s3 ls s3://my-bucket, however with aws s3api get-bucket-location --bucket my-bucket I get the access denied message.
According to the documentation: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html
To use this implementation of the operation, you must be the bucket
owner.
When in doubt always refer to the AWS API documentation it usually specifies the permission needed for the given action.

AWS Lambda Access Denied on Pre-Signed CloudFront URL

I was following the guide from https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/deployment.html to create a new Lambda Function over my CloudFront distribution. However, I have an extra requirement to only use the pre-signed URLs. The idea is that my service generates the CloudFront pre-signed URL and gives that URL to the client to access it. However, client should be able to invoke the Lambda Function on that URL.
For example the following should be possible:
Service returns the URL https://dfg565mo4z0svb.cloudfront.net/portrait.jpeg?Expires=1540724061&Signature=VLfwYdHrLM91wzFyOg0S3C6PKkKWghfOiZzt1-ew~gt0HPK~Sap0~5PHVHCEDHgHIQfwb0~oAZQ1igOOiRigzMTQ-ew~uSIR7-dsd~QJlAuceO5f2cDB2hopC5~trEgRTMnQSozPlbrFSwthveVBlZPVI3s2YapZgC7pqZB08IKIYtcXKjRfMPkxgumV5P-~Dj7rK5fdfvLyvTUTxIwrt3WLndOydBjxxUsL-6D-Hkdz8uWi6u59-sg__&Key-Pair-Id=BPKDVBLKFPWSDLIAXN8I
The client should be able to invoke Lambda like this: https://dfg565mo4z0svb.cloudfront.net/fit-in/100x100/portrait.jpeg?Expires=1540724061&Signature=VLfwYdHrLM91wzFyOg0S3C6PKkKWghfOiZzt1-ew~gt0HPK~Sap0~5PHVHCEDHgHIQfwb0~oAZQ1igOOiRigzMTQ-ew~uSIR7-dsd~QJlAuceO5f2cDB2hopC5~trEgRTMnQSozPlbrFSwthveVBlZPVI3s2YapZgC7pqZB08IKIYtcXKjRfMPkxgumV5P-~Dj7rK5fdfvLyvTUTxIwrt3WLndOydBjxxUsL-6D-Hkdz8uWi6u59-sg__&Key-Pair-Id=BPKDVBLKFPWSDLIAXN8I
where /fit-in/100x100/ is the Lambda Function.
All of that works by the default, but if I set the Restrict Viewer Access
(Use Signed URLs or Signed Cookies) option under Origin Behaviour to Yes, then suddenly any call to my Lambda Function returns the Access Denied response.
IAM Policy of the Role that my Lambda Function is using
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": "arn:aws:s3:::myBucket/*"
}
]
}
Bucket Policy
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EN2PJ6YY7V8EE"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myBucket/*"
},
{
"Sid": "2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2EM2OLBKAK85T"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myBucket/*"
}
]
}
How can I use the presigned URLs with Lambda?