Payload on 400 error for HEAD requests #624

Closed
opened 2023-08-31 17:02:09 +00:00 by earl-warren · 6 comments

When sending a HEAD /bucket/ request with an incorrect region, the 400 error returned by garage 0.8.2 setup with this script is empty.

The tcpdump output (in full below) has:

HTTP/1.1 400 Bad Request
content-type: application/xml
content-length: 252
date: Thu, 31 Aug 2023 16:56:26 GMT

Is this a misconfiguration of garage? It would be helpful to have more information to display to the Forgejo user when they set the wrong region: this is why there is a particular interest in the content of this error.

$ sudo tcpdump -A -s 0 -i lo port 9000 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes 18:56:26.595565 IP localhost.43304 > localhost.9000: Flags [S], seq 239110995, win 65495, options [mss 65495,sackOK,TS val 3833192476 ecr 0,nop,wscale 7], length 0 E..<..@.@............(#(.@.S.........0......... .y.......... 18:56:26.595579 IP localhost.9000 > localhost.43304: Flags [S.], seq 3278046014, ack 239110996, win 65483, options [mss 65495,sackOK,TS val 3833192476 ecr 3833192476,nop,wscale 7], length 0 E..<..@.@.<.........#(.(.c.>.@.T.....0......... .y...y...... 18:56:26.595588 IP localhost.43304 > localhost.9000: Flags [.], ack 1, win 512, options [nop,nop,TS val 3833192476 ecr 3833192476], length 0 E..4..@.@............(#(.@.T.c.?.....(..... .y...y.. 18:56:26.595683 IP localhost.43304 > localhost.9000: Flags [P.], seq 1:428, ack 1, win 512, options [nop,nop,TS val 3833192476 ecr 3833192476], length 427 E.....@.@............(#(.@.T.c.?........... .y...y..HEAD /bucket/ HTTP/1.1 Host: minio:9000 User-Agent: MinIO (linux; amd64) minio-go/v7.0.61 Authorization: AWS4-HMAC-SHA256 Credential=123456/20230831/badregion/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=a5c84e0c09d6c1edd623714d8e4e4f26c6676bcd0701cce3210927c568817e43 X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 X-Amz-Date: 20230831T165626Z

18:56:26.595691 IP localhost.9000 > localhost.43304: Flags [.], ack 428, win 509, options [nop,nop,TS val 3833192476 ecr 3833192476], length 0
E..4PS@.@..n........#(.(.c.?.@.......(.....
.y...y..
18:56:26.595855 IP localhost.9000 > localhost.43304: Flags [P.], seq 1:118, ack 428, win 512, options [nop,nop,TS val 3833192477 ecr 3833192476], length 117
E...PT@.@...........#(.(.c.?.@.............
.y...y..HTTP/1.1 400 Bad Request
content-type: application/xml
content-length: 252
date: Thu, 31 Aug 2023 16:56:26 GMT

18:56:26.595864 IP localhost.43304 > localhost.9000: Flags [.], ack 118, win 512, options [nop,nop,TS val 3833192477 ecr 3833192477], length 0
E..4..@.@............(#(.@...c.......(.....
.y...y..
18:56:26.596495 IP localhost.43304 > localhost.9000: Flags [F.], seq 428, ack 118, win 512, options [nop,nop,TS val 3833192477 ecr 3833192477], length 0
E..4..@.@............(#(.@...c.......(.....
.y...y..
18:56:26.596519 IP localhost.9000 > localhost.43304: Flags [F.], seq 118, ack 429, win 512, options [nop,nop,TS val 3833192477 ecr 3833192477], length 0
E..4PU@.@..l........#(.(.c...@.......(.....
.y...y..
18:56:26.596530 IP localhost.43304 > localhost.9000: Flags [.], ack 119, win 512, options [nop,nop,TS val 3833192477 ecr 3833192477], length 0
E..4..@.@............(#(.@...c.......(.....
.y...y..

When sending a `HEAD /bucket/` request with an incorrect region, the 400 error returned by [garage 0.8.2](https://codeberg.org/forgejo/forgejo/src/branch/forgejo-development/.forgejo/upgrades/test-upgrade.sh#L54) setup [with this script](https://codeberg.org/forgejo/forgejo/src/branch/forgejo-development/.forgejo/upgrades/test-upgrade.sh#L139-L182) is empty. The tcpdump output (in full below) has: ``` HTTP/1.1 400 Bad Request content-type: application/xml content-length: 252 date: Thu, 31 Aug 2023 16:56:26 GMT ``` Is this a misconfiguration of garage? It would be helpful to have more information to display to the Forgejo user when they set the wrong region: this is why there is a particular interest in the content of this error. <details> $ sudo tcpdump -A -s 0 -i lo port 9000 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes 18:56:26.595565 IP localhost.43304 > localhost.9000: Flags [S], seq 239110995, win 65495, options [mss 65495,sackOK,TS val 3833192476 ecr 0,nop,wscale 7], length 0 E..<..@.@............(#(.@.S.........0......... .y.......... 18:56:26.595579 IP localhost.9000 > localhost.43304: Flags [S.], seq 3278046014, ack 239110996, win 65483, options [mss 65495,sackOK,TS val 3833192476 ecr 3833192476,nop,wscale 7], length 0 E..<..@.@.<.........#(.(.c.>.@.T.....0......... .y...y...... 18:56:26.595588 IP localhost.43304 > localhost.9000: Flags [.], ack 1, win 512, options [nop,nop,TS val 3833192476 ecr 3833192476], length 0 E..4..@.@............(#(.@.T.c.?.....(..... .y...y.. 18:56:26.595683 IP localhost.43304 > localhost.9000: Flags [P.], seq 1:428, ack 1, win 512, options [nop,nop,TS val 3833192476 ecr 3833192476], length 427 E.....@.@............(#(.@.T.c.?........... .y...y..HEAD /bucket/ HTTP/1.1 Host: minio:9000 User-Agent: MinIO (linux; amd64) minio-go/v7.0.61 Authorization: AWS4-HMAC-SHA256 Credential=123456/20230831/badregion/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=a5c84e0c09d6c1edd623714d8e4e4f26c6676bcd0701cce3210927c568817e43 X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 X-Amz-Date: 20230831T165626Z 18:56:26.595691 IP localhost.9000 > localhost.43304: Flags [.], ack 428, win 509, options [nop,nop,TS val 3833192476 ecr 3833192476], length 0 E..4PS@.@..n........#(.(.c.?.@.......(..... .y...y.. 18:56:26.595855 IP localhost.9000 > localhost.43304: Flags [P.], seq 1:118, ack 428, win 512, options [nop,nop,TS val 3833192477 ecr 3833192476], length 117 E...PT@.@...........#(.(.c.?.@............. .y...y..HTTP/1.1 400 Bad Request content-type: application/xml content-length: 252 date: Thu, 31 Aug 2023 16:56:26 GMT 18:56:26.595864 IP localhost.43304 > localhost.9000: Flags [.], ack 118, win 512, options [nop,nop,TS val 3833192477 ecr 3833192477], length 0 E..4..@.@............(#(.@...c.......(..... .y...y.. 18:56:26.596495 IP localhost.43304 > localhost.9000: Flags [F.], seq 428, ack 118, win 512, options [nop,nop,TS val 3833192477 ecr 3833192477], length 0 E..4..@.@............(#(.@...c.......(..... .y...y.. 18:56:26.596519 IP localhost.9000 > localhost.43304: Flags [F.], seq 118, ack 429, win 512, options [nop,nop,TS val 3833192477 ecr 3833192477], length 0 E..4PU@.@..l........#(.(.c...@.......(..... .y...y.. 18:56:26.596530 IP localhost.43304 > localhost.9000: Flags [.], ack 119, win 512, options [nop,nop,TS val 3833192477 ecr 3833192477], length 0 E..4..@.@............(#(.@...c.......(..... .y...y.. </details>
Owner

New discovery : an error response to a HEAD request is not supposed to have a body

I don't think we have specific code to not send the response body if the request is a HEAD, but I wouldn't be surprised if it is the hyper http library that removes it automatically to ensure protocol conformance.

This means that the region redirection mechanism cannot work with just a head request, unfortunately... I think it is implemented in the minio client, and maybe in the minio client library, could we look at how they do it?

New discovery : [an error response to a HEAD request is not supposed to have a body](https://developer.mozilla.org/en-US/docs/web/http/methods/head) I don't think we have specific code to not send the response body if the request is a HEAD, but I wouldn't be surprised if it is the hyper http library that removes it automatically to ensure protocol conformance. This means that the region redirection mechanism cannot work with just a head request, unfortunately... I think it is implemented in the minio client, and maybe in the minio client library, could we look at how they do it?
Author

@gusted looked at it and found some information. I'll try using GET instead see where that gets me.

@gusted looked at it and [found some information](https://codeberg.org/forgejo/forgejo/issues/1344#issuecomment-1075551). I'll try using GET instead see where that gets me.
Author

Using GET the 400 payload is present, you are correct: HEAD hides it somewhere in the codepath.

GET / HTTP/1.1
Host: minio:9000
User-Agent: MinIO (linux; amd64) minio-go/v7.0.61
Authorization: AWS4-HMAC-SHA256 Credential=123456/20230831/badregion/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=a0c9454bdfc0187f76c4c58ac881c9feea7a9d539c5d6b48b5a0d8fca0621f9b
X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
X-Amz-Date: 20230831T194154Z
Accept-Encoding: gzip


21:41:54.333195 IP localhost.9000 > localhost.45112: Flags [.], ack 443, win 509, options [nop,nop,TS val 3843120214 ecr 3843120214], length 0
E..4IP@.@..q........#(.8g............(.....
..\V..\V
21:41:54.333380 IP localhost.9000 > localhost.45112: Flags [P.], seq 1:363, ack 443, win 512, options [nop,nop,TS val 3843120214 ecr 3843120214], length 362
E...IQ@.@...........#(.8g..................
..\V..\VHTTP/1.1 400 Bad Request
content-type: application/xml
content-length: 245
date: Thu, 31 Aug 2023 19:41:54 GMT

<?xml version="1.0" encoding="UTF-8"?><Error><Code>AuthorizationHeaderMalformed</Code><Message>Authorization header malformed, unexpected scope: 20230831/badregion/s3/aws4_request</Message><Resource>/</Resource><Region>us-east-1</Region></Error>
Using GET the 400 payload is present, you are correct: HEAD hides it somewhere in the codepath. ``` GET / HTTP/1.1 Host: minio:9000 User-Agent: MinIO (linux; amd64) minio-go/v7.0.61 Authorization: AWS4-HMAC-SHA256 Credential=123456/20230831/badregion/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=a0c9454bdfc0187f76c4c58ac881c9feea7a9d539c5d6b48b5a0d8fca0621f9b X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 X-Amz-Date: 20230831T194154Z Accept-Encoding: gzip 21:41:54.333195 IP localhost.9000 > localhost.45112: Flags [.], ack 443, win 509, options [nop,nop,TS val 3843120214 ecr 3843120214], length 0 E..4IP@.@..q........#(.8g............(..... ..\V..\V 21:41:54.333380 IP localhost.9000 > localhost.45112: Flags [P.], seq 1:363, ack 443, win 512, options [nop,nop,TS val 3843120214 ecr 3843120214], length 362 E...IQ@.@...........#(.8g.................. ..\V..\VHTTP/1.1 400 Bad Request content-type: application/xml content-length: 245 date: Thu, 31 Aug 2023 19:41:54 GMT <?xml version="1.0" encoding="UTF-8"?><Error><Code>AuthorizationHeaderMalformed</Code><Message>Authorization header malformed, unexpected scope: 20230831/badregion/s3/aws4_request</Message><Resource>/</Resource><Region>us-east-1</Region></Error> ```
earl-warren changed title from Payload on 400 error to Payload on 400 error for HEAD requests 2023-08-31 20:00:01 +00:00
Author

I'm not sure which way to go to resolve this. I think I'll use a GET request to indirectly assert the region is valid and display a meaningful error message if it does not, using the 400 payload.

But it feels like a hack and there should be a more idiomatic way to do that.

Thoughts?

I'm not sure which way to go to resolve this. I think I'll use a GET request to indirectly assert the region is valid and display a meaningful error message if it does not, using the 400 payload. But it feels like a hack and there should be a more idiomatic way to do that. Thoughts?
Author

https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html

This action is useful to determine if a bucket exists and you have permission to access it. The action returns a 200 OK if the bucket exists and you have permission to access it.

If the bucket does not exist or you do not have permission to access it, the HEAD request returns a generic 400 Bad Request, 403 Forbidden or 404 Not Found code. A message body is not included, so you cannot determine the exception beyond these error codes.

In any case garage behaves like AWS S3 in that instance and this issue can be closed.

https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html > This action is useful to determine if a bucket exists and you have permission to access it. The action returns a 200 OK if the bucket exists and you have permission to access it. > > If the bucket does not exist or you do not have permission to access it, the HEAD request returns a generic 400 Bad Request, 403 Forbidden or 404 Not Found code. A message body is not included, so you cannot determine the exception beyond these error codes. In any case garage behaves like AWS S3 in that instance and this issue can be closed.
Owner

What we are still missing is the x-amz-bucket-region though. I'm not sure how it is used by minio to detect the correct region but we should probably add it to garage anyway

What we are still missing is the `x-amz-bucket-region` though. I'm not sure how it is used by minio to detect the correct region but we should probably add it to garage anyway
Sign in to join this conversation.
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Deuxfleurs/garage#624
No description provided.