'Go Lambda with Full Access Policy 403 Access Denied on S3 PutObject
I'm attempting to upload a file to an S3 bucket via Lambda in Go. I am able to read objects from the bucket with no issues, but I get Access Denied errors whenever I try to upload an object to the bucket.
To debug, I created the following simple Lambda function:
package main
import (
"bytes"
"context"
"log"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
func LambdaMainWrapper() {
data := []byte("this is some data stored as a byte slice in Go Lang!")
// convert byte slice to io.Reader
reader := bytes.NewReader(data)
// upload to s3
client := s3.New(s3.Options{Region: "us-east-2"})
putObjectInput := &s3.PutObjectInput{
Bucket: aws.String(<MY_BUCKET_NAME>),
Key: aws.String("test-file"),
Body: reader,
}
res, err := client.PutObject(context.Background(), putObjectInput)
if err != nil {
log.Fatal("Error uploading object to S3: ", err)
}
log.Println("[s3 res]", res)
}
func main() {
lambda.Start(LambdaMainWrapper)
}
And here is the attached policy on the execution role for the function, which to my understanding grants it all the permissions it would need to upload an object to the bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ExampleStmt",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<MY_BUCKET_NAME>/*"
]
},
{
"Sid": "ExampleStmt2",
"Action": [
"s3:PutObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<MY_BUCKET_NAME>/*"
]
},
{
"Sid": "ExampleStmt3",
"Action": [
"s3:PutObjectAcl"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<MY_BUCKET_NAME>/*"
]
}
]
}
Lambda reports back:
START RequestId: XXX Version: $LATEST
2022/01/25 16:39:06 Error uploading object to S3: operation error S3: PutObject, https response error StatusCode: 403, RequestID: XXXXXXXXXX, HostID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXX, api error AccessDenied: Access Denied
2022/01/25 16:39:06 unexpected EOF
2022/01/25 16:39:06 unexpected EOF
END RequestId: XXX
I'm struggling to root cause this as an error with my Go S3 client configuration or if I've configured permissions within AWS incorrectly. It could even be that I'm sending the Body of the object incorrectly - which might explain the unexpected EOF messages. Any help is much appreciated, thanks!
e: using local S3 client (no lambda), I was able to succesfully upload and download objects from S3.
Solution 1:[1]
Turns out the issue was credentials. The bucket I am accessing allows public read access, hence why my GetObject calls were working. However, it does not allow public write access, so PutObject calls were resulting in 403 Access Denied ???? I assumed my GetObject calls were authenticated, but you know what they say about assuming...
The fix was simply changing
// upload to s3
client := s3.New(s3.Options{Region: "us-east-2"})
to
cfg, err := config.LoadDefaultConfig(context.TODO())
cfg.Region = "us-east-2"
client := s3.NewFromConfig(cfg)
thanks @jarmod for making me realize I should attempt to use the lambda function's local default config, as one does when running on localhost !
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ginglis |
