-
Notifications
You must be signed in to change notification settings - Fork 167
Description
The Python Client for Google Cloud Storage API returns a double slash after the hostname for signed URLs when a bucket bound hostname is given.
Double slashes may work just fine for LBs that have the feature of merging slashes but that is not always the case, a GCP classic LB for instance will not merge them, causing Cloud Storage to respond with a mismatch signature when the signed URL is used.
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message>
<StringToSign>GOOG4-RSA-SHA256 20220921T204802Z 20220921/auto/storage/goog4_request 8f4c42e1514feacce7dc33b3b0b70932c88a8c26517f9b9d80c73530475e79be</StringToSign>
<CanonicalRequest>GET //0/62d5e5a9928b41d409618c91.tgz X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=truncated%2F20220921%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220921T204802Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host host:bucket-bound-hostname host UNSIGNED-PAYLOAD</CanonicalRequest>
</Error>
Example of a bad output URL:
https://{{bucket-bound-url}}**//**22604/630d15000fa2842ad668e51b.zip?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=truncated%2F20220829%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220829T223637Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host&X-Goog-Signature=8b708edd22c5f6636f21fb572a62a5a8e8d6...truncated
Expected URL:
https://{{bucket-bound-url}}**/**22604/630d15000fa2842ad668e51b.zip?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=truncated%2F20220829%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220829T223637Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host&X-Goog-Signature=8b708edd22c5f6636f21fb572a62a5a8e8d6...truncated
Environment details
- OS type and version: Any
- Python version:
3.10.0 - pip version:
21.3.1 google-cloud-storageversion:1.44.0
Steps to reproduce
Generate any signed URL providing a bucket bound hostname like below.
Code example
from google.cloud.storage import Client as GCSClient, Bucket
from datetime import timedelta
client = GCSClient(
project=credentials["project_id"], credentials=client_creds
)
bucket = client.bucket("bucket_name")
blob = bucket.blob("object_name")
url = blob.generate_signed_url(
version="v4",
expiration=timedelta(seconds=600),
method="GET",
bucket_bound_hostname="https://storage_bound_hostname",
)
print(url)