【问题标题】:403 forbidden error on S3 REST API HEAD requestS3 REST API HEAD 请求上的 403 禁止错误
【发布时间】:2015-02-12 16:59:53
【问题描述】:

我正在尝试向 S3 REST API 发出 HEAD Object 请求,但我不断收到 403 Forbidden 错误,即使我在 S3 上拥有具有必要权限的策略设置。响应正文是空的,所以我认为这不是签名问题。我已经尝试对政策进行多次更改,但似乎没有任何效果。我可以正常 PUT 对象和 DELETE 对象,只是 HEAD 不起作用。

这是我的存储桶政策:

{
"Statement": [
    {
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam:: 999999999999:user/User"
        },
        "Action": "s3:ListBucket",
        "Resource": "arn:aws:s3:::my-bucket"
    },
    {
        "Effect": "Allow",
        "Principal": {
            "AWS": "*"
        },
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::my-bucket/*"
    },
    {
        "Sid": "",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::999999999999:user/User"
        },
        "Action": [
            "s3:GetObject",
            "s3:GetObjectVersion",
            "s3:DeleteObject",
            "s3:PutObject"
        ],
        "Resource": "arn:aws:s3:::my-bucket/*"
    }
]
}

有什么想法吗?

更新:

正如迈克尔指出的那样,我的签名似乎有问题,尽管我看不出是什么。

def generate_url options={}
options[:action] = options[:action].to_s.upcase
options[:expires] ||= Time.now.to_i + 100
file_path = "/" + @bucket_name + "/" + options[:file_name]

string_to_sign = ""
string_to_sign += options[:action]
string_to_sign += "\n\n#{options[:mime_type]}\n"
string_to_sign += options[:expires].to_s
string_to_sign += "\n"
string_to_sign += file_path

signature = CGI::escape(
  Base64.strict_encode64(
    OpenSSL::HMAC.digest('sha1', SECRET_KEY, string_to_sign)
  )
)

url = "https://s3.amazonaws.com"
url += file_path
url += "?AWSAccessKeyId=#{ACCESS_KEY}"
url += "&Expires=#{options[:expires]}"
url += "&Signature=#{signature}"
url
end

生成的要签名的字符串如下所示:

HEAD\n\n\n1418590715\n/video-thumbnails/1234.jpg"

解决方案:

似乎在开发文件 PUT 部分时,我实际上破坏了 GET 和 HEAD。我传递了一个空字符串作为请求的主体,而不是什么都不传递,而是在签名上创建了所需的 mime 类型并破坏了它,因为我没有提供 mime 类型。我只是删除了空的请求正文,它工作得很好。感谢 Michael 为我指出了错误的方向(我浪费了很多时间来更改存储桶策略)。

【问题讨论】:

  • 那么,这个完全相同的代码适用于签署GET 请求,但不适用于同一对象的HEAD 请求?我认为“video-thumbnails”是bucket,1234.jpg是key,US-Standard(us-east-1)是bucket所在的区域?
  • 正确。我使用基于查询的身份验证,这适用于 HEAD 请求吗?

标签: rest amazon-s3 http-status-code-403


【解决方案1】:

它仍然可能是您的签名,我怀疑它是,原因如下:

您对邮件正文的观察是一个很好的观察;但是,它并不意味着您已经得出的结论。

在这种情况下,缺少响应正文根本不会为您提供任何有关错误性质的信息,因为无论如何,Web 服务器都不应该返回正文以及 HEAD 响应:

HEAD 方法与 GET 相同,只是服务器 MUST NOT 在响应中返回消息体

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html (RFC-2616)

在我这边进行测试后,我确认 S3 对未签名的 HEAD 请求和未正确签名的 HEAD 请求的响应没有什么不同:它始终是 HTTP/1.1 403 Forbidden,没有消息正文。

另外请注意,GET 的签名 URL 对 HEAD 无效,反之亦然。

在 S3 Signature Version 2 和 S3 Signature Version 4 中,“要签名的字符串”包括“HTTP 动词”,即 GETHEAD,这意味着对 GET 有效的签名将对HEAD 无效,反之亦然...请求方法必须在签名时已知,因为它是在签名过程中使用的元素。

s3:GetObject 权限是使用HEAD 所需的唯一documented 权限,如果GET 正常工作,这似乎消除了权限问题,这表明签名是潜在的问题。

【讨论】:

  • 迈克尔,感谢您指出。请查看已编辑的消息。
  • @Marcello 我看到你已经接受了这个答案。我很感激,但您发现问题了吗?
【解决方案2】:

确认 HEAD a presigned-URL 将获得 403 Forbidden。 如果设置自定义标头,例如对象的内容类型。 403 响应将不包含自定义标头,仍会获取 application/xml。

【讨论】:

    【解决方案3】:

    对上述@Michael-sqlbot 答案的补充评论...

    我面临相同的症状,但我有不同的根本原因。

    如果您尝试 HEAD 一个不存在的文件,那么这也会返回 403 禁止错误,除非您拥有 s3:ListBucket 权限。

    在我的例子中,我拥有 s3.GetObject、s3.PutObject 和 s3.HeadBucket 权限,但直到我添加了 s3.ListBucket,我才得到正确的 404 - 未找到错误。

    这里也有解释:https://aws.amazon.com/premiumsupport/knowledge-center/s3-rest-api-cloudfront-error-403/

    【讨论】:

      【解决方案4】:

      有同样的问题,但根本原因不同 - 试图创建一个存储桶,而不是得到 404,得到了 403。由于 S3 是全局命名空间的,所以其他人创建了存储桶,所以虽然我有正确的我的帐户的权限和设置,我仍然会从 HEAD 请求中获得 403。解决方法是先检查bucket是否全局存在,如果存在,换一个bucket名称。

      【讨论】:

        【解决方案5】:

        我也收到了这个错误作为一个红鲱鱼;在pytest 期间使用freezegun。我已经冻结了过去的时间,并且收到了 403 错误。所以时钟偏差可能会导致这种情况。

        我通过尝试另一个 API 调用发现了这一点,我收到了:

        E           botocore.exceptions.ClientError: An error occurred (RequestTimeTooSkewed) when calling the ListObjects operation: The difference between the request time and the current time is too large.
        

        【讨论】:

          猜你喜欢
          • 2019-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多