Closed btalbot closed 11 months ago
This appears to be related to https://github.com/softwaremill/elasticmq/issues/812 which is marked as closed and fixed in elasticmq 1.4.
The ruby aws-sdk-sqs client does indeed switch to using application/x-amz-json-1.0
while the previous (working) version uses application/x-www-form-urlencoded
content-type.
Below are two wire captures of the requests.
Working request using aws-sdk-sqs 1.65.0
POST / HTTP/1.1
Accept-Encoding:
Content-Type: application/x-www-form-urlencoded; charset=utf-8
User-Agent: aws-sdk-ruby3/3.186.0 ua/2.0 api/sqs#1.65.0 os/macos#22 md/x86_64 lang/ruby#3.2.2 md/3.2.2 cfg/retry-mode#legacy
Host: sqs.nemo
X-Amz-Date: 20231109T033528Z
X-Amz-Content-Sha256: 48a38266faf90970d6c7fea9b15e6ba366e5f6397c2970fc893f8a7b5e207bd0
Authorization: AWS4-HMAC-SHA256 Credential=FakeKey/20231109/us-nemo-1/sqs/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=7c43dceff9053ab8f766ad8ea0cc2e7ca871bb32f1bfad1f72ca6f21b2ff774c
Content-Length: 36
Accept: */*
Action=ListQueues&Version=2012-11-05
Broken request using aws-sdk-sqs 1.66.0
POST / HTTP/1.1
Accept-Encoding:
Content-Type: application/x-amz-json-1.0
X-Amz-Target: AmazonSQS.ListQueues
User-Agent: aws-sdk-ruby3/3.186.0 ua/2.0 api/sqs#1.66.0 os/macos#22 md/x86_64 lang/ruby#3.2.2 md/3.2.2 cfg/retry-mode#legacy
Host: sqs.nemo
X-Amz-Date: 20231109T034347Z
X-Amz-Content-Sha256: 44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
Authorization: AWS4-HMAC-SHA256 Credential=FakeKey/20231109/us-nemo-1/sqs/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target, Signature=072de1de606d8081c64e67bef6eab9cff99866bd1c693b91b1f3794d8d9258cc
Content-Length: 2
Accept: */*
{}
Had the same issue using the AWS SDK for javascript v3. Reverted to the soon to be deprecated v2 and it works fine. I have not yet figured out in which version of v3 that amazon dropped the X-Amz-Target header.
I think I've found the root of the problem. The issue is that elasticmq, when looking for the X-Amz-Target
, header is making a case sensitive comparison here:
https://github.com/softwaremill/elasticmq/blob/b31c8a6dd1f7097650b7294ce77044849290c622/rest/rest-sqs/src/main/scala/org/elasticmq/rest/sqs/directives/AnyParamDirectives.scala#L25C11-L25C11
The HTTP 1.1 spec generally expects http header NAMES to be case insensitive and thus many proxies may alter the headers during filtering and serialization which is what the envoy proxies running in our kubernetes systems are doing. https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/header_casing
I believe that the proper fix is to simply make the search of the x-amz-target
header be case insensitive as the check for the x-amzn-trace-id header is here
https://github.com/softwaremill/elasticmq/blob/b31c8a6dd1f7097650b7294ce77044849290c622/rest/rest-sqs/src/main/scala/org/elasticmq/rest/sqs/directives/AnyParamDirectives.scala#L38C32-L38C32
I've verified experimentally (via curl) that Amazon SQS is case-insensitive in accepting the header names.
[edit] included link to x-amzn-trace-id header which uses equalsIgnoreCase
Thanks for reporting the issue. I'll try to look into this within a few days
I think I've found the root of the problem. The issue is that elasticmq, when looking for the
X-Amz-Target
, header is making a case sensitive comparison here: https://github.com/softwaremill/elasticmq/blob/b31c8a6dd1f7097650b7294ce77044849290c622/rest/rest-sqs/src/main/scala/org/elasticmq/rest/sqs/directives/AnyParamDirectives.scala#L25C11-L25C11The HTTP 1.1 spec generally expects http header NAMES to be case insensitive and thus many proxies may alter the headers during filtering and serialization which is what the envoy proxies running in our kubernetes systems are doing. https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/header_casing
I believe that the proper fix is to simply make the search of the
x-amz-target
header be case insensitive as the check for the x-amzn-trace-id header is here https://github.com/softwaremill/elasticmq/blob/b31c8a6dd1f7097650b7294ce77044849290c622/rest/rest-sqs/src/main/scala/org/elasticmq/rest/sqs/directives/AnyParamDirectives.scala#L38C32-L38C32I've verified experimentally (via curl) that Amazon SQS is case-insensitive in accepting the header names.
[edit] included link to x-amzn-trace-id header which uses
equalsIgnoreCase
@btalbot thanks. I tested the fix and it works perfectly. I made a PR with the fix #900 and also docker images.
Latest (as of right now anyway) version of aws-sdk-sqs ruby client version 1.66.0 seems to no longer supply the X-Amz-Target header ... at least elasticmq cannot find it.
I've tested using docker the elasticmq and elasticmq-native images and they behave the same. Reverting the aws-sdk-sqs ruby client to 1.65.0 and it works. The problematic aws-sdk-sqs ruby client version 1.66.0 works fine with real SQS on AWS so I doubt that AWS will consider this a bug.
The bug is trivial to trigger in ruby with anything that makes a request to sqs (activemq)
The activemq server stack trace