403 Forbidden Error in S3 REST API HEAD Request

I'm trying to make a request for a HEAD object in the S3 REST API, but I still get a 403 Forbidden error even though I have a policy setting with the required permissions on S3. The body of the response is empty, so I don't think this is a signature issue. I tried several policy changes, nothing seemed to work. I can run objects and DELETE objects just fine, only HEAD doesn't work.

Here's my bucket policy:

{
"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/*"
    }
]
}

      

Any ideas?

Update:

As Michael pointed out, it looks like this is a problem with my signature, although Im not been able to figure out what.

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

      

The generated string looks like this:

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

      

Decision:

It seems that at some point while developing the PUT part of the file I actually broke GET and HEAD. I was passing in an empty string as the request body instead of not skipping anything, creating the mimic type required for the signature and breaking it because I didn't provide the mime type. I just removed the empty request body and it worked fine. Thank you Michael for pointing me in the wrong direction (I've spent so much time changing the bucket policy).

+3


source to share


2 answers


It could still be your signature, and I suspect it is for the following reasons:

Your observation that the body of the message is a good observation; however, this does not mean that you did it.

The absence of a response body does not give you any information about the nature of the error, in this case, since the web server should not return the body along with the response HEAD

, no matter what

The method HEAD

is identical GET

, except that the server MUST NOT

returns the message body in response

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



By checking this on my side, I have verified that the S3 response to the unsigned HEAD

request and the incorrectly signed HEAD

request is no different: it is always HTTP/1.1 403 Forbidden

without a message body.

Please note that the signed URL for is GET

not valid for HEAD

and vice versa.

In S3 Signature Version 2 and S3 Signature Version 4 "String to Sign" includes "HTTP-Verb", which will be GET

or HEAD

, which means that a signature valid for GET

, invalid for HEAD

and vice versa ... the request method must be known in time of signing, because it is an element that was used in the signing process.

The permission s3:GetObject

is the only documented permission required for use HEAD

, which seems to eliminate the permission as a problem if it GET

works, which indicates the signature as a potential problem.

+1


source


Confirmed that HEAD assigned url will receive 403 Forbidden. If custom headers are set, such as the content type of the object. The 403 response will not contain a custom header and will still receive the app / xml.



+1


source







All Articles