Path: blob/develop/tests/functional/s3/test_presign_command.py
1567 views
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.1#2# Licensed under the Apache License, Version 2.0 (the "License"). You3# may not use this file except in compliance with the License. A copy of4# the License is located at5#6# http://aws.amazon.com/apache2.0/7#8# or in the "license" file accompanying this file. This file is9# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF10# ANY KIND, either express or implied. See the License for the specific11# language governing permissions and limitations under the License.12import datetime1314from botocore.compat import urlsplit15from awscli.testutils import BaseAWSCommandParamsTest, mock, temporary_file16from awscli.testutils import create_clidriver171819# Values used to fix time.time() and datetime.datetime.now()20# so we know the exact values of the signatures generated.21FROZEN_TIMESTAMP = 147130565222DEFAULT_EXPIRES = 360023FROZEN_TIME = mock.Mock(return_value=FROZEN_TIMESTAMP)24FROZEN_DATETIME = mock.Mock(25return_value=datetime.datetime(2016, 8, 18, 14, 33, 3, 0))262728class TestPresignCommand(BaseAWSCommandParamsTest):2930prefix = 's3 presign '3132def enable_addressing_mode_in_config(self, fileobj, mode):33fileobj.write(34"[default]\n"35"s3 =\n"36" addressing_style = %s\n" % mode37)38fileobj.flush()39self.environ['AWS_CONFIG_FILE'] = fileobj.name40self.driver = create_clidriver()4142def enable_sigv4_from_config_file(self, fileobj):43fileobj.write(44"[default]\n"45"s3 =\n"46" signature_version = s3v4\n"47)48fileobj.flush()49self.environ['AWS_CONFIG_FILE'] = fileobj.name50self.driver = create_clidriver()5152def assert_presigned_url_matches(self, actual_url, expected_match):53"""Verify generated presigned URL matches expected dict.5455This method compares an actual URL against a dict of expected56values. The reason that the "expected_match" is a dict instead57of the expected presigned URL is because the query params58are unordered so we can't guarantee an expected query param59ordering.6061"""62parts = urlsplit(actual_url)63self.assertEqual(parts.netloc, expected_match['hostname'])64self.assertEqual(parts.path, expected_match['path'])65query_params = self.parse_query_string(parts.query)66self.assertEqual(query_params, expected_match['query_params'])6768def parse_query_string(self, query_string):69pairs = []70for part in query_string.split('&'):71pairs.append(part.split('=', 1))72return dict(pairs)7374def get_presigned_url_for_cmd(self, cmdline):75with mock.patch('time.time', FROZEN_TIME):76with mock.patch('datetime.datetime') as d:77d.now = FROZEN_DATETIME78stdout = self.assert_params_for_cmd(cmdline, None)[0].strip()79return stdout8081def test_generates_a_url(self):82stdout = self.get_presigned_url_for_cmd(83self.prefix + 's3://bucket/key')8485self.assert_presigned_url_matches(86stdout, {87'hostname': 'bucket.s3.amazonaws.com',88'path': '/key',89'query_params': {90'AWSAccessKeyId': 'access_key',91'Expires': str(FROZEN_TIMESTAMP + DEFAULT_EXPIRES),92'Signature': '2m9M0eLB%2BqI0nUpkyTskKmHd0Ig%3D',93}94}95)9697def test_handles_non_dns_compatible_buckets(self):98stdout = self.get_presigned_url_for_cmd(99self.prefix + 's3://bucket.dots/key')100101self.assert_presigned_url_matches(102stdout, {103'hostname': 's3.amazonaws.com',104'path': '/bucket.dots/key',105'query_params': {106'AWSAccessKeyId': 'access_key',107'Expires': str(FROZEN_TIMESTAMP + DEFAULT_EXPIRES),108'Signature': '0IiC2vxub438EVcKfEFEMHuoHRw%3D',109}110}111)112113def test_handles_expires_in(self):114expires_in = 1000115stdout = self.get_presigned_url_for_cmd(116self.prefix + 's3://bucket/key --expires-in %s' % expires_in)117118self.assert_presigned_url_matches(119stdout, {120'hostname': 'bucket.s3.amazonaws.com',121'path': '/key',122'query_params': {123'AWSAccessKeyId': 'access_key',124'Expires': str(FROZEN_TIMESTAMP + expires_in),125'Signature': 'WZEMcfBNlzfTZBq3bOvYef1cfoU%3D',126}127}128)129130def test_handles_sigv4(self):131with temporary_file('w') as f:132self.enable_sigv4_from_config_file(f)133stdout = self.get_presigned_url_for_cmd(134self.prefix + 's3://bucket/key')135136expected = {137'hostname': 'bucket.s3.amazonaws.com',138'path': '/key',139'query_params': {140'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',141'X-Amz-Credential': (142'access_key%2F20160818%2Fus-east-1'143'%2Fs3%2Faws4_request'),144'X-Amz-Date': '20160818T143303Z',145'X-Amz-Expires': '3600',146'X-Amz-Signature': (147'd28b6c4a54f31196a6d49335556736a3fc29f036018c8e'148'50775887299092d1a0'),149'X-Amz-SignedHeaders': 'host'150}151}152self.assert_presigned_url_matches(stdout, expected)153154def test_s3_prefix_not_needed(self):155# Consistent with the 'ls' command.156stdout = self.get_presigned_url_for_cmd(157self.prefix + 'bucket/key')158159self.assert_presigned_url_matches(160stdout, {161'hostname': 'bucket.s3.amazonaws.com',162'path': '/key',163'query_params': {164'AWSAccessKeyId': 'access_key',165'Expires': str(FROZEN_TIMESTAMP + DEFAULT_EXPIRES),166'Signature': '2m9M0eLB%2BqI0nUpkyTskKmHd0Ig%3D',167}168}169)170171def test_can_support_addressing_mode_config(self):172with temporary_file('w') as f:173self.enable_addressing_mode_in_config(f, 'path')174stdout = self.get_presigned_url_for_cmd(175self.prefix + 's3://bucket/key')176self.assert_presigned_url_matches(177stdout, {178'hostname': 's3.amazonaws.com',179'path': '/bucket/key',180'query_params': {181'AWSAccessKeyId': 'access_key',182'Expires': str(FROZEN_TIMESTAMP + DEFAULT_EXPIRES),183'Signature': '2m9M0eLB%2BqI0nUpkyTskKmHd0Ig%3D',184}185}186)187188189