Skip to content

Commit

Permalink
forward original host and fix logic for path based addressing
Browse files Browse the repository at this point in the history
  • Loading branch information
whummer committed Sep 23, 2024
1 parent 0bcbb53 commit f9c0349
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 3 deletions.
16 changes: 14 additions & 2 deletions aws-replicator/aws_replicator/client/auth_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from localstack import config as localstack_config
from localstack.aws.spec import load_service
from localstack.config import external_service_url
from localstack.constants import AWS_REGION_US_EAST_1, DOCKER_IMAGE_NAME_PRO
from localstack.constants import AWS_REGION_US_EAST_1, DOCKER_IMAGE_NAME_PRO, LOCALHOST_HOSTNAME
from localstack.http import Request
from localstack.utils.aws.aws_responses import requests_response
from localstack.utils.bootstrap import setup_logging
Expand All @@ -32,6 +32,7 @@
from aws_replicator import config as repl_config
from aws_replicator.client.utils import truncate_content
from aws_replicator.config import HANDLER_PATH_PROXIES
from aws_replicator.shared.constants import HEADER_HOST_ORIGINAL
from aws_replicator.shared.models import AddProxyRequest, ProxyConfig

from .http2_server import run_server
Expand Down Expand Up @@ -106,6 +107,7 @@ def proxy_request(self, request: Request, data: bytes) -> Response:

# fix headers (e.g., "Host") and create client
self._fix_headers(request, service_name)
self._fix_host_and_path(request, service_name)

# create request and request dict
operation_model, aws_request, request_dict = self._parse_aws_request(
Expand Down Expand Up @@ -262,14 +264,24 @@ def _fix_headers(self, request: Request, service_name: str):
host = request.headers.get("Host") or ""
regex = r"^(https?://)?([0-9.]+|localhost)(:[0-9]+)?"
if re.match(regex, host):
request.headers["Host"] = re.sub(regex, r"\1s3.localhost.localstack.cloud", host)
request.headers["Host"] = re.sub(regex, rf"\1s3.{LOCALHOST_HOSTNAME}", host)
request.headers.pop("Content-Length", None)
request.headers.pop("x-localstack-request-url", None)
request.headers.pop("X-Forwarded-For", None)
request.headers.pop("X-Localstack-Tgt-Api", None)
request.headers.pop("X-Moto-Account-Id", None)
request.headers.pop("Remote-Addr", None)

def _fix_host_and_path(self, request: Request, service_name: str):
if service_name == "s3":
# fix the path and Host header, to avoid bucket addressing issues
host = request.headers.pop(HEADER_HOST_ORIGINAL, None)
host = host or request.headers.get("Host") or ""
match = re.match(rf"(.+)\.s3\.{LOCALHOST_HOSTNAME}", host)
if match:
# prepend the bucket name (extracted from the host) to the path of the request (path-based addressing)
request.path = f"/{match.group(1)}{request.path}"

def _extract_region_and_service(self, headers) -> Optional[Tuple[str, str]]:
auth_header = headers.pop("Authorization", "")
parts = auth_header.split("Credential=", maxsplit=1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
except ImportError:
from localstack.constants import TEST_AWS_ACCESS_KEY_ID

from aws_replicator.shared.constants import HEADER_HOST_ORIGINAL
from aws_replicator.shared.models import ProxyInstance, ProxyServiceConfig

LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -145,7 +146,7 @@ def forward_request(self, context: RequestContext, proxy: ProxyInstance) -> requ

result = None
try:
headers.pop("Host", None)
headers[HEADER_HOST_ORIGINAL] = headers.pop("Host", None)
headers.pop("Content-Length", None)
ctype = headers.get("Content-Type")
data = b""
Expand Down
2 changes: 2 additions & 0 deletions aws-replicator/aws_replicator/shared/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# header name for the original request host name forwarded in the request to the target proxy handler
HEADER_HOST_ORIGINAL = "x-ls-host-original"

0 comments on commit f9c0349

Please sign in to comment.