Closed
Description
Months ago, I solved an issue to a Stack overflow user by explaining how to generate a signed URL without a service account JSON fey file. I also release an article on this
Today, a comment of a user told me that is doesn't work. They open a new Stack Overflow question and in their question, there is the v4 mentioned.
I dug into the code and yes, the v2 and the v4 haven't the same behavior: the v4 check if the credential can generate a signed URL by itself, that implies the useless check later that allows to use Service Account Credential API, instead of the service account private key to generate the signature.
Environment details
- Linux (Cloud Function and Cloud Run)
- Python version:
python --version
3.7 and 3.8 google-cloud-storage
version: latest (1.35.0)
Steps to reproduce
- Working code on Cloud Run (for example) Replace YOUR_BUCKET by a valid bucket
import os
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def sign_url():
from google.cloud import storage
from datetime import datetime, timedelta
import google.auth
credentials, project_id = google.auth.default()
# Perform a refresh request to get the access token of the current credentials (Else, it's None)
from google.auth.transport import requests
r = requests.Request()
credentials.refresh(r)
client = storage.Client()
bucket = client.get_bucket('YOUR_BUCKET')
blob = bucket.get_blob('name.csv')
service_account_email = credentials.service_account_email
url = blob.generate_signed_url(service_account_email=service_account_email, access_token=credentials.token,version="v2", method="PUT",expiration=timedelta(minutes=120),content_type="application/octet-stream")
return url, 200
if __name__ == "__main__":
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
- Broken code on Cloud Run (for example) Replace YOUR_BUCKET by a valid bucket
import os
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def sign_url():
from google.cloud import storage
from datetime import datetime, timedelta
import google.auth
credentials, project_id = google.auth.default()
# Perform a refresh request to get the access token of the current credentials (Else, it's None)
from google.auth.transport import requests
r = requests.Request()
credentials.refresh(r)
client = storage.Client()
bucket = client.get_bucket('YOUR_BUCKET')
blob = bucket.get_blob('name.csv')
service_account_email = credentials.service_account_email
url = blob.generate_signed_url(service_account_email=service_account_email, access_token=credentials.token,version="v4", method="PUT",expiration=timedelta(minutes=120),content_type="application/octet-stream")
return url, 200
if __name__ == "__main__":
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
Only the version (v2/v4) has changed
Fix proposal is coming.