S3: 当从 Go Lambda 调用 HeadObject 时,返回 403 响应。

huangapple go评论95阅读模式
英文:

S3:HeadObject returns 403 response when invoked from Go lambda

问题

我正在使用Go CDK来定义以下基础设施:

bucket := awss3.NewBucket(stack, aws.String("REDACTED"), &awss3.BucketProps{
	AccessControl:    awss3.BucketAccessControl_PRIVATE,
	PublicReadAccess: aws.Bool(false),
	RemovalPolicy:    awscdk.RemovalPolicy_DESTROY,
	Versioned:        aws.Bool(true),
})

getFileStatsLambda := awslambda.NewFunction(stack, aws.String("GetFileStatsLambda"), &awslambda.FunctionProps{
	Runtime: awslambda.Runtime_GO_1_X(),
	Code:    awslambda.Code_FromAsset(lambdaPath("get_file_stats"), &awss3assets.AssetOptions{}),
	Handler: aws.String("main"),
})
getFileStatsLambda.AddToRolePolicy(
	awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{
		Actions:   &[]*string{aws.String("s3:ListBucket")},
		Resources: &[]*string{bucket.BucketArn()},
	}),
)
getFileStatsLambda.AddToRolePolicy(
	awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{
		Actions: &[]*string{
			aws.String("s3:ListBucket"),
			aws.String("s3:GetObject"),
			aws.String("s3:PutObject"),
			aws.String("s3:GetObjectAttributes"),
		},
		Resources: &[]*string{aws.String(*bucket.BucketArn() + "/*")},
	}),
)

"GetFileStatsLambda"的处理程序定义如下:

key := args.Body

// 实例化S3客户端。
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
	panic(fmt.Errorf("failed to load aws config: %w", err))
}
s3Client := s3.NewFromConfig(cfg)

// 获取对象统计信息。
headObjectOutput, err := s3Client.HeadObject(ctx, &s3.HeadObjectInput{
	Bucket: aws.String("REDACTED_BUCKET_NAME"),
	Key:    aws.String(key),
})
if err != nil {
	panic(fmt.Errorf("failed to get object stats for key %s: %w", key, err))
}

return "empty", nil

当我使用以下curl命令调用lambda时,我得到一个"Internal Server Error":

curl -X POST \
    'https://REDACTED.lambda-url.us-east-1.on.aws/' \
    -H 'Content-Type: application/json' \
    -d 'path/to/file'

从CloudWatch中查看,我可以看到错误是:

operation error S3: HeadObject, https response error StatusCode: 403

无论使用lambda调用的S3键是否存在,都会发生此错误。

通过谷歌搜索此错误,可以找到将错误归因于缺少以下权限之一的来源:

  • s3:ListBucket
  • s3:GetObject
  • s3:PutObject
  • s3:GetObjectAttributes

但是,我已经在lambda使用的IAM角色的策略中授予了这些权限。在撰写本文时,我的策略如下所示:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:GetObjectAttributes",
                "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::REDACTED_BUCKET_NAME",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:GetObjectAttributes",
                "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::REDACTED_BUCKET_NAME/*",
            "Effect": "Allow"
        }
    ]
}

请注意,上述策略与CDK中定义的策略不同,因为我手动编辑它以减少限制,自上次运行CDK部署以来。

有人知道为什么我的lambda会收到403错误吗?

英文:

I am using the Go CDK to define the following infrastrucutre:

bucket := awss3.NewBucket(stack, aws.String("REDACTED"), &awss3.BucketProps{
	AccessControl:    awss3.BucketAccessControl_PRIVATE,
	PublicReadAccess: aws.Bool(false),
	RemovalPolicy:    awscdk.RemovalPolicy_DESTROY,
	Versioned:        aws.Bool(true),
})

getFileStatsLambda := awslambda.NewFunction(stack, aws.String("GetFileStatsLambda"), &awslambda.FunctionProps{
	Runtime: awslambda.Runtime_GO_1_X(),
	Code:    awslambda.Code_FromAsset(lambdaPath("get_file_stats"), &awss3assets.AssetOptions{}),
	Handler: aws.String("main"),
})
getFileStatsLambda.AddToRolePolicy(
	awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{
		Actions:   &[]*string{aws.String("s3:ListBucket")},
		Resources: &[]*string{bucket.BucketArn()},
	}),
)
getFileStatsLambda.AddToRolePolicy(
	awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{
		Actions: &[]*string{
			aws.String("s3:ListBucket"),
			aws.String("s3:GetObject"),
			aws.String("s3:PutObject"),
			aws.String("s3:GetObjectAttributes"),
		},
		Resources: &[]*string{aws.String(*bucket.BucketArn() + "/*")},
	}),
)

The handler of the "GetFileStatsLambda" is defined as follows:

key := args.Body
// Instantiate S3 client.
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
panic(fmt.Errorf("failed to load aws config: %w", err))
}
s3Client := s3.NewFromConfig(cfg)
// Get object stats.
headObjectOutput, err := s3Client.HeadObject(ctx, &s3.HeadObjectInput{
Bucket: aws.String("REDACTED_BUCKET_NAME"),
Key:    aws.String(key),
})
if err != nil {
panic(fmt.Errorf("failed to get object stats for key %s: %w", key, err))
}
return "empty", nil

When I invoke the lambda with the below curl command, I get a "Internal Server Error"

curl -X POST \
    'https://REDACTED.lambda-url.us-east-1.on.aws/' \
    -H 'Content-Type: application/json' \
    -d 'path/to/file'

From looking in CloudWatch, I can see that the error is:

operation error S3: HeadObject, https response error StatusCode: 403

This error happens regardless of whether the S3 key with which the lambda is invoked exists or not.

Googling this error, yields sources that attribute the error to not having one of the following permissions:

  • s3:ListBucket
  • s3:GetObject
  • s3:PutObject
  • s3:GetObjectAttributes

but I do already grant these in the policy used by the IAM role used by the lambda. At the moment of writing this, my policy looks like this:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:GetObjectAttributes",
                "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::REDACTED_BUCKET_NAME",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:GetObjectAttributes",
                "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::REDACTED_BUCKET_NAME/*",
            "Effect": "Allow"
        }
    ]
}

Note that the above policy is different from the policy defined in the CDK because I have manually edit it to be less restrictive since I last ran a CDK deploy.

Does anyone have any idea why my lambda is getting a 403 error?

答案1

得分: 1

问题是我在lambda操作的存储桶名称上硬编码了。我通过将正确的存储桶名称注入到构建lambda之前的CDK程序中来解决了这个问题。我通过将我的存储桶名称放入环境变量中,并让lambda从那里读取它来解决了这个问题。

英文:

The issue was that I had hardcoded the bucket name on which the lambda operates. <strike>I solved it by changing by CDK program to inject the correct bucket name into the lambda before building it.</strike> I solved it by putting my bucket name into an environment variable and having my lambda read it from there.

huangapple
  • 本文由 发表于 2022年8月25日 04:42:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/73479250.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定