def _create_prepared_request(self, params, operation_model): request = create_request_object(params) self._sign_request(request) prepared_request = self.client._endpoint.prepare_request(request) if self._extra_headers is not None: prepared_request.headers.update(self._extra_headers) return prepared_request
def generate_presigned_url(self, request_dict, operation_name, expires_in=3600, region_name=None, signing_name=None): """Generates a presigned url :type request_dict: dict :param request_dict: The prepared request dictionary returned by ``botocore.awsrequest.prepare_request_dict()`` :type operation_name: str :param operation_name: The operation being signed. :type expires_in: int :param expires_in: The number of seconds the presigned url is valid for. By default it expires in an hour (3600 seconds) :type region_name: string :param region_name: The region name to sign the presigned url. :type signing_name: str :param signing_name: The name to use for the service when signing. :returns: The presigned url """ request = create_request_object(request_dict) self.sign(operation_name, request, region_name, 'presign-url', expires_in, signing_name) request.prepare() return request.url
def test_create_request_object(self): request = create_request_object(self.request_dict) self.assertEqual(request.method, self.request_dict['method']) self.assertEqual(request.url, self.request_dict['url']) self.assertEqual(request.data, self.request_dict['body']) self.assertEqual(request.context, self.request_dict['context']) self.assertIn('User-Agent', request.headers)
def generate_presigned_url(self, request_dict, operation_name, expires_in=3600, region_name=None): """Generates a presigned url :type request_dict: dict :param request_dict: The prepared request dictionary returned by ``botocore.awsrequest.prepare_request_dict()`` :type operation_name: str :param operation_name: The operation being signed. :type expires_in: int :param expires_in: The number of seconds the presigned url is valid for. By default it expires in an hour (3600 seconds) :type region_name: string :param region_name: The region name to sign the presigned url. :returns: The presigned url """ request = create_request_object(request_dict) self.sign(operation_name, request, region_name, 'presign-url', expires_in) request.prepare() return request.url
def test_enable_disable_callbacks_only_ever_registered_once(self): body = CallbackEnablingBody() request = create_request_object({ 'method': 'PUT', 'url': 'https://s3.amazonaws.com', 'body': body, 'headers': {}, 'context': {} }) # Create two TransferManager's using the same client TransferManager(self.client) TransferManager(self.client) self.client.meta.events.emit('request-created.s3', request=request, operation_name='PutObject') # The client should have only have the enable/disable callback # handlers registered once depite being used for two different # TransferManagers. self.assertEqual( body.enable_callback_call_count, 1, 'The enable_callback() should have only ever been registered once') self.assertEqual( body.disable_callback_call_count, 1, 'The disable_callback() should have only ever been registered ' 'once')
def authenticate_presign_url_signv2(method, path, headers, data, url, query_params, request_dict): # Calculating Signature aws_request = create_request_object(request_dict) credentials = Credentials(access_key=TEST_AWS_ACCESS_KEY_ID, secret_key=TEST_AWS_SECRET_ACCESS_KEY) auth = HmacV1QueryAuth(credentials=credentials, expires=query_params['Expires'][0]) split = urlsplit(aws_request.url) string_to_sign = auth.get_string_to_sign(method=method, split=split, headers=aws_request.headers) signature = auth.get_signature(string_to_sign=string_to_sign) # Comparing the signature in url with signature we calculated query_sig = urlparse.unquote(query_params['Signature'][0]) if query_sig != signature: return requests_error_response_xml_signature_calculation( code=403, code_string='SignatureDoesNotMatch', aws_access_token=TEST_AWS_ACCESS_KEY_ID, string_to_sign=string_to_sign, signature=signature, message='The request signature we calculated does not match the signature you provided. \ Check your key and signing method.') # Checking whether the url is expired or not if int(query_params['Expires'][0]) < time.time(): return requests_error_response_xml_signature_calculation( code=403, code_string='AccessDenied', message='Request has expired', expires=query_params['Expires'][0] )
def authenticate_presign_url_signv4(method, path, headers, data, url, query_params, request_dict): # Calculating Signature aws_request = create_request_object(request_dict) ReadOnlyCredentials = namedtuple('ReadOnlyCredentials', ['access_key', 'secret_key', 'token']) credentials = ReadOnlyCredentials(TEST_AWS_ACCESS_KEY_ID, TEST_AWS_SECRET_ACCESS_KEY, None) region = query_params['X-Amz-Credential'][0].split('/')[2] signer = S3SigV4QueryAuth(credentials, 's3', region, expires=int(query_params['X-Amz-Expires'][0])) signature = signer.add_auth(aws_request, query_params['X-Amz-Date'][0]) expiration_time = datetime.datetime.strptime(query_params['X-Amz-Date'][0], '%Y%m%dT%H%M%SZ') + \ datetime.timedelta(seconds=int(query_params['X-Amz-Expires'][0])) # Comparing the signature in url with signature we calculated query_sig = urlparse.unquote(query_params['X-Amz-Signature'][0]) if query_sig != signature: return requests_error_response_xml_signature_calculation( code=403, code_string='SignatureDoesNotMatch', aws_access_token=TEST_AWS_ACCESS_KEY_ID, signature=signature, message='The request signature we calculated does not match the signature you provided. \ Check your key and signing method.') # Checking whether the url is expired or not if expiration_time < datetime.datetime.utcnow(): return requests_error_response_xml_signature_calculation( code=403, code_string='AccessDenied', message='Request has expired', expires=query_params['X-Amz-Expires'][0] )
def create_request(self, params, operation_model=None): request = create_request_object(params) if operation_model: event_name = "request-created.{endpoint_prefix}.{op_name}".format( endpoint_prefix=self._endpoint_prefix, op_name=operation_model.name ) self._event_emitter.emit(event_name, request=request, operation_name=operation_model.name) prepared_request = self.prepare_request(request) return prepared_request
def create_request(self, params, operation_model=None): request = create_request_object(params) if operation_model: event_name = 'request-created.{endpoint_prefix}.{op_name}'.format( endpoint_prefix=self._endpoint_prefix, op_name=operation_model.name) self._event_emitter.emit(event_name, request=request, operation_name=operation_model.name) prepared_request = self.prepare_request(request) return prepared_request
def authenticate_presign_url_signv4(method, path, headers, data, url, query_params, request_dict): is_presign_valid = False for port in PORT_REPLACEMENT: match = re.match(HOST_COMBINATION_REGEX, urlparse.urlparse(request_dict['url']).netloc) if match and match.group(2): request_dict['url'] = request_dict['url'].replace('%s' % match.group(2), '%s' % port) else: request_dict['url'] = '%s:%s' % (request_dict['url'], port) # Calculating Signature aws_request = create_request_object(request_dict) ReadOnlyCredentials = namedtuple('ReadOnlyCredentials', ['access_key', 'secret_key', 'token']) credentials = ReadOnlyCredentials(TEST_AWS_ACCESS_KEY_ID, TEST_AWS_SECRET_ACCESS_KEY, query_params.get('X-Amz-Security-Token', None)) region = query_params['X-Amz-Credential'][0].split('/')[2] signer = S3SigV4QueryAuth(credentials, 's3', region, expires=int(query_params['X-Amz-Expires'][0])) signature = signer.add_auth(aws_request, query_params['X-Amz-Date'][0]) expiration_time = datetime.datetime.strptime(query_params['X-Amz-Date'][0], '%Y%m%dT%H%M%SZ') + \ datetime.timedelta(seconds=int(query_params['X-Amz-Expires'][0])) # Comparing the signature in url with signature we calculated query_sig = urlparse.unquote(query_params['X-Amz-Signature'][0]) if query_sig == signature: is_presign_valid = True break # Comparing the signature in url with signature we calculated if config.S3_SKIP_SIGNATURE_VALIDATION: if not is_presign_valid: LOGGER.warning('Signatures do not match, but not raising an error, as S3_SKIP_SIGNATURE_VALIDATION=1') signature = query_sig is_presign_valid = True if not is_presign_valid: return requests_error_response_xml_signature_calculation( code=403, code_string='SignatureDoesNotMatch', aws_access_token=TEST_AWS_ACCESS_KEY_ID, signature=signature, message='The request signature we calculated does not match the signature you provided. \ Check your key and signing method.') # Checking whether the url is expired or not if expiration_time < datetime.datetime.utcnow(): return requests_error_response_xml_signature_calculation( code=403, code_string='AccessDenied', message='Request has expired', expires=query_params['X-Amz-Expires'][0] )
def authenticate_presign_url_signv2(method, path, headers, data, url, query_params, request_dict): # Calculating Signature aws_request = create_request_object(request_dict) credentials = Credentials( access_key=TEST_AWS_ACCESS_KEY_ID, secret_key=TEST_AWS_SECRET_ACCESS_KEY, token=query_params.get("X-Amz-Security-Token", None), ) auth = HmacV1QueryAuth(credentials=credentials, expires=query_params["Expires"][0]) split = urlsplit(aws_request.url) string_to_sign = auth.get_string_to_sign(method=method, split=split, headers=aws_request.headers) signature = auth.get_signature(string_to_sign=string_to_sign) # Comparing the signature in url with signature we calculated query_sig = urlparse.unquote(query_params["Signature"][0]) if config.S3_SKIP_SIGNATURE_VALIDATION: if query_sig != signature: LOGGER.warning( "Signatures do not match, but not raising an error, as S3_SKIP_SIGNATURE_VALIDATION=1" ) signature = query_sig if query_sig != signature: return requests_error_response_xml_signature_calculation( code=403, code_string="SignatureDoesNotMatch", aws_access_token=TEST_AWS_ACCESS_KEY_ID, string_to_sign=string_to_sign, signature=signature, message= "The request signature we calculated does not match the signature you provided. \ Check your key and signing method.", ) # Checking whether the url is expired or not if int(query_params["Expires"][0]) < time.time(): if config.S3_SKIP_SIGNATURE_VALIDATION: LOGGER.warning( "Signature is expired, but not raising an error, as S3_SKIP_SIGNATURE_VALIDATION=1" ) else: return requests_error_response_xml_signature_calculation( code=403, code_string="AccessDenied", message="Request has expired", expires=query_params["Expires"][0], )
def create_request(self, params, operation_model=None): request = create_request_object(params) if operation_model: request.stream_output = any([ operation_model.has_streaming_output, operation_model.has_event_stream_output ]) event_name = 'request-created.{endpoint_prefix}.{op_name}'.format( endpoint_prefix=self._endpoint_prefix, op_name=operation_model.name) self._event_emitter.emit(event_name, request=request, operation_name=operation_model.name) prepared_request = self.prepare_request(request) return prepared_request
def generate_presigned_url(self, request_dict, expires_in=3600, region_name=None): """Generates a presigned url :type request_dict: dict :param request_dict: The prepared request dictionary returned by ``botocore.awsrequest.prepare_request_dict()`` :type expires_in: int :param expires_in: The number of seconds the presigned url is valid for. By default it expires in an hour (3600 seconds) :type region_name: string :param region_name: The region name to sign the presigned url. :returns: The presigned url """ if region_name is None: region_name = self._region_name query_prefix = '-query' signature_version = self._signature_version if not signature_version.endswith(query_prefix): signature_version += query_prefix kwargs = { 'signing_name': self._signing_name, 'region_name': region_name, 'signature_version': signature_version, 'expires': expires_in } signature_type = signature_version.split('-', 1)[0] try: auth = self.get_auth_instance(**kwargs) except UnknownSignatureVersionError: raise UnsupportedSignatureVersionError( signature_version=signature_type) request = create_request_object(request_dict) # Fix s3 host for s3 sigv2 bucket names fix_s3_host(request, signature_type, region_name) auth.add_auth(request) request.prepare() return request.url
def create_request(self, params, operation_model=None): request = create_request_object(params) if operation_model: request.stream_output = any([ operation_model.has_streaming_output, operation_model.has_event_stream_output ]) service_id = operation_model.service_model.service_id.hyphenize() event_name = 'request-created.{service_id}.{op_name}'.format( service_id=service_id, op_name=operation_model.name) self._event_emitter.emit(event_name, request=request, operation_name=operation_model.name) prepared_request = self.prepare_request(request) return prepared_request
def generate_presigned_url(self, request_dict, expires_in=3600, region_name=None): """Generates a presigned url :type request_dict: dict :param request_dict: The prepared request dictionary returned by ``botocore.awsrequest.prepare_request_dict()`` :type expires_in: int :param expires_in: The number of seconds the presigned url is valid for. By default it expires in an hour (3600 seconds) :type region_name: string :param region_name: The region name to sign the presigned url. :returns: The presigned url """ if region_name is None: region_name = self._region_name query_prefix = '-query' signature_version = self._signature_version if not signature_version.endswith(query_prefix): signature_version += query_prefix kwargs = {'signing_name': self._signing_name, 'region_name': region_name, 'signature_version': signature_version, 'expires': expires_in} signature_type = signature_version.split('-', 1)[0] try: auth = self.get_auth(**kwargs) except UnknownSignatureVersionError: raise UnsupportedSignatureVersionError( signature_version=signature_type) request = create_request_object(request_dict) # Fix s3 host for s3 sigv2 bucket names fix_s3_host(request, signature_type, region_name) auth.add_auth(request) request.prepare() return request.url
def test_service_router_works_for_every_service( service: ServiceModel, operation: OperationModel, caplog ): caplog.set_level("CRITICAL", "botocore") # Create a dummy request for the service router client = _client(service.service_name) request_context = { "client_region": client.meta.region_name, "client_config": client.meta.config, "has_streaming_input": operation.has_streaming_input, "auth_type": operation.auth_type, } request_args = _create_dummy_request_args(operation) request_dict = client._convert_to_request_dict(request_args, operation, request_context) request_object = create_request_object(request_dict) client._request_signer.sign(operation.name, request_object) request: Request = _botocore_request_to_localstack_request(request_object) # Execute the service router detected_service_name = determine_aws_service_name(request) # Make sure the detected service is the same as the one we generated the request for assert service.service_name == detected_service_name
def test_enable_disable_callbacks_only_ever_registered_once(self): body = CallbackEnablingBody() request = create_request_object({ 'method': 'PUT', 'url': 'https://s3.amazonaws.com', 'body': body, 'headers': {}, 'context': {} }) # Create two TransferManager's using the same client TransferManager(self.client) TransferManager(self.client) self.client.meta.events.emit( 'request-created.s3', request=request, operation_name='PutObject') # The client should have only have the enable/disable callback # handlers registered once depite being used for two different # TransferManagers. self.assertEqual( body.enable_callback_call_count, 1, 'The enable_callback() should have only ever been registered once') self.assertEqual( body.disable_callback_call_count, 1, 'The disable_callback() should have only ever been registered ' 'once')
def generate_presigned_post(self, request_dict, fields=None, conditions=None, expires_in=3600, region_name=None): """Generates the url and the form fields used for a presigned s3 post :type request_dict: dict :param request_dict: The prepared request dictionary returned by ``botocore.awsrequest.prepare_request_dict()`` :type fields: dict :param fields: A dictionary of prefilled form fields to build on top of. :type conditions: list :param conditions: A list of conditions to include in the policy. Each element can be either a list or a structure. For example: [ {"acl": "public-read"}, {"bucket": "mybucket"}, ["starts-with", "$key", "mykey"] ] :type expires_in: int :param expires_in: The number of seconds the presigned post is valid for. :type region_name: string :param region_name: The region name to sign the presigned post to. :rtype: dict :returns: A dictionary with two elements: ``url`` and ``fields``. Url is the url to post to. Fields is a dictionary filled with the form fields and respective values to use when submitting the post. For example: {'url': 'https://mybucket.s3.amazonaws.com 'fields': {'acl': 'public-read', 'key': 'mykey', 'signature': 'mysignature', 'policy': 'mybase64 encoded policy'} } """ if fields is None: fields = {} if conditions is None: conditions = [] if region_name is None: region_name = self._request_signer.region_name # Create the policy for the post. policy = {} # Create an expiration date for the policy datetime_now = datetime.datetime.utcnow() expire_date = datetime_now + datetime.timedelta(seconds=expires_in) policy['expiration'] = expire_date.strftime(botocore.auth.ISO8601) # Append all of the conditions that the user supplied. policy['conditions'] = [] for condition in conditions: policy['conditions'].append(condition) # Obtain the appropriate signer. query_prefix = '-presign-post' signature_version = self._request_signer.signature_version if not signature_version.endswith(query_prefix): signature_version += query_prefix kwargs = {'signing_name': self._request_signer.signing_name, 'region_name': region_name, 'signature_version': signature_version} signature_type = signature_version.split('-', 1)[0] try: auth = self._request_signer.get_auth(**kwargs) except UnknownSignatureVersionError: raise UnsupportedSignatureVersionError( signature_version=signature_type) # Store the policy and the fields in the request for signing request = create_request_object(request_dict) request.context['s3-presign-post-fields'] = fields request.context['s3-presign-post-policy'] = policy auth.add_auth(request) # Fix s3 host for s3 sigv2 bucket names fix_s3_host(request, signature_type, region_name) # Return the url and the fields for th form to post. return {'url': request.url, 'fields': fields}
def authenticate_presign_url_signv4(method, path, headers, data, url, query_params, request_dict): is_presign_valid = False for port in PORT_REPLACEMENT: match = re.match(HOST_COMBINATION_REGEX, urlparse.urlparse(request_dict["url"]).netloc) if match and match.group(2): request_dict["url"] = request_dict["url"].replace("%s" % match.group(2), "%s" % port) else: request_dict["url"] = "%s:%s" % (request_dict["url"], port) # Calculating Signature aws_request = create_request_object(request_dict) ReadOnlyCredentials = namedtuple( "ReadOnlyCredentials", ["access_key", "secret_key", "token"] ) credentials = ReadOnlyCredentials( TEST_AWS_ACCESS_KEY_ID, TEST_AWS_SECRET_ACCESS_KEY, query_params.get("X-Amz-Security-Token", None), ) region = query_params["X-Amz-Credential"][0].split("/")[2] signer = S3SigV4QueryAuth( credentials, "s3", region, expires=int(query_params["X-Amz-Expires"][0]) ) signature = signer.add_auth(aws_request, query_params["X-Amz-Date"][0]) expiration_time = datetime.datetime.strptime( query_params["X-Amz-Date"][0], "%Y%m%dT%H%M%SZ" ) + datetime.timedelta(seconds=int(query_params["X-Amz-Expires"][0])) expiration_time = expiration_time.replace(tzinfo=datetime.timezone.utc) # Comparing the signature in url with signature we calculated query_sig = urlparse.unquote(query_params["X-Amz-Signature"][0]) if query_sig == signature: is_presign_valid = True break # Comparing the signature in url with signature we calculated if config.S3_SKIP_SIGNATURE_VALIDATION: if not is_presign_valid: LOGGER.warning( "Signatures do not match, but not raising an error, as S3_SKIP_SIGNATURE_VALIDATION=1" ) signature = query_sig is_presign_valid = True if not is_presign_valid: return requests_error_response_xml_signature_calculation( code=403, code_string="SignatureDoesNotMatch", aws_access_token=TEST_AWS_ACCESS_KEY_ID, signature=signature, message="The request signature we calculated does not match the signature you provided. \ Check your key and signing method.", ) # Checking whether the url is expired or not if is_expired(expiration_time): if config.S3_SKIP_SIGNATURE_VALIDATION: LOGGER.warning( "Signature is expired, but not raising an error, as S3_SKIP_SIGNATURE_VALIDATION=1" ) else: return requests_error_response_xml_signature_calculation( code=403, code_string="AccessDenied", message="Request has expired", expires=query_params["X-Amz-Expires"][0], )
def generate_presigned_post(self, request_dict, fields=None, conditions=None, expires_in=3600, region_name=None): """Generates the url and the form fields used for a presigned s3 post :type request_dict: dict :param request_dict: The prepared request dictionary returned by ``botocore.awsrequest.prepare_request_dict()`` :type fields: dict :param fields: A dictionary of prefilled form fields to build on top of. :type conditions: list :param conditions: A list of conditions to include in the policy. Each element can be either a list or a structure. For example: [ {"acl": "public-read"}, {"bucket": "mybucket"}, ["starts-with", "$key", "mykey"] ] :type expires_in: int :param expires_in: The number of seconds the presigned post is valid for. :type region_name: string :param region_name: The region name to sign the presigned post to. :rtype: dict :returns: A dictionary with two elements: ``url`` and ``fields``. Url is the url to post to. Fields is a dictionary filled with the form fields and respective values to use when submitting the post. For example: {'url': 'https://mybucket.s3.amazonaws.com 'fields': {'acl': 'public-read', 'key': 'mykey', 'signature': 'mysignature', 'policy': 'mybase64 encoded policy'} } """ if fields is None: fields = {} if conditions is None: conditions = [] if region_name is None: region_name = self._request_signer.region_name # Create the policy for the post. policy = {} # Create an expiration date for the policy datetime_now = datetime.datetime.utcnow() expire_date = datetime_now + datetime.timedelta(seconds=expires_in) policy['expiration'] = expire_date.strftime(botocore.auth.ISO8601) # Append all of the conditions that the user supplied. policy['conditions'] = [] for condition in conditions: policy['conditions'].append(condition) # Obtain the appropriate signer. query_prefix = '-presign-post' signature_version = self._request_signer.signature_version if not signature_version.endswith(query_prefix): signature_version += query_prefix kwargs = { 'signing_name': self._request_signer.signing_name, 'region_name': region_name, 'signature_version': signature_version } signature_type = signature_version.split('-', 1)[0] try: auth = self._request_signer.get_auth_instance(**kwargs) except UnknownSignatureVersionError: raise UnsupportedSignatureVersionError( signature_version=signature_type) # Store the policy and the fields in the request for signing request = create_request_object(request_dict) request.context['s3-presign-post-fields'] = fields request.context['s3-presign-post-policy'] = policy auth.add_auth(request) # Fix s3 host for s3 sigv2 bucket names fix_s3_host(request, signature_type, region_name) # Return the url and the fields for th form to post. return {'url': request.url, 'fields': fields}
def generate_presigned_post(self, request_dict, fields=None, conditions=None, expires_in=3600, region_name=None): """Generates the url and the form fields used for a presigned s3 post :type request_dict: dict :param request_dict: The prepared request dictionary returned by ``botocore.awsrequest.prepare_request_dict()`` :type fields: dict :param fields: A dictionary of prefilled form fields to build on top of. :type conditions: list :param conditions: A list of conditions to include in the policy. Each element can be either a list or a structure. For example: [ {"acl": "public-read"}, {"bucket": "mybucket"}, ["starts-with", "$key", "mykey"] ] :type expires_in: int :param expires_in: The number of seconds the presigned post is valid for. :type region_name: string :param region_name: The region name to sign the presigned post to. :rtype: dict :returns: A dictionary with two elements: ``url`` and ``fields``. Url is the url to post to. Fields is a dictionary filled with the form fields and respective values to use when submitting the post. For example: {'url': 'https://mybucket.s3.amazonaws.com 'fields': {'acl': 'public-read', 'key': 'mykey', 'signature': 'mysignature', 'policy': 'mybase64 encoded policy'} } """ if fields is None: fields = {} if conditions is None: conditions = [] # Create the policy for the post. policy = {} # Create an expiration date for the policy datetime_now = datetime.datetime.utcnow() expire_date = datetime_now + datetime.timedelta(seconds=expires_in) policy['expiration'] = expire_date.strftime(botocore.auth.ISO8601) # Append all of the conditions that the user supplied. policy['conditions'] = [] for condition in conditions: policy['conditions'].append(condition) # Store the policy and the fields in the request for signing request = create_request_object(request_dict) request.context['s3-presign-post-fields'] = fields request.context['s3-presign-post-policy'] = policy self._request_signer.sign('PutObject', request, region_name, 'presign-post') # Return the url and the fields for th form to post. return {'url': request.url, 'fields': fields}
def generate_presigned_post(self, request_dict, fields=None, conditions=None, expires_in=3600, region_name=None): """Generates the url and the form fields used for a presigned s3 post :type request_dict: dict :param request_dict: The prepared request dictionary returned by ``botocore.awsrequest.prepare_request_dict()`` :type fields: dict :param fields: A dictionary of prefilled form fields to build on top of. :type conditions: list :param conditions: A list of conditions to include in the policy. Each element can be either a list or a structure. For example: [ {"acl": "public-read"}, {"bucket": "mybucket"}, ["starts-with", "$key", "mykey"] ] :type expires_in: int :param expires_in: The number of seconds the presigned post is valid for. :type region_name: string :param region_name: The region name to sign the presigned post to. :rtype: dict :returns: A dictionary with two elements: ``url`` and ``fields``. Url is the url to post to. Fields is a dictionary filled with the form fields and respective values to use when submitting the post. For example: {'url': 'https://mybucket.s3.amazonaws.com 'fields': {'acl': 'public-read', 'key': 'mykey', 'signature': 'mysignature', 'policy': 'mybase64 encoded policy'} } """ if fields is None: fields = {} if conditions is None: conditions = [] # Create the policy for the post. policy = {} # Create an expiration date for the policy datetime_now = datetime.datetime.utcnow() expire_date = datetime_now + datetime.timedelta(seconds=expires_in) policy['expiration'] = expire_date.strftime(botocore.auth.ISO8601) # Append all of the conditions that the user supplied. policy['conditions'] = [] for condition in conditions: policy['conditions'].append(condition) # Store the policy and the fields in the request for signing request = create_request_object(request_dict) request.context['s3-presign-post-fields'] = fields request.context['s3-presign-post-policy'] = policy self._request_signer.sign( 'PutObject', request, region_name, 'presign-post') # Return the url and the fields for th form to post. return {'url': request.url, 'fields': fields}