英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论