diff --git a/.changes/next-release/bugfix-SSEC-65150.json b/.changes/next-release/bugfix-SSEC-65150.json new file mode 100644 index 000000000000..de684e1ec9e7 --- /dev/null +++ b/.changes/next-release/bugfix-SSEC-65150.json @@ -0,0 +1,5 @@ +{ + "type": "bugfix", + "category": "``SSE-C``", + "description": "Pass SSECustomer* arguments to CompleteMultipartUpload for upload operations" +} diff --git a/awscli/botocore/handlers.py b/awscli/botocore/handlers.py index 2ff0625fda2b..6b846b26fa9c 100644 --- a/awscli/botocore/handlers.py +++ b/awscli/botocore/handlers.py @@ -1125,6 +1125,7 @@ def customize_endpoint_resolver_builtins( ('before-parameter-build.s3.UploadPart', sse_md5), ('before-parameter-build.s3.UploadPartCopy', sse_md5), ('before-parameter-build.s3.UploadPartCopy', copy_source_sse_md5), + ('before-parameter-build.s3.CompleteMultipartUpload', sse_md5), ('before-parameter-build.ec2.RunInstances', base64_encode_user_data), ('before-parameter-build.auto-scaling.CreateLaunchConfiguration', base64_encode_user_data), diff --git a/awscli/s3transfer/copies.py b/awscli/s3transfer/copies.py index a1dfdc8ba390..3cd8ef04fa01 100644 --- a/awscli/s3transfer/copies.py +++ b/awscli/s3transfer/copies.py @@ -69,7 +69,13 @@ class CopySubmissionTask(SubmissionTask): 'TaggingDirective', ] - COMPLETE_MULTIPART_ARGS = ['RequestPayer', 'ExpectedBucketOwner'] + COMPLETE_MULTIPART_ARGS = [ + 'SSECustomerKey', + 'SSECustomerAlgorithm', + 'SSECustomerKeyMD5', + 'RequestPayer', + 'ExpectedBucketOwner', + ] def _submit( self, client, config, osutil, request_executor, transfer_future diff --git a/awscli/s3transfer/upload.py b/awscli/s3transfer/upload.py index 18368e0e363a..b864b97d0ac3 100644 --- a/awscli/s3transfer/upload.py +++ b/awscli/s3transfer/upload.py @@ -521,7 +521,13 @@ class UploadSubmissionTask(SubmissionTask): 'ExpectedBucketOwner', ] - COMPLETE_MULTIPART_ARGS = ['RequestPayer', 'ExpectedBucketOwner'] + COMPLETE_MULTIPART_ARGS = [ + 'SSECustomerKey', + 'SSECustomerAlgorithm', + 'SSECustomerKeyMD5', + 'RequestPayer', + 'ExpectedBucketOwner', + ] def _get_upload_input_manager_cls(self, transfer_future): """Retrieves a class for managing input for an upload based on file type diff --git a/tests/functional/s3transfer/test_copy.py b/tests/functional/s3transfer/test_copy.py index 86f05cbfd229..9fde743c9628 100644 --- a/tests/functional/s3transfer/test_copy.py +++ b/tests/functional/s3transfer/test_copy.py @@ -481,7 +481,9 @@ def test_copy_passes_args_to_create_multipart_and_upload_part(self): self.add_head_object_response(expected_params=head_params) self._add_params_to_expected_params( - add_copy_kwargs, ['create_mpu', 'copy'], self.extra_args + add_copy_kwargs, + ['create_mpu', 'copy', 'complete_mpu'], + self.extra_args, ) self.add_successful_copy_responses(**add_copy_kwargs) diff --git a/tests/functional/s3transfer/test_upload.py b/tests/functional/s3transfer/test_upload.py index 9f2a4d63ce18..cf61ecb3eb66 100644 --- a/tests/functional/s3transfer/test_upload.py +++ b/tests/functional/s3transfer/test_upload.py @@ -599,3 +599,28 @@ def test_multipart_upload_passes_checksums(self): ) future.result() self.assert_expected_client_calls_were_correct() + + def test_multipart_upload_with_ssec_args(self): + params = { + 'RequestPayer': 'requester', + 'SSECustomerKey': 'key', + 'SSECustomerAlgorithm': 'AES256', + 'SSECustomerKeyMD5': 'key-hash', + } + self.extra_args.update(params) + + self.add_create_multipart_response_with_default_expected_params( + extra_expected_params=params + ) + + self.add_upload_part_responses_with_default_expected_params( + extra_expected_params=params + ) + self.add_complete_multipart_response_with_default_expected_params( + extra_expected_params=params + ) + future = self.manager.upload( + self.filename, self.bucket, self.key, self.extra_args + ) + future.result() + self.assert_expected_client_calls_were_correct()