Skip to content

Commit

Permalink
Support for specifying custom presign request date
Browse files Browse the repository at this point in the history
This allows the request date used for presigning the request to be
configurable.
  • Loading branch information
cheungpat committed Apr 13, 2018
1 parent df3c7cd commit 05df7a9
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 10 deletions.
21 changes: 17 additions & 4 deletions minio/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1227,7 +1227,8 @@ def presigned_url(self, method,
bucket_name,
object_name,
expires=timedelta(days=7),
response_headers=None):
response_headers=None,
request_date=None):
"""
Presigns a method on an object and provides a url
Expand All @@ -1247,6 +1248,9 @@ def presigned_url(self, method,
:params response_headers: Optional response_headers argument to
specify response fields like date, size,
type of file, data about server, etc.
:params request_date: Optional request_date argument to
specify a different request date. Default is
current date.
:return: Presigned put object url.
"""
is_valid_bucket_name(bucket_name)
Expand All @@ -1269,11 +1273,13 @@ def presigned_url(self, method,
self._secret_key,
region=region,
expires=int(expires.total_seconds()),
response_headers=response_headers)
response_headers=response_headers,
request_date=request_date)

def presigned_get_object(self, bucket_name, object_name,
expires=timedelta(days=7),
response_headers=None):
response_headers=None,
request_date=None):
"""
Presigns a get object request and provides a url
Expand All @@ -1290,13 +1296,20 @@ def presigned_get_object(self, bucket_name, object_name,
:param object_name: Object for which presigned url is generated.
:param expires: Optional expires argument to specify timedelta.
Defaults to 7days.
:params response_headers: Optional response_headers argument to
specify response fields like date, size,
type of file, data about server, etc.
:params request_date: Optional request_date argument to
specify a different request date. Default is
current date.
:return: Presigned url.
"""
return self.presigned_url('GET',
bucket_name,
object_name,
expires,
response_headers=response_headers)
response_headers=response_headers,
request_date=request_date)

def presigned_put_object(self, bucket_name, object_name,
expires=timedelta(days=7)):
Expand Down
18 changes: 12 additions & 6 deletions minio/signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ def post_presign_signature(date, region, secret_key, policy_str):


def presign_v4(method, url, access_key, secret_key, region=None,
headers=None, expires=None, response_headers=None):
headers=None, expires=None, response_headers=None,
request_date=None):
"""
Calculates signature version '4' for regular presigned URLs.
Expand All @@ -71,6 +72,8 @@ def presign_v4(method, url, access_key, secret_key, region=None,
:param headers: any additional HTTP request headers to
be presigned, it is optional.
:param expires: final expiration of the generated URL. Maximum is 7days.
:param response_headers: Specify additional query string parameters.
:param request_date: the date of the request.
"""

# Validate input arguments.
Expand All @@ -86,19 +89,22 @@ def presign_v4(method, url, access_key, secret_key, region=None,
if expires is None:
expires = '604800'

if request_date is None:
request_date = datetime.utcnow()

parsed_url = urlsplit(url)
content_hash_hex = _UNSIGNED_PAYLOAD
host = parsed_url.netloc
headers['Host'] = host
date = datetime.utcnow()
iso8601Date = date.strftime("%Y%m%dT%H%M%SZ")
iso8601Date = request_date.strftime("%Y%m%dT%H%M%SZ")

headers_to_sign = headers
# Construct queries.
query = {}
query['X-Amz-Algorithm'] = _SIGN_V4_ALGORITHM
query['X-Amz-Credential'] = generate_credential_string(access_key,
date, region)
request_date,
region)
query['X-Amz-Date'] = iso8601Date
query['X-Amz-Expires'] = str(expires)
signed_headers = get_signed_headers(headers_to_sign)
Expand Down Expand Up @@ -134,9 +140,9 @@ def presign_v4(method, url, access_key, secret_key, region=None,
headers_to_sign,
signed_headers,
content_hash_hex)
string_to_sign = generate_string_to_sign(date, region,
string_to_sign = generate_string_to_sign(request_date, region,
canonical_request)
signing_key = generate_signing_key(date, region, secret_key)
signing_key = generate_signing_key(request_date, region, secret_key)
signature = hmac.new(signing_key, string_to_sign.encode('utf-8'),
hashlib.sha256).hexdigest()
new_parsed_url = urlsplit(new_url + "&X-Amz-Signature="+signature)
Expand Down

0 comments on commit 05df7a9

Please sign in to comment.