Go Lambda调用S3:HeadObject返回403错误排查求助
Lambda调用S3 HeadObject返回403权限错误排查
问题背景
使用Go CDK定义了S3版本化存储桶及关联Lambda函数,调用Lambda时返回Internal Server Error,CloudWatch日志显示S3 HeadObject操作触发403权限错误,无论传入的S3对象键是否存在都会报错。已手动调整Lambda执行角色的IAM策略,但问题仍存在。
1. CDK基础设施定义(Go)
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() + "/*")}, }), )
2. Lambda处理程序代码
key := args.Body // 初始化S3客户端 cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { panic(fmt.Errorf("加载AWS配置失败: %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("获取对象%s元数据失败: %w", key, err)) } return "empty", nil
3. 调用Lambda的curl命令
curl -X POST \ 'https://REDACTED.lambda-url.us-east-1.on.aws/' \ -H 'Content-Type: application/json' \ -d 'path/to/file'
4. 错误信息
operation error S3: HeadObject, https response error StatusCode: 403
5. 当前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定义策略不一致。
问题排查与解决方案
核心问题:IAM策略中Action与Resource不匹配
AWS S3的权限模型对操作对应的资源范围有严格要求:
- 针对桶级的操作(如
s3:ListBucket)必须绑定桶ARN(arn:aws:s3:::bucket-name) - 针对对象级的操作(如
s3:GetObject、s3:HeadObject、s3:GetObjectAttributes)必须绑定对象ARN(arn:aws:s3:::bucket-name/*)
你当前的策略把对象级操作绑定到了桶ARN,桶级操作绑定到了对象ARN,导致权限实际未生效。
修正后的IAM策略
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:ListBucket" ], "Resource": "arn:aws:s3:::REDACTED_BUCKET_NAME", "Effect": "Allow" }, { "Action": [ "s3:GetObject", "s3:PutObject", "s3:GetObjectAttributes", "s3:GetObjectVersion", "s3:HeadObject" ], "Resource": "arn:aws:s3:::REDACTED_BUCKET_NAME/*", "Effect": "Allow" } ] }
- 明确添加
s3:HeadObject权限(虽然与s3:GetObject有重叠,但版本化桶中明确声明更稳妥) - 严格区分桶级/对象级操作对应的资源范围
其他可能的排查方向
- 权限边界限制:检查Lambda执行角色是否配置了权限边界,若边界未允许S3相关操作,即使策略允许也会触发403
- Bucket Policy冲突:查看S3桶自身的Bucket Policy,是否存在拒绝Lambda角色访问的语句(Bucket Policy优先级高于IAM策略)
- VPC配置问题:若Lambda部署在VPC内,需确保VPC已配置S3端点或允许出站流量访问S3公网端点,否则会因网络不通触发权限类错误
内容的提问来源于stack exchange,提问作者K. Claesson
相关产品推荐
相关产品推荐

