-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Storage: add support for V4 signed URLs #7460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 34 commits
1d2d7f9
cca6312
6a6566b
9a25e9a
7ea200a
98b7e45
78d7de5
188d0a3
31dade9
5c114d6
01e2cd9
9113cdd
ba065a1
c39ac66
8b94be4
943e273
0c9c812
a78605d
5a6d44c
9833d68
c860d51
87aa6b6
e08ad30
db05933
dada493
de892c6
eae12c5
dc7bd12
c52e2db
2c5759e
7617b4f
d33c68e
c37e77a
2d04844
ccccaed
3a583a4
8f2e13f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,7 +54,8 @@ | |
| from google.api_core.iam import Policy | ||
| from google.cloud.storage._helpers import _PropertyMixin | ||
| from google.cloud.storage._helpers import _scalar_property | ||
| from google.cloud.storage._signing import generate_signed_url | ||
| from google.cloud.storage._signing import generate_signed_url_v2 | ||
| from google.cloud.storage._signing import generate_signed_url_v4 | ||
| from google.cloud.storage.acl import ACL | ||
| from google.cloud.storage.acl import ObjectACL | ||
|
|
||
|
|
@@ -96,6 +97,12 @@ | |
| _READ_LESS_THAN_SIZE = ( | ||
| "Size {:d} was specified but the file-like object only had " "{:d} bytes remaining." | ||
| ) | ||
| _SIGNED_URL_V2_DEFAULT_MESSAGE = ( | ||
| "You have generated a signed URL using the default v2 signing " | ||
| "implementation. In the future, this will default to v4. " | ||
| "You may experience breaking changes if you use longer than 7 day " | ||
| "expiration times with v4. To opt-in to the behavior specify version='v2'." | ||
| ) | ||
|
|
||
| _DEFAULT_CHUNKSIZE = 104857600 # 1024 * 1024 B * 100 = 100 MB | ||
| _MAX_MULTIPART_SIZE = 8388608 # 8 MB | ||
|
|
@@ -302,14 +309,19 @@ def public_url(self): | |
|
|
||
| def generate_signed_url( | ||
| self, | ||
| expiration, | ||
| expiration=None, | ||
| api_access_endpoint=_API_ACCESS_ENDPOINT, | ||
| method="GET", | ||
| content_md5=None, | ||
| content_type=None, | ||
| generation=None, | ||
| response_disposition=None, | ||
| response_type=None, | ||
| generation=None, | ||
| headers=None, | ||
| query_parameters=None, | ||
| client=None, | ||
| credentials=None, | ||
| version=None, | ||
| ): | ||
| """Generates a signed URL for this blob. | ||
|
|
||
|
|
@@ -332,20 +344,23 @@ def generate_signed_url( | |
| accessible blobs, but don't want to require users to explicitly | ||
| log in. | ||
|
|
||
| :type expiration: int, long, datetime.datetime, datetime.timedelta | ||
| :param expiration: When the signed URL should expire. | ||
| :type expiration: Union[Integer, datetime.datetime, datetime.timedelta] | ||
| :param expiration: Point in time when the signed URL should expire. | ||
|
|
||
| :type api_access_endpoint: str | ||
| :param api_access_endpoint: Optional URI base. | ||
|
|
||
| :type method: str | ||
| :param method: The HTTP verb that will be used when requesting the URL. | ||
|
|
||
| :type content_md5: str | ||
| :param content_md5: (Optional) The MD5 hash of the object referenced by | ||
| ``resource``. | ||
|
|
||
| :type content_type: str | ||
| :param content_type: (Optional) The content type of the object | ||
| referenced by ``resource``. | ||
|
|
||
| :type generation: str | ||
| :param generation: (Optional) A value that indicates which generation | ||
| of the resource to fetch. | ||
|
|
||
| :type response_disposition: str | ||
| :param response_disposition: (Optional) Content disposition of | ||
| responses to requests for the signed URL. | ||
|
|
@@ -359,6 +374,24 @@ def generate_signed_url( | |
| for the signed URL. Used to over-ride the content | ||
| type of the underlying blob/object. | ||
|
|
||
| :type generation: str | ||
| :param generation: (Optional) A value that indicates which generation | ||
| of the resource to fetch. | ||
|
|
||
| :type headers: dict | ||
| :param headers: | ||
| (Optional) Additional HTTP headers to be included as part of the | ||
| signed URLs. See: | ||
| https://cloud.google.com/storage/docs/xml-api/reference-headers | ||
| Requests using the signed URL *must* pass the specified header | ||
| (name and value) with each request for the URL. | ||
|
|
||
| :type query_parameters: dict | ||
| :param query_parameters: | ||
| (Optional) Additional query paramtersto be included as part of the | ||
| signed URLs. See: | ||
| https://cloud.google.com/storage/docs/xml-api/reference-headers#query | ||
|
|
||
| :type client: :class:`~google.cloud.storage.client.Client` or | ||
| ``NoneType`` | ||
| :param client: (Optional) The client to use. If not passed, falls back | ||
|
|
@@ -371,6 +404,11 @@ def generate_signed_url( | |
| the URL. Defaults to the credentials stored on the | ||
| client used. | ||
|
|
||
| :type version: str | ||
| :param version: (Optional) The version of signed credential to create. | ||
| Must be one of 'v2' | 'v4'. | ||
|
|
||
| :raises: :exc:`ValueError` when version is invalid. | ||
| :raises: :exc:`TypeError` when expiration is not a valid type. | ||
| :raises: :exc:`AttributeError` if credentials is not an instance | ||
| of :class:`google.auth.credentials.Signing`. | ||
|
|
@@ -379,6 +417,11 @@ def generate_signed_url( | |
| :returns: A signed URL you can use to access the resource | ||
| until expiration. | ||
| """ | ||
| if version is None: | ||
| version = "v2" | ||
| elif version not in ("v2", "v4"): | ||
| raise ValueError("'version' must be either 'v2' or 'v4'") | ||
|
|
||
| resource = "/{bucket_name}/{quoted_name}".format( | ||
| bucket_name=self.bucket.name, quoted_name=quote(self.name.encode("utf-8")) | ||
| ) | ||
|
|
@@ -387,16 +430,24 @@ def generate_signed_url( | |
| client = self._require_client(client) | ||
| credentials = client._credentials | ||
|
|
||
| return generate_signed_url( | ||
| if version == "v2": | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tseaver could you add a warning as log output that V2 will change to V4 in the future:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| helper = generate_signed_url_v2 | ||
| else: | ||
| helper = generate_signed_url_v4 | ||
|
|
||
| return helper( | ||
| credentials, | ||
| resource=resource, | ||
| api_access_endpoint=_API_ACCESS_ENDPOINT, | ||
| expiration=expiration, | ||
| api_access_endpoint=api_access_endpoint, | ||
| method=method.upper(), | ||
| content_md5=content_md5, | ||
| content_type=content_type, | ||
| response_type=response_type, | ||
| response_disposition=response_disposition, | ||
| generation=generation, | ||
| headers=headers, | ||
| query_parameters=query_parameters, | ||
| ) | ||
|
|
||
| def exists(self, client=None): | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.