403 запрещенная ошибка в запросе головы REST API S3
Я пытаюсь сделать запрос объекта HEAD к API REST S3, но я продолжаю получать ошибку 403 Forbidden, хотя у меня есть настройка политики с необходимыми разрешениями на S3. Тело ответа пустое, поэтому я не думаю, что это проблема подписи. Я попробовал несколько изменений в политике, но ничего не помогает. Я могу ставить объекты и удалять объекты нормально, просто голова не работает.
Вот моя политика ведра:
{
"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 += "nn#{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
Сгенерированная строка для подписи выглядит следующим образом:
HEADnnn1418590715n/video-thumbnails/1234.jpg"
Решение:
Похоже, в какой-то момент при разработке файла PUT part я на самом деле сломал GET и HEAD. Я передавал пустую строку в качестве тела запроса, вместо того, чтобы передавать ничего, делая MIME-тип необходимым для подписи и нарушая его, потому что я был нет тип MIME. Я просто удалил пустое тело запроса, и оно сработало идеально. Спасибо Майклу за то, что он указал мне неправильное направление(я потратил столько времени на изменение политики ведра).
2 ответа:
Это все еще может быть ваша подпись, и я подозреваю, что это так, по следующим причинам:
Ваше замечание о том, что тело сообщения-это хорошее наблюдение; однако оно не означает того, что вы заключили, что оно означает.Отсутствие тела ответа не дает вам никакой информации о природе ошибки, в данном случае, потому что веб-сервер не должен возвращать тело вместе с ответом
HEAD
, независимо от того, что:Проверяя это на своей стороне, я подтвердил, что ответ S3 на неподписанный запросМетод
HEAD
является идентичноGET
за исключением того, что серверMUST NOT
возвращает тело сообщения в ответе- http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html (RFC-2616)
HEAD
и на неправильно подписанный запросHEAD
ничем не отличается: он всегдаHTTP/1.1 403 Forbidden
без тела сообщения.Обратите также внимание, что подписанный URL для
GET
недопустим дляHEAD
, и наоборот наоборот.Как в S3 Signature Version 2, так и в S3 Signature Version 4, "строка для подписи" включает "http-глагол", который будет
GET
илиHEAD
, что означает, что подпись, которая действительна дляGET
, не будет действительна дляHEAD
, и наоборот... метод запроса должен быть известен во время подписания, потому что это элемент, который используется в процессе подписания.Разрешение
s3:GetObject
является единственным документированным разрешением, необходимым для использованияHEAD
, который, по-видимому, устраняет разрешения как проблему, еслиGET
работает, что указывает на подпись как потенциальную проблему.