Repository: localstack/localstack

Issue:
bug: LocalStack authentication expects a space after commas in Authorization header parameters
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

I'm using [`LocalStack`](https://github.com/localstack/localstack) - the Docker container - to perform local tests on top of [`ex_aws`](https://github.com/ex-aws/ex_aws), an Elixir library.

I'm getting the following error 

```
Authorization header requires \\Signature\\ parameter. Authorization header requires \\SignedHeaders\\ parameter.
```

The `Authorization` header does have those parameters, but... they're written like this

```
AWS4-HMAC-SHA256 Credential=<cred>,SignedHeaders=<sign_head>,Signature=<sign>
```

instead of

```
AWS4-HMAC-SHA256 Credential=<cred>, SignedHeaders=<sign_head>, Signature=<sign>
                                   ^ notice the extra space
```

which seemingly LocalStack expects, but shouldn't (?)

[AWS' Authenticating Requests (AWS Signature Version 4) > Using an Authorization Header > Overview](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html#sigv4-auth-header-overview) is not very clear either since in the example they post, we find

```
Authorization: AWS4-HMAC-SHA256 
Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, 
                                                                   ^ a space here
SignedHeaders=host;range;x-amz-date,
                                    ^ no space here
Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
```

### Expected Behavior

LocalStack should consume both forms of the `Authorization` header made explicit in section "Current Behavior"

### How are you starting LocalStack?

With a `docker run` command

### Steps To Reproduce

#### How are you starting localstack (e.g., `bin/localstack` command, arguments, or `docker-compose.yml`)

    docker run localstack/localstack

#### Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)

    using an Elixir library, as explained above

### Environment

```markdown
- OS: MacOS 12.6
- LocalStack: 1.3.0
```


### Anything else?

I initially posted about this in [discuss.localstack.cloud: 
Authorization header potentially not parsed right](https://discuss.localstack.cloud/t/authorization-header-potentially-not-parsed-right/183/3).


Discussion:
Welcome to LocalStack! Thanks for reporting your first issue and our team will be working towards fixing the issue for you or reach out for more background information. We recommend joining our [Slack Community](https://localstack.cloud/contact/) for real-time help and drop a message to LocalStack Pro Support if you are a Pro user! If you are willing to contribute towards fixing this issue, please have a look at our [contributing guidelines](https://github.com/localstack/.github/blob/main/CONTRIBUTING.md) and our [contributing guide](https://docs.localstack.cloud/contributing/).
I did a quick search on the source code and can't find anything that points to the Authorization header being parsed by LocalStack itself. This is maybe a dependency issue (?)
Hello @paulo-ferraz-oliveira and thanks a lot for your report!

Like you, I've tried a quick search through LocalStack and some dependencies and could not find something like the beginning of the error message. Could you please tell us when that exception happen? Is it targeting a specific service?

I've tried to send a request against S3 (`CreateBucket`) with no space between around commas and it passed.
(Sent headers: `'Authorization': 'AWS4-HMAC-SHA256 Credential=000000000000/20221219/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-date,Signature=061edc089173b7191df123d52d92fc25a157de842fab60f391bc55b781cad04e'`)

So I'm guessing it has to do with a specific implementation, and not the general one. Thanks a lot for the pointer in your last message!
Maybe you can link the Docker logs you have when receiving this particular exception. You can set `LS_LOG=trace` and `DEBUG=1` to get some more verbose logs.
Hello. Thank you for your feedback. It's a least happening using Kinesis. I did not check if it's happening for other services, for the time being.
I'm running the container, locally, with

```
docker run -p 4566:4566 localstack/localstack
```

then I'm performing a call with `awslocal` as

```
awslocal --debug --endpoint-url=http://localhost:4566 kinesis list-streams
```

but the headers include the `, `. I'll try to perform the HTTP call directly, e.g. using `curl` and check what happens.
Now running the container with

```
LS_LOG=trace DEBUG=1 docker run -p 4566:4566 localstack/localstack
```

the `curl` request being

```
curl -v -X POST -H "Authorization: AWS4-HMAC-SHA256 Credential=test/20221219/us-east-1/kinesis/aws4_request,SignedHeaders=content-type;host;x-amz-date;x-amz-target,Signature=ba9705e002b4f224d08c908606f0076a7f4f53bcc68315897764c587c7e5ffb5" -H "content-type: application/x-amz-json-1.1" -H "host: localhost:4566" -H "x-amz-date: 20221219T221436Z" -H "x-amz-target: Kinesis_20131202.ListStreams" http://127.0.0.1:4566
```

I'm getting

```
{"__type": "IncompleteSignatureException", "message": "Authorization header requires \\Signature\\ parameter. Authorization header requires \\SignedHeaders\\ parameter."}
```

Put the spaces in and I get

```
{"StreamNames": [], "HasMoreStreams": false}
```

(strange that the service with influence Authorization header parsing)
Docker logs

```
2022-12-19T22:23:08.585  INFO --- [   asgi_gw_0] localstack.services.infra  : Starting mock Kinesis service on http port 4566 ...
2022-12-19T22:23:09.394  INFO --- [-functhread9] l.s.k.kinesis_mock_server  : [io-compute-blocker-2] INFO  2022-12-19 22:23:09,392 k.m.KinesisMockService contextId=b7aab196-7feb-11ed-b751-af810d2f0af3, cacheConfig={"awsAccountId":"000000000000","awsRegion":"us-east-1","createStreamDuration":{"length":500,"unit":"MILLISECONDS"},"deleteStreamDuration":{"length":500,"unit":"MILLISECONDS"},"deregisterStreamConsumerDuration":{"length":500,"unit":"MILLISECONDS"},"initializeStreams":null,"mergeShardsDuration":{"length":500,"unit":"MILLISECONDS"},"onDemandStreamCountLimit":10,"persistConfig":{"fileName":"000000000000.json","interval":{"length":5,"unit":"SECONDS"},"loadIfExists":true,"path":"/var/lib/localstack/tmp/state/kinesis","shouldPersist":true},"registerStreamConsumerDuration":{"length":500,"unit":"MILLISECONDS"},"shardLimit":100,"splitShardDuration":{"length":500,"unit":"MILLISECONDS"},"startStreamEncryptionDuration":{"length":500,"unit":"MILLISECONDS"},"stopStreamEncryptionDuration":{"length":500,"unit":"MILLISECONDS"},"updateShardCountDuration":{"length":500,"unit":"MILLISECONDS"}} - Logging Cache Config
2022-12-19T22:23:09.952  INFO --- [-functhread9] l.s.k.kinesis_mock_server  : [io-compute-blocker-6] INFO  2022-12-19 22:23:09,952 k.m.KinesisMockService  - Starting Kinesis TLS Mock Service on port 41233
2022-12-19T22:23:09.952  INFO --- [-functhread9] l.s.k.kinesis_mock_server  : [io-compute-blocker-6] INFO  2022-12-19 22:23:09,952 k.m.KinesisMockService  - Starting Kinesis Plain Mock Service on port 57369
2022-12-19T22:23:09.963  INFO --- [-functhread9] l.s.k.kinesis_mock_server  : [io-compute-2] INFO  2022-12-19 22:23:09,962 k.m.KinesisMockService contextId=b801f957-7feb-11ed-b751-af810d2f0af3 - Starting persist data loop
2022-12-19T22:23:10.389  INFO --- [-functhread9] l.s.k.kinesis_mock_server  : [io-compute-0] WARN  2022-12-19 22:23:10,389 k.m.KinesisMockRoutes missingAuthKeys=Signature, SignedHeaders, x-amzn-RequestId=b844327b-7feb-11ed-b751-af810d2f0af3, action=ListStreams, contextId=b844327a-7feb-11ed-b751-af810d2f0af3, x-amz-id-2=bW85lsdMwUNuQMLM/z6xbM6FqktvJQliiy3X9GZpBQOXYKlMOSJe3GnAAeeag7fAHrtCO8JY9jdspHFvxhOEr1A97tuC7wnd, contentType=application/x-amz-json-1.1 - Some required information was not provied with the authorization header
2022-12-19T22:23:10.396  INFO --- [   asgi_gw_0] localstack.request.aws     : AWS kinesis.ListStreams => 400 (IncompleteSignatureException)
2022-12-19T22:24:01.014  INFO --- [   asgi_gw_1] localstack.request.aws     : AWS kinesis.ListStreams => 200
```

This also has a typo 😄 (provied): "Some required information was not provied with the authorization header"
I'm now convinced the error is coming from https://github.com/etspaceman/kinesis-mock/blob/main/src/main/scala/kinesis/mock/KinesisMockRoutes.scala#L206, as I peaked inside `Dockerfile` and found it to use `kinesis-mock`. (that lib also contains the "provied" typo 😄)
Yes, thanks a lot for your investigation, I was coming to the same conclusion.
I've opened [an issue](https://github.com/etspaceman/kinesis-mock/issues/386) in the repository, but we will keep this one open until the fix is part of LocalStack.

Thanks again for your detailed report!
Thank you for your time and energy. Yes, it's good this remains open until a fix is released and properly integrated into LocalStack.
`kinesis-mock` 0.3.1 was released with that fix. Want me to pull request here to use that, as a default, in the Docker image?
Hello!
Sure, if you want, you can create a PR. Here's the last PR made by the maintainer of `kinesis-mock`: #7346 
That would be great, thanks a lot for your work! 
No biggie. My PR would be to simply up the version LocalStack is using, by default, for `kinesis-mock`. I believe that'd be enough. (I think there's no need to add tests here, but let me know if you feel otherwise)

Resolving patch:
diff --git a/localstack/services/kinesis/packages.py b/localstack/services/kinesis/packages.py
--- a/localstack/services/kinesis/packages.py
+++ b/localstack/services/kinesis/packages.py
@@ -6,7 +6,7 @@
 from localstack.packages import GitHubReleaseInstaller, Package, PackageInstaller
 from localstack.utils.platform import get_arch, get_os
 
-_KINESIS_MOCK_VERSION = os.environ.get("KINESIS_MOCK_VERSION") or "0.3.0"
+_KINESIS_MOCK_VERSION = os.environ.get("KINESIS_MOCK_VERSION") or "0.3.1"
 
 
 class KinesisMockPackage(Package):


Test patch: