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

Commit

Permalink
fix URL host name and credentials when generating presigned URL
Browse files Browse the repository at this point in the history
  • Loading branch information
whummer committed Nov 12, 2020
1 parent e4bf2eb commit f4c7499
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 13 deletions.
4 changes: 2 additions & 2 deletions localstack/services/infra.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ def check_aws_credentials():
pass
if not credentials:
# set temporary dummy credentials
os.environ['AWS_ACCESS_KEY_ID'] = 'LocalStackDummyAccessKey'
os.environ['AWS_SECRET_ACCESS_KEY'] = 'LocalStackDummySecretKey'
os.environ['AWS_ACCESS_KEY_ID'] = constants.TEST_AWS_ACCESS_KEY_ID
os.environ['AWS_SECRET_ACCESS_KEY'] = constants.TEST_AWS_SECRET_ACCESS_KEY
session = boto3.Session()
credentials = session.get_credentials()
assert credentials
Expand Down
31 changes: 20 additions & 11 deletions localstack/services/s3/s3_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
IGNORED_HEADERS_LOWER = [
'remote-addr', 'host', 'user-agent', 'accept-encoding',
'accept', 'connection', 'origin',
'x-forwarded-for', 'x-localstack-edge', 'authorization'
'x-forwarded-for', 'x-localstack-edge', 'authorization', 'date'
]

# params are required in presigned url
Expand Down Expand Up @@ -326,6 +326,14 @@ def convert_origins_into_list(allowed_origins):
return [allowed_origins]


def get_origin_host(headers):
origin = headers.get('Origin')
if not origin:
x_forwarded_header = re.split(r',\s?', headers.get('X-Forwarded-For', ''))
origin = x_forwarded_header[len(x_forwarded_header) - 1]
return origin


def append_cors_headers(bucket_name, request_method, request_headers, response):
bucket_name = normalize_bucket_name(bucket_name)

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

# Fetching origin of the request
origin = request_headers.get('Origin')

if not origin:
x_forwarded_header = re.split(r',\s?', request_headers.get('X-Forwarded-For'))
origin = x_forwarded_header[len(x_forwarded_header) - 1]
origin = get_origin_host(request_headers)

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

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

# Preparnig dictionary of request to build AWSRequest's object of the botocore
request_url = url.split('?')[0]
origin = get_origin_host(headers)
if origin:
request_url = re.sub('://[^/]+', '://%s' % origin, request_url)
request_dict = {
'url_path': path.split('?')[0],
'query_string': {},
'method': method,
'headers': dict(sign_headers),
'body': b'',
'url': url.split('?')[0],
'url': request_url,
'context': {
'is_presign_request': True,
'use_global_endpoint': True,
Expand All @@ -1428,7 +1436,8 @@ def authenticate_presign_url(method, path, headers, data=None):
signature = auth.get_signature(string_to_sign=string_to_sign)

# Comparing the signature in url with signature we calculated
if query_params['Signature'][0] != signature:
query_sig = urlparse.unquote(query_params['Signature'][0])
if query_sig != signature:
return requests_error_response_xml_signature_calculation(
code=403,
code_string='SignatureDoesNotMatch',
Expand Down

0 comments on commit f4c7499

Please sign in to comment.