diff --git a/localstack/aws/handlers/partition_rewriter.py b/localstack/aws/handlers/partition_rewriter.py index 701481ace6770..edf5d260c123d 100644 --- a/localstack/aws/handlers/partition_rewriter.py +++ b/localstack/aws/handlers/partition_rewriter.py @@ -1,3 +1,5 @@ +import base64 +import hashlib import logging import re from re import Match @@ -109,6 +111,12 @@ def modify_request(self, request: Request) -> Request: dict(request.headers), self.DEFAULT_INBOUND_PARTITION ) + # if a Content-MD5 was given, we need to update it after a potential modification + if "Content-MD5" in forward_rewritten_headers: + md = hashlib.md5(forward_rewritten_body).digest() + content_md5 = base64.b64encode(md).decode("utf-8") + forward_rewritten_headers["Content-MD5"] = content_md5 + # add header to signal request has already been rewritten forward_rewritten_headers["LS-INTERNAL-REWRITE-HANDLER"] = "1" # Create a new request with the updated data diff --git a/tests/unit/test_partition_rewriter.py b/tests/unit/test_partition_rewriter.py index 73a9be6cfd260..59e74e70b7b96 100644 --- a/tests/unit/test_partition_rewriter.py +++ b/tests/unit/test_partition_rewriter.py @@ -1,3 +1,5 @@ +import base64 +import hashlib import json from unittest import mock from urllib.parse import urlencode @@ -117,6 +119,37 @@ def test_arn_partition_rewriting_urlencoded_body(): } +def test_arn_partition_rewriting_contentmd5(): + rewrite_handler = ArnPartitionRewriteHandler() + data = {"some-data-with-arn": "arn:aws-us-gov:iam::000000000000:role/test-role"} + body = urlencode(data) + original_md5 = base64.b64encode(hashlib.md5(body.encode("utf-8")).digest()).decode("utf-8") + headers = { + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + "Content-MD5": original_md5, + } + + request = Request( + method="POST", + path="/", + query_string="", + body=body, + headers=headers, + ) + result = rewrite_handler.modify_request(request) + data = result.get_data() + assert result.method == "POST" + assert get_full_raw_path(result) == "/" + assert result.form.to_dict() == { + "some-data-with-arn": "arn:aws:iam::000000000000:role/test-role" + } + assert "Content-MD5" in result.headers + assert result.headers["Content-MD5"] != original_md5 + assert result.headers["Content-MD5"] == base64.b64encode(hashlib.md5(data).digest()).decode( + "utf-8" + ) + + def test_arn_partition_rewriting_url_encoding(httpserver, monkeypatch): path = "/query%3Aencoded%2Fpath/"