具有完全访问策略的 Go Lambda S3 PutObject 上的 403 访问被拒绝

Gin*_*lis 5 amazon-s3 go amazon-web-services aws-lambda

我正在尝试通过 Go 中的 Lambda 将文件上传到 S3 存储桶。我可以毫无问题地从存储桶中读取对象,但Access Denied每当我尝试将对象上传到存储桶时,都会出现错误。

为了进行调试,我创建了以下简单的 Lambda 函数:

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)
}
Run Code Online (Sandbox Code Playgroud)

以下是该函数执行角色的附加策略,据我了解,该策略授予该函数将对象上传到存储桶所需的所有权限:

{
    "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>/*"
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

Lambda 报告:

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
Run Code Online (Sandbox Code Playgroud)

我正在努力找出根本原因,因为我的 Go S3 客户端配置错误或者我在 AWS 中错误地配置了权限。甚至可能是我错误地发送了对象的主体 - 这可能解释了这些unexpected EOF消息。非常感谢任何帮助,谢谢!

e:使用本地 S3 客户端(无 lambda),我能够成功地从 S3 上传和下载对象。

Gin*_*lis 4

事实证明问题出在凭据上。我正在访问的存储桶允许公共读取访问,因此我的GetObject呼叫可以正常工作。但是,它不允许公共写入访问,因此PutObject调用会导致403 Access Denied\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f 我假设我的GetObject调用已通过身份验证,但你知道他们所说的假设.. 。

\n

修复方法只是改变

\n
// upload to s3\nclient := s3.New(s3.Options{Region: "us-east-2"})\n
Run Code Online (Sandbox Code Playgroud)\n

\n
cfg, err := config.LoadDefaultConfig(context.TODO())\ncfg.Region = "us-east-2"\nclient := s3.NewFromConfig(cfg)\n
Run Code Online (Sandbox Code Playgroud)\n

感谢@jarmod 让我意识到我应该尝试使用 lambda 函数的本地默认配置,就像在 localhost 上运行时所做的那样!

\n