S3 Bucket对象删除失败:已配权限仍报403 AccessDenied
S3 Bucket对象删除AccessDenied问题排查
配置了允许删除对象的S3桶策略,但调用Go代码删除对象时返回403 AccessDenied错误,列出对象功能正常,以下是相关配置、代码及排查方向:
桶策略配置
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::frienlinkfotos/*" }, { "Effect": "Allow", "Principal": "*", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::frienlinkfotos" } ] }
Go删除对象函数
func DeletePost(c *gin.Context) { // iniciando aws service := utils.UtilAWS() svc := s3.New(service) //pegando id_usuario a partir do contexto IDUser := utils.GetUserJWT(c) uuidPost := c.PostForm("uuid_post") IDPost, err := strconv.Atoi(c.PostForm("id_post")) if err != nil { log.Println("Erro ao converter id", err) c.Status(400) return } _, err = DB.Exec(`DELETE FROM post WHERE id_post = ? AND id_usuario_pt = ? AND uuid_post = ?`, IDPost, IDUser, uuidPost) if err != nil { log.Println("Erro ao deletar post", err) c.Status(400) } else { c.Status(200) } // deletando tambem do bucket: Bucket := os.Getenv("Bucket") log.Println(Bucket) _, err = svc.DeleteObject(&s3.DeleteObjectInput{Bucket: aws.String(Bucket), Key: aws.String(uuidPost)}) if err != nil { log.Println("Erro ao deletar post do S3 bucket", err) c.JSON(400, err) } err = svc.WaitUntilObjectNotExists(&s3.HeadObjectInput{ Bucket: aws.String(Bucket), Key: aws.String(uuidPost), }) }
返回错误信息
Error when deleting post from S3 bucket AccessDenied: Access Denied status code: 403, request id: HMMCQN87, host id: GFtkmaI4hBft5Sh9U78/HIAljTcTYzW29J8hG6JavZxBMjubBvDaf5ia57e9PAd/q5I=
AWS会话工具函数
package utils import ( "log" "os" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" ) var s3Session = session.New() func UtilAWS() *session.Session { //Variaveis de login para o aws region := os.Getenv("REGION") key := os.Getenv("KEY") secretpass := os.Getenv("SECRETPASS") if region == "" || key == "" || secretpass == "" { log.Println("informações de login da AWS não pode ser nulas") } s3Config := &aws.Config{ Region: aws.String(region), Credentials: credentials.NewStaticCredentials(key, secretpass, ""), } s3Session = session.New(s3Config) return session.New(s3Config.WithRegion(region)) }
排查方向
- IAM凭证权限验证:桶策略仅控制资源端权限,需确认环境变量
KEY/SECRETPASS对应的IAM实体(用户/角色)是否具备s3:DeleteObject权限,且资源范围覆盖arn:aws:s3:::frienlinkfotos/*;同时检查是否存在IAM策略或组织SCP中的Deny语句,Deny权限会优先生效。 - 对象Key正确性:确认
uuidPost是否为S3对象的完整Key,若对象存储在子目录下,Key需包含前缀(如subfolder/uuidPost),可通过ListObjectsV2接口获取对象实际Key对比验证。 - 区域一致性检查:确认UtilAWS函数使用的环境变量
REGION与S3桶的实际区域完全一致,区域不匹配会导致请求路由错误,间接引发权限问题。 - 桶版本控制与MFA Delete:若桶开启了版本控制,
DeleteObject仅添加删除标记而非真正删除,但不会返回AccessDenied;若开启MFA Delete,则删除操作需附加MFA参数,缺失会导致403错误。 - 代码逻辑确认:检查代码中
uuidPost是否正确获取,以及DeleteObject调用是否执行到;另外,函数中数据库删除成功后返回200,但后续S3删除代码仍会执行,此逻辑不影响权限错误,但需确认参数传递无误。
内容的提问来源于stack exchange,提问作者Guilherme Rodrigues
相关产品推荐
相关产品推荐

