You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:13:13