Skip to content

Instantly share code, notes, and snippets.

@jmatt
Created July 19, 2019 23:47
Show Gist options
  • Save jmatt/f18fc75a10423147565ec6b22832726d to your computer and use it in GitHub Desktop.
Save jmatt/f18fc75a10423147565ec6b22832726d to your computer and use it in GitHub Desktop.
GS presign source code.
import binascii
import collections
import datetime
import hashlib
import sys
from six.moves.urllib.parse import quote
from google.oauth2 import service_account
def generate_signed_url(service_account_file, bucket_name, object_name,
expiration, http_method='GET', query_parameters=None,
headers=None):
if expiration > 604800:
print('Expiration Time can\'t be longer than 604800 seconds (7 days).')
sys.exit(1)
escaped_object_name = quote(object_name, safe='')
canonical_uri = '/{}/{}'.format(bucket_name, escaped_object_name)
datetime_now = datetime.datetime.utcnow()
request_timestamp = datetime_now.strftime('%Y%m%dT%H%M%SZ')
datestamp = datetime_now.strftime('%Y%m%d')
google_credentials = service_account.Credentials.from_service_account_file(
service_account_file)
client_email = google_credentials.service_account_email
credential_scope = '{}/auto/storage/goog4_request'.format(datestamp)
credential = '{}/{}'.format(client_email, credential_scope)
if headers is None:
headers = dict()
headers['host'] = 'storage.googleapis.com'
canonical_headers = ''
ordered_headers = collections.OrderedDict(sorted(headers.items()))
for k, v in ordered_headers.items():
lower_k = str(k).lower()
strip_v = str(v).lower()
canonical_headers += '{}:{}\n'.format(lower_k, strip_v)
signed_headers = ''
for k, _ in ordered_headers.items():
lower_k = str(k).lower()
signed_headers += '{};'.format(lower_k)
signed_headers = signed_headers[:-1] # remove trailing ';'
if query_parameters is None:
query_parameters = dict()
query_parameters['X-Goog-Algorithm'] = 'GOOG4-RSA-SHA256'
query_parameters['X-Goog-Credential'] = credential
query_parameters['X-Goog-Date'] = request_timestamp
query_parameters['X-Goog-Expires'] = expiration
query_parameters['X-Goog-SignedHeaders'] = signed_headers
canonical_query_string = ''
ordered_query_parameters = collections.OrderedDict(
sorted(query_parameters.items()))
for k, v in ordered_query_parameters.items():
encoded_k = quote(str(k), safe='')
encoded_v = quote(str(v), safe='')
canonical_query_string += '{}={}&'.format(encoded_k, encoded_v)
canonical_query_string = canonical_query_string[:-1] # remove trailing ';'
canonical_request = '\n'.join([http_method,
canonical_uri,
canonical_query_string,
canonical_headers,
signed_headers,
'UNSIGNED-PAYLOAD'])
canonical_request_hash = hashlib.sha256(
canonical_request.encode()).hexdigest()
string_to_sign = '\n'.join(['GOOG4-RSA-SHA256',
request_timestamp,
credential_scope,
canonical_request_hash])
signature = binascii.hexlify(
google_credentials.signer.sign(string_to_sign)
).decode()
host_name = 'https://storage.googleapis.com'
signed_url = '{}{}?{}&X-Goog-Signature={}'.format(host_name, canonical_uri,
canonical_query_string,
signature)
return signed_url
@jmatt
Copy link
Author

jmatt commented Jul 19, 2019

In [36]: import datetime

In [37]: from gs.presign import generate_signed_url

In [38]: generate_signed_url(credential_file, "fly-me-ics-uploads", "testing2", int(datetime.timedelta(da
    ...: ys=1).total_seconds()), http_method="POST")
Out[38]: 'https://storage.googleapis.com/fly-me-ics-uploads/testing2?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=devops-jmatt%40fly-me-dev.iam.gserviceaccount.com%2F20190719%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190719T234500Z&X-Goog-Expires=86400&X-Goog-SignedHeaders=host&X-Goog-Signature=a43db25c4809eb613fa6eea3406e79259eb53a32510fcd8210a4124f569f471ad5ac0fc15b6274caf46ee32a954fe02134257705e65457a012b87075f448d390d59e592c5da1830fffbd8c0e99de280b3f1e2e2aa5f082beccde6301215f954666a3db5d2ce383ae06e6ba30166e7275fe6ae2b2a37b2c4014982145425ce145d2c2cd98b5c6e3c344989f018c2a331af56c74c05a993640b9fbc5f01bae33f07bad9e70da0a64157970d12d0b189ecd786e7f34f8301c1ef02b01c962372009e248931dbf3901f2db86f98b83c0f24b44a26d649a386ac166e061da07affb8a98005c5a410024719842195d6c74a57d76dba9a6a4038c0068ec2fb87ac2b8e9'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment