From 17980e243f4642d43b0f90b46462db7a5598ad5b Mon Sep 17 00:00:00 2001 From: djmailhot Date: Mon, 5 Mar 2018 11:02:48 -0800 Subject: [PATCH 01/11] CDN samples dir with snippet for signing urls Implements the Cloud Storage documentation on signing urls found at https://cloud.google.com/storage/docs/access-control/create-signed-urls-program --- cdn/snippets.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 cdn/snippets.py diff --git a/cdn/snippets.py b/cdn/snippets.py new file mode 100644 index 00000000000..8d0134331b7 --- /dev/null +++ b/cdn/snippets.py @@ -0,0 +1,75 @@ +"""This application demonstrates how to perform operations on data (content) +when using the Google Cloud CDN (Content Delivery Network). + +For more information, see the README.md under /cdn and the documentation +at https://cloud.google.com/cdn/docs. +""" + +import argparse +import base64 +import calendar +import datetime +import hashlib +import hmac +import time +import urlparse +import sys + +def sign_url(url, key_name, key, expiration_time): + """Gets the Signed URL string for the specified URL and configuration. + + Args: + url: The URL to sign. + key_name: Signed URL key name to use for the 'KeyName=' query parameter. + key: The 16-byte unencoded secret key value to use for signing. + expiration_time: expiration time expressed as a UTC datetime object. + + Returns: + Returns the Signed URL appended with the query parameters based on the + specified configuration. Roughly of the form: + {url}{separator}Expires={expiration}&KeyName={key_name}&Signature={signature} + + """ + stripped_url = url.strip() + parsed_url = urlparse.urlsplit(stripped_url) + query_params = urlparse.parse_qs(parsed_url.query, keep_blank_values=True) + epoch = datetime.datetime.utcfromtimestamp(0) + expiration_timestamp = (expiration_time - epoch).total_seconds() + + url_to_sign = '{url}{separator}Expires={expires}&KeyName={key_name}'.format( + url=stripped_url, + separator='&' if query_params else '?', + expires=expiration_timestamp, + key_name=key_name) + + signature = base64.urlsafe_b64encode( + hmac.new(key, url_to_sign, hashlib.sha1).digest()) + + return '{url}&Signature={signature}'.format( + url=url_to_sign, signature=signature) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + subparsers = parser.add_subparsers(dest='command') + subparsers.add_parser('sign-url', help=sign_url.__doc__) + + sign_url_parser = subparsers.add_parser('sign-url', help=sign_url.__doc__) + sign_url_parser.add_argument('url') + sign_url_parser.add_argument('key_name') + sign_url_parser.add_argument('key') + sign_url_parser.add_argument('expiration_time') + + args = parser.parse_args() + + args.url = "http://35.186.234.33/index.html" + args.key_name = "my-key" + args.key = base64.urlsafe_b64decode("nZtRohdNF9m3cKM24IcK4w==") + args.expiration_time = datetime.datetime.utcnow().replace(year=2020) + + if args.command == 'sign-url': + print sign_url(args.url, args.key_name, args.key, args.expiration_time) + From 4a7dc15e327fc31e46e3002e4eda2afde63d03d0 Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Mon, 5 Mar 2018 10:49:19 -0800 Subject: [PATCH 02/11] Add CDN samples dir with snippet for signing urls --- cdn/snippets.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 cdn/snippets.py diff --git a/cdn/snippets.py b/cdn/snippets.py new file mode 100644 index 00000000000..8fe2ccadc17 --- /dev/null +++ b/cdn/snippets.py @@ -0,0 +1,76 @@ +"""This application demonstrates how to perform operations on data (content) +when using the Google Cloud CDN (Content Delivery Network). + +For more information, see the README.md under /cdn and the documentation +at https://cloud.google.com/cdn/docs. +""" + +import argparse +import base64 +import datetime +import hashlib +import hmac +import urlparse + +def sign_url(url, key_name, key, expiration_time): + """Gets the Signed URL string for the specified URL and configuration. + + Args: + url: The URL to sign. + key_name: Signed URL key name to use for the 'KeyName=' query parameter. + key: The 16-byte unencoded secret key value to use for signing. + expiration_time: expiration time expressed as a UTC datetime object. + + Returns: + Returns the Signed URL appended with the query parameters based on the + specified configuration. Roughly of the form: + {url}{separator}Expires={expiration}&KeyName={key_name}&Signature={signature} + + """ + stripped_url = url.strip() + parsed_url = urlparse.urlsplit(stripped_url) + query_params = urlparse.parse_qs(parsed_url.query, keep_blank_values=True) + epoch = datetime.datetime.utcfromtimestamp(0) + expiration_timestamp = (expiration_time - epoch).total_seconds() + + url_to_sign = '{url}{separator}Expires={expires}&KeyName={key_name}'.format( + url=stripped_url, + separator='&' if query_params else '?', + expires=expiration_timestamp, + key_name=key_name) + + signature = base64.urlsafe_b64encode( + hmac.new(key, url_to_sign, hashlib.sha1).digest()) + + return '{url}&Signature={signature}'.format( + url=url_to_sign, signature=signature) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + subparsers = parser.add_subparsers(dest='command') + subparsers.add_parser('sign-url', help=sign_url.__doc__) + + sign_url_parser = subparsers.add_parser('sign-url', help=sign_url.__doc__) + sign_url_parser.add_argument('url', + help="The URL to sign.") + sign_url_parser.add_argument('key_name', + help="Signed URL key name to use for the 'KeyName=' query parameter.") + sign_url_parser.add_argument('key', + help="The 16-byte unencoded secret key value to use for signing.") + sign_url_parser.add_argument('expiration_timestamp', + help="Expiration time expessed as seconds since the epoch.") + + args = parser.parse_args() + + args.url = "http://35.186.234.33/index.html" + args.key_name = "my-key" + args.key = base64.urlsafe_b64decode("nZtRohdNF9m3cKM24IcK4w==") + + if args.command == 'sign-url': + expiration_time = datetime.datetime.fromtimestamp(float(args.expiration_timestamp)) + print sign_url(args.url, args.key_name, args.key, expiration_time) + From 06b9d762e7b7d599f1aca2b8892c97bb9e6a94bf Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Mon, 5 Mar 2018 14:37:25 -0800 Subject: [PATCH 03/11] Fixup snippets to work properly, remove test code --- cdn/snippets.py | 70 +++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/cdn/snippets.py b/cdn/snippets.py index a3d464d410f..fc1276e65cd 100644 --- a/cdn/snippets.py +++ b/cdn/snippets.py @@ -1,5 +1,21 @@ +#!/usr/bin/env python +# +# Copyright 2017 Google, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """This application demonstrates how to perform operations on data (content) -when using the Google Cloud CDN (Content Delivery Network). +when using Google Cloud CDN (Content Delivery Network). For more information, see the README.md under /cdn and the documentation at https://cloud.google.com/cdn/docs. @@ -7,20 +23,20 @@ import argparse import base64 -<<<<<<< HEAD import datetime import hashlib import hmac import urlparse -def sign_url(url, key_name, key, expiration_time): +# [BEGIN sign_url] +def sign_url(url, key_name, decoded_base64_key, expiration_datetime): """Gets the Signed URL string for the specified URL and configuration. Args: url: The URL to sign. - key_name: Signed URL key name to use for the 'KeyName=' query parameter. - key: The 16-byte unencoded secret key value to use for signing. - expiration_time: expiration time expressed as a UTC datetime object. + key_name: key name for the authorization secret key. + decoded_base64_key: base64 decoded secret key value to sign the url. + expiration_datetime: expiration time as a UTC datetime object. Returns: Returns the Signed URL appended with the query parameters based on the @@ -32,7 +48,7 @@ def sign_url(url, key_name, key, expiration_time): parsed_url = urlparse.urlsplit(stripped_url) query_params = urlparse.parse_qs(parsed_url.query, keep_blank_values=True) epoch = datetime.datetime.utcfromtimestamp(0) - expiration_timestamp = (expiration_time - epoch).total_seconds() + expiration_timestamp = int((expiration_datetime - epoch).total_seconds()) url_to_sign = '{url}{separator}Expires={expires}&KeyName={key_name}'.format( url=stripped_url, @@ -41,11 +57,11 @@ def sign_url(url, key_name, key, expiration_time): key_name=key_name) signature = base64.urlsafe_b64encode( - hmac.new(key, url_to_sign, hashlib.sha1).digest()) + hmac.new(decoded_base64_key, url_to_sign, hashlib.sha1).digest()) return '{url}&Signature={signature}'.format( url=url_to_sign, signature=signature) - +# [END sign_url] if __name__ == '__main__': parser = argparse.ArgumentParser( @@ -53,25 +69,27 @@ def sign_url(url, key_name, key, expiration_time): formatter_class=argparse.RawDescriptionHelpFormatter) subparsers = parser.add_subparsers(dest='command') - subparsers.add_parser('sign-url', help=sign_url.__doc__) - - sign_url_parser = subparsers.add_parser('sign-url', help=sign_url.__doc__) - sign_url_parser.add_argument('url', - help="The URL to sign.") - sign_url_parser.add_argument('key_name', - help="Signed URL key name to use for the 'KeyName=' query parameter.") - sign_url_parser.add_argument('key', - help="The 16-byte unencoded secret key value to use for signing.") - sign_url_parser.add_argument('expiration_timestamp', - help="Expiration time expessed as seconds since the epoch.") - args = parser.parse_args() + sign_url_parser = subparsers.add_parser( + 'sign-url', + help="Sign a URL to grant temporary authorized access.") + sign_url_parser.add_argument( + 'url', help='The URL to sign') + sign_url_parser.add_argument( + 'key_name', + help='Key name for the authorization secret key.') + sign_url_parser.add_argument( + 'encoded_base64_key', + help='The base64 encoded secret key value to use for signing.') + sign_url_parser.add_argument( + 'expiration_timestamp', + help='Expiration time expessed as seconds since the epoch.') - args.url = "http://35.186.234.33/index.html" - args.key_name = "my-key" - args.key = base64.urlsafe_b64decode("nZtRohdNF9m3cKM24IcK4w==") + args = parser.parse_args() if args.command == 'sign-url': - expiration_time = datetime.datetime.fromtimestamp(float(args.expiration_timestamp)) - print sign_url(args.url, args.key_name, args.key, expiration_time) + expiration_datetime = datetime.datetime.utcfromtimestamp( + float(args.expiration_timestamp)) + decoded_key = base64.urlsafe_b64decode(args.encoded_base64_key) + print(sign_url(args.url, args.key_name, decoded_key, expiration_datetime)) From 072012baed126e4ca51c96641682f26908e69a2e Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Mon, 5 Mar 2018 14:38:13 -0800 Subject: [PATCH 04/11] Add README.rst.in --- cdn/README.rst.in | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 cdn/README.rst.in diff --git a/cdn/README.rst.in b/cdn/README.rst.in new file mode 100644 index 00000000000..f9c47171edc --- /dev/null +++ b/cdn/README.rst.in @@ -0,0 +1,16 @@ +# Used to generate README.rst + +product: + name: Google Cloud CDN + short_name: Cloud CDN + url: https://cloud.google.com/cdn/docs + description: > + 'Google Cloud CDN'_ enables low-latency, low-cost content delivery using + Google's global network + +samples: + - name: Snippets + file: snippets.py + show_help: true + +folder: cdn From 8e3e8c74fa568922b6384ba86926e28b6631814f Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Wed, 7 Mar 2018 14:17:31 -0800 Subject: [PATCH 05/11] Remove argument pre-processing for cdn sign_url --- cdn/snippets.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/cdn/snippets.py b/cdn/snippets.py index fc1276e65cd..ab6f022059d 100644 --- a/cdn/snippets.py +++ b/cdn/snippets.py @@ -26,17 +26,22 @@ import datetime import hashlib import hmac -import urlparse + +# Python 2 & 3 compatibility +try: + from urllib.parse import urlsplit, parse_qs +except ImportError: + from urlparse import urlsplit, parse_qs # [BEGIN sign_url] -def sign_url(url, key_name, decoded_base64_key, expiration_datetime): +def sign_url(url, key_name, key, expiration_time): """Gets the Signed URL string for the specified URL and configuration. Args: - url: The URL to sign. - key_name: key name for the authorization secret key. - decoded_base64_key: base64 decoded secret key value to sign the url. - expiration_datetime: expiration time as a UTC datetime object. + url: URL to sign as a string. + key_name: name of the signing key as a string. + key: signing key as a urlsafe base64 encoded string. + expiration_time: expiration time as a UTC datetime object. Returns: Returns the Signed URL appended with the query parameters based on the @@ -45,10 +50,11 @@ def sign_url(url, key_name, decoded_base64_key, expiration_datetime): """ stripped_url = url.strip() - parsed_url = urlparse.urlsplit(stripped_url) - query_params = urlparse.parse_qs(parsed_url.query, keep_blank_values=True) + parsed_url = urlsplit(stripped_url) + query_params = parse_qs(parsed_url.query, keep_blank_values=True) epoch = datetime.datetime.utcfromtimestamp(0) - expiration_timestamp = int((expiration_datetime - epoch).total_seconds()) + expiration_timestamp = int((expiration_time - epoch).total_seconds()) + decoded_key = base64.urlsafe_b64decode(key) url_to_sign = '{url}{separator}Expires={expires}&KeyName={key_name}'.format( url=stripped_url, @@ -57,7 +63,7 @@ def sign_url(url, key_name, decoded_base64_key, expiration_datetime): key_name=key_name) signature = base64.urlsafe_b64encode( - hmac.new(decoded_base64_key, url_to_sign, hashlib.sha1).digest()) + hmac.new(decoded_key, url_to_sign, hashlib.sha1).digest()) return '{url}&Signature={signature}'.format( url=url_to_sign, signature=signature) @@ -79,17 +85,15 @@ def sign_url(url, key_name, decoded_base64_key, expiration_datetime): 'key_name', help='Key name for the authorization secret key.') sign_url_parser.add_argument( - 'encoded_base64_key', + 'key', help='The base64 encoded secret key value to use for signing.') sign_url_parser.add_argument( - 'expiration_timestamp', + 'expiration_time', + type=lambda d: datetime.datetime.utcfromtimestamp(float(d)), help='Expiration time expessed as seconds since the epoch.') args = parser.parse_args() if args.command == 'sign-url': - expiration_datetime = datetime.datetime.utcfromtimestamp( - float(args.expiration_timestamp)) - decoded_key = base64.urlsafe_b64decode(args.encoded_base64_key) - print(sign_url(args.url, args.key_name, decoded_key, expiration_datetime)) + print(sign_url(args.url, args.key_name, args.key, args.expiration_time)) From 6c417f21ce147d306b85d7d720cd78c968e394ed Mon Sep 17 00:00:00 2001 From: Jon Wayne Parrott Date: Wed, 7 Mar 2018 14:32:44 -0800 Subject: [PATCH 06/11] Fix some python 2/3 compatibility issues Change-Id: Ib5b67ddcc761aae2731cd6c7d74ba4bd3ff59f5d --- cdn/snippets.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/cdn/snippets.py b/cdn/snippets.py index ab6f022059d..62f1335e6f8 100644 --- a/cdn/snippets.py +++ b/cdn/snippets.py @@ -27,11 +27,8 @@ import hashlib import hmac -# Python 2 & 3 compatibility -try: - from urllib.parse import urlsplit, parse_qs -except ImportError: - from urlparse import urlsplit, parse_qs +from six.moves import urllib + # [BEGIN sign_url] def sign_url(url, key_name, key, expiration_time): @@ -50,25 +47,32 @@ def sign_url(url, key_name, key, expiration_time): """ stripped_url = url.strip() - parsed_url = urlsplit(stripped_url) - query_params = parse_qs(parsed_url.query, keep_blank_values=True) + parsed_url = urllib.parse.urlsplit(stripped_url) + query_params = urllib.parse.parse_qs( + parsed_url.query, keep_blank_values=True) epoch = datetime.datetime.utcfromtimestamp(0) expiration_timestamp = int((expiration_time - epoch).total_seconds()) decoded_key = base64.urlsafe_b64decode(key) - url_to_sign = '{url}{separator}Expires={expires}&KeyName={key_name}'.format( + url_pattern = u'{url}{separator}Expires={expires}&KeyName={key_name}' + + url_to_sign = url_pattern.format( url=stripped_url, separator='&' if query_params else '?', expires=expiration_timestamp, key_name=key_name) - signature = base64.urlsafe_b64encode( - hmac.new(decoded_key, url_to_sign, hashlib.sha1).digest()) + digest = hmac.new( + decoded_key, url_to_sign.encode('utf-8'), hashlib.sha1).digest() + signature = base64.urlsafe_b64encode(digest) - return '{url}&Signature={signature}'.format( + signed_url = u'{url}&Signature={signature}'.format( url=url_to_sign, signature=signature) + + print(signed_url) # [END sign_url] + if __name__ == '__main__': parser = argparse.ArgumentParser( description=__doc__, @@ -95,5 +99,4 @@ def sign_url(url, key_name, key, expiration_time): args = parser.parse_args() if args.command == 'sign-url': - print(sign_url(args.url, args.key_name, args.key, args.expiration_time)) - + sign_url(args.url, args.key_name, args.key, args.expiration_time) From 2094d01f7102bce0bcc926eb33464f0b4b74af78 Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Wed, 7 Mar 2018 15:16:18 -0800 Subject: [PATCH 07/11] Test for CDN sign_url code sample --- cdn/snippets_test.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 cdn/snippets_test.py diff --git a/cdn/snippets_test.py b/cdn/snippets_test.py new file mode 100644 index 00000000000..05367c75524 --- /dev/null +++ b/cdn/snippets_test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# +# Copyright 2017 Google, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for snippets.""" + +import datetime + +import snippets + + +def test_sign_url(capsys): + + snippets.sign_url( + 'http://www.example.com/', 'my-key', 'd9hoKw==', datetime.datetime.max) + + out, _ = capsys.readouterr() + + assert out == ('http://www.example.com/?Expires=253402300800&' + 'KeyName=my-key&Signature=w5FrhnkzGIrEabLP9HNxETNmS9U=') From bd333aeaa28677180dd364941ef967d69f956bcb Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Wed, 7 Mar 2018 15:17:53 -0800 Subject: [PATCH 08/11] Update sign_url sample with vebose var names --- cdn/snippets.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/cdn/snippets.py b/cdn/snippets.py index 62f1335e6f8..ff48ed097b0 100644 --- a/cdn/snippets.py +++ b/cdn/snippets.py @@ -31,13 +31,13 @@ # [BEGIN sign_url] -def sign_url(url, key_name, key, expiration_time): +def sign_url(url, key_name, base64_key, expiration_time): """Gets the Signed URL string for the specified URL and configuration. Args: url: URL to sign as a string. key_name: name of the signing key as a string. - key: signing key as a urlsafe base64 encoded string. + base64_key: signing key as a base64 encoded string. expiration_time: expiration time as a UTC datetime object. Returns: @@ -52,7 +52,7 @@ def sign_url(url, key_name, key, expiration_time): parsed_url.query, keep_blank_values=True) epoch = datetime.datetime.utcfromtimestamp(0) expiration_timestamp = int((expiration_time - epoch).total_seconds()) - decoded_key = base64.urlsafe_b64decode(key) + decoded_key = base64.urlsafe_b64decode(base64_key) url_pattern = u'{url}{separator}Expires={expires}&KeyName={key_name}' @@ -84,13 +84,13 @@ def sign_url(url, key_name, key, expiration_time): 'sign-url', help="Sign a URL to grant temporary authorized access.") sign_url_parser.add_argument( - 'url', help='The URL to sign') + 'url', help='The URL to sign.') sign_url_parser.add_argument( 'key_name', - help='Key name for the authorization secret key.') + help='Key name for the signing key.') sign_url_parser.add_argument( - 'key', - help='The base64 encoded secret key value to use for signing.') + 'base64_key', + help='The base64 encoded signing key.') sign_url_parser.add_argument( 'expiration_time', type=lambda d: datetime.datetime.utcfromtimestamp(float(d)), @@ -99,4 +99,5 @@ def sign_url(url, key_name, key, expiration_time): args = parser.parse_args() if args.command == 'sign-url': - sign_url(args.url, args.key_name, args.key, args.expiration_time) + sign_url( + args.url, args.key_name, args.base64_key, args.expiration_time) From 2adb16dd9084fe3144875530b67b82b1983c1194 Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Wed, 7 Mar 2018 17:02:34 -0800 Subject: [PATCH 09/11] Add README.rst and requirements.txt for cdn/ --- cdn/README.rst | 55 ++++++++++++++++++++++++++++++++++++++++++++ cdn/requirements.txt | 1 + 2 files changed, 56 insertions(+) create mode 100644 cdn/README.rst create mode 100644 cdn/requirements.txt diff --git a/cdn/README.rst b/cdn/README.rst new file mode 100644 index 00000000000..18b522dc360 --- /dev/null +++ b/cdn/README.rst @@ -0,0 +1,55 @@ +.. This file is automatically generated. Do not edit this file directly. + +Google Cloud CDN Python Samples +=============================================================================== + +.. image:: https://gstatic.com/cloudssh/images/open-btn.png + :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=cdn/README.rst + + +This directory contains samples for Google Cloud CDN. 'Google Cloud CDN'_ enables low-latency, low-cost content delivery using Google's global network + + + + +.. _Google Cloud CDN: https://cloud.google.com/cdn/docs + + +Samples +------------------------------------------------------------------------------- + +Snippets ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. image:: https://gstatic.com/cloudssh/images/open-btn.png + :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=cdn/snippets.py;cdn/README.rst + + + + +To run this sample: + +.. code-block:: bash + + $ python snippets.py + + usage: snippets.py [-h] {sign-url} ... + + This application demonstrates how to perform operations on data (content) + when using Google Cloud CDN (Content Delivery Network). + + For more information, see the README.md under /cdn and the documentation + at https://cloud.google.com/cdn/docs. + + positional arguments: + {sign-url} + sign-url Sign a URL to grant temporary authorized access. + + optional arguments: + -h, --help show this help message and exit + + + + + +.. _Google Cloud SDK: https://cloud.google.com/sdk/ \ No newline at end of file diff --git a/cdn/requirements.txt b/cdn/requirements.txt new file mode 100644 index 00000000000..ffe2fce4989 --- /dev/null +++ b/cdn/requirements.txt @@ -0,0 +1 @@ +six From 7ef411d69bb6f49450f29114a937205bb9cd707b Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Wed, 7 Mar 2018 17:09:36 -0800 Subject: [PATCH 10/11] Update cdn sign_url tests, fixed encoding issues --- cdn/snippets.py | 6 ++---- cdn/snippets_test.py | 29 +++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/cdn/snippets.py b/cdn/snippets.py index ff48ed097b0..753957d578e 100644 --- a/cdn/snippets.py +++ b/cdn/snippets.py @@ -42,9 +42,7 @@ def sign_url(url, key_name, base64_key, expiration_time): Returns: Returns the Signed URL appended with the query parameters based on the - specified configuration. Roughly of the form: - {url}{separator}Expires={expiration}&KeyName={key_name}&Signature={signature} - + specified configuration. """ stripped_url = url.strip() parsed_url = urllib.parse.urlsplit(stripped_url) @@ -64,7 +62,7 @@ def sign_url(url, key_name, base64_key, expiration_time): digest = hmac.new( decoded_key, url_to_sign.encode('utf-8'), hashlib.sha1).digest() - signature = base64.urlsafe_b64encode(digest) + signature = base64.urlsafe_b64encode(digest).decode('utf-8') signed_url = u'{url}&Signature={signature}'.format( url=url_to_sign, signature=signature) diff --git a/cdn/snippets_test.py b/cdn/snippets_test.py index 05367c75524..ce2f7efcb01 100644 --- a/cdn/snippets_test.py +++ b/cdn/snippets_test.py @@ -22,11 +22,32 @@ def test_sign_url(capsys): - snippets.sign_url( - 'http://www.example.com/', 'my-key', 'd9hoKw==', datetime.datetime.max) + 'http://35.186.234.33/index.html', + 'my-key', + 'nZtRohdNF9m3cKM24IcK4w==', + datetime.datetime.utcfromtimestamp(1549751401)) + snippets.sign_url( + 'http://www.example.com/', + 'my-key', + 'nZtRohdNF9m3cKM24IcK4w==', + datetime.datetime.utcfromtimestamp(1549751401)) + snippets.sign_url( + 'http://www.example.com/some/path?some=query&another=param', + 'my-key', + 'nZtRohdNF9m3cKM24IcK4w==', + datetime.datetime.utcfromtimestamp(1549751401)) out, _ = capsys.readouterr() - assert out == ('http://www.example.com/?Expires=253402300800&' - 'KeyName=my-key&Signature=w5FrhnkzGIrEabLP9HNxETNmS9U=') + results = out.splitlines() + print(results) + assert results[0] == ( + 'http://35.186.234.33/index.html?Expires=1549751401&KeyName=my-key&' + 'Signature=CRFqQnVfFyiUyR63OQf-HRUpIwc=') + assert results[1] == ( + 'http://www.example.com/?Expires=1549751401&KeyName=my-key&' + 'Signature=OqDUFfHpN5Vxga6r80bhsgxKves=') + assert results[2] == ( + 'http://www.example.com/some/path?some=query&another=param&Expires=' + '1549751401&KeyName=my-key&Signature=9Q9TCxSju8-W5nUkk5CuTrun2_o=') From 06d56064d9fac8ef9389217fa12bd7c28c1f0788 Mon Sep 17 00:00:00 2001 From: David Mailhot Date: Wed, 7 Mar 2018 17:11:34 -0800 Subject: [PATCH 11/11] Remove print from cdn/ tests --- cdn/snippets_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cdn/snippets_test.py b/cdn/snippets_test.py index ce2f7efcb01..245daea13cd 100644 --- a/cdn/snippets_test.py +++ b/cdn/snippets_test.py @@ -41,7 +41,6 @@ def test_sign_url(capsys): out, _ = capsys.readouterr() results = out.splitlines() - print(results) assert results[0] == ( 'http://35.186.234.33/index.html?Expires=1549751401&KeyName=my-key&' 'Signature=CRFqQnVfFyiUyR63OQf-HRUpIwc=')