Skip to content
This repository was archived by the owner on Aug 14, 2024. It is now read-only.

Commit f4c7499

Browse files
committed
fix URL host name and credentials when generating presigned URL
1 parent e4bf2eb commit f4c7499

2 files changed

Lines changed: 22 additions & 13 deletions

File tree

localstack/services/infra.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ def check_aws_credentials():
329329
pass
330330
if not credentials:
331331
# set temporary dummy credentials
332-
os.environ['AWS_ACCESS_KEY_ID'] = 'LocalStackDummyAccessKey'
333-
os.environ['AWS_SECRET_ACCESS_KEY'] = 'LocalStackDummySecretKey'
332+
os.environ['AWS_ACCESS_KEY_ID'] = constants.TEST_AWS_ACCESS_KEY_ID
333+
os.environ['AWS_SECRET_ACCESS_KEY'] = constants.TEST_AWS_SECRET_ACCESS_KEY
334334
session = boto3.Session()
335335
credentials = session.get_credentials()
336336
assert credentials

localstack/services/s3/s3_listener.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
IGNORED_HEADERS_LOWER = [
9999
'remote-addr', 'host', 'user-agent', 'accept-encoding',
100100
'accept', 'connection', 'origin',
101-
'x-forwarded-for', 'x-localstack-edge', 'authorization'
101+
'x-forwarded-for', 'x-localstack-edge', 'authorization', 'date'
102102
]
103103

104104
# params are required in presigned url
@@ -326,6 +326,14 @@ def convert_origins_into_list(allowed_origins):
326326
return [allowed_origins]
327327

328328

329+
def get_origin_host(headers):
330+
origin = headers.get('Origin')
331+
if not origin:
332+
x_forwarded_header = re.split(r',\s?', headers.get('X-Forwarded-For', ''))
333+
origin = x_forwarded_header[len(x_forwarded_header) - 1]
334+
return origin
335+
336+
329337
def append_cors_headers(bucket_name, request_method, request_headers, response):
330338
bucket_name = normalize_bucket_name(bucket_name)
331339

@@ -340,11 +348,7 @@ def append_cors_headers(bucket_name, request_method, request_headers, response):
340348
del response.headers[header]
341349

342350
# Fetching origin of the request
343-
origin = request_headers.get('Origin')
344-
345-
if not origin:
346-
x_forwarded_header = re.split(r',\s?', request_headers.get('X-Forwarded-For'))
347-
origin = x_forwarded_header[len(x_forwarded_header) - 1]
351+
origin = get_origin_host(request_headers)
348352

349353
rules = cors['CORSConfiguration']['CORSRule']
350354
if not isinstance(rules, list):
@@ -1392,9 +1396,9 @@ def authenticate_presign_url(method, path, headers, data=None):
13921396
if key.lower() not in IGNORED_HEADERS_LOWER:
13931397
sign_headers.append(header)
13941398

1395-
# Request's headers are more essentials than the query parameters in the requets.
1396-
# Different values of header in the header of the request and in the query paramter of the requets url
1397-
# will fail the signature calulation. As per the AWS behaviour
1399+
# Request's headers are more essentials than the query parameters in the request.
1400+
# Different values of header in the header of the request and in the query parameter of the
1401+
# request URL will fail the signature calulation. As per the AWS behaviour
13981402
presign_params_lower = [p.lower() for p in PRESIGN_QUERY_PARAMS]
13991403
if len(query_params) > 2:
14001404
for key in query_params:
@@ -1403,13 +1407,17 @@ def authenticate_presign_url(method, path, headers, data=None):
14031407
sign_headers.append((key, query_params[key][0]))
14041408

14051409
# Preparnig dictionary of request to build AWSRequest's object of the botocore
1410+
request_url = url.split('?')[0]
1411+
origin = get_origin_host(headers)
1412+
if origin:
1413+
request_url = re.sub('://[^/]+', '://%s' % origin, request_url)
14061414
request_dict = {
14071415
'url_path': path.split('?')[0],
14081416
'query_string': {},
14091417
'method': method,
14101418
'headers': dict(sign_headers),
14111419
'body': b'',
1412-
'url': url.split('?')[0],
1420+
'url': request_url,
14131421
'context': {
14141422
'is_presign_request': True,
14151423
'use_global_endpoint': True,
@@ -1428,7 +1436,8 @@ def authenticate_presign_url(method, path, headers, data=None):
14281436
signature = auth.get_signature(string_to_sign=string_to_sign)
14291437

14301438
# Comparing the signature in url with signature we calculated
1431-
if query_params['Signature'][0] != signature:
1439+
query_sig = urlparse.unquote(query_params['Signature'][0])
1440+
if query_sig != signature:
14321441
return requests_error_response_xml_signature_calculation(
14331442
code=403,
14341443
code_string='SignatureDoesNotMatch',

0 commit comments

Comments
 (0)