Skip to content

Commit

Permalink
Additional clean up and doc update
Browse files Browse the repository at this point in the history
  • Loading branch information
Yohannes-B committed Jul 20, 2024
1 parent 55e7a78 commit ac0d069
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 17 deletions.
2 changes: 2 additions & 0 deletions docs/backends/gcloud.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ you **MUST** use Cloud IAM sign function (SignBlob) to sign data and directly si

Luckily this can be worked around by passing `service_account_email` and `access_token` to the generate_signed_url function.
When both of those args are provided, generate_signed_url will use the IAM SignBlob API to sign the url and no private key file is needed.
In order to enable this, use setting `iam_blob_sign` and the optional `sa_email` (if providing a service account email different than the one attached
to GCP Environment).

Last resort you can still use the service account key file for authentication (not recommended by Google):

Expand Down
44 changes: 27 additions & 17 deletions storages/backends/gcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,7 @@ def get_default_settings(self):
@property
def client(self):
if self._client is None:
if self.project_id is None or self.credentials is None:
self.credentials, self.project_id = auth.default(
scopes=['https://www.googleapis.com/auth/cloud-platform']
)
self._client = Client(project=self.project_id, credentials=self.credentials)
if self.credentials and self.credentials.token_state != TokenState.FRESH:
self.credentials.refresh(requests.Request())
return self._client

@property
Expand Down Expand Up @@ -344,20 +338,36 @@ def url(self, name, parameters=None):
params = parameters or {}

if self.iam_sign_blob:
if not hasattr(self.credentials, "service_account_email") and not self.sa_email:
raise AttributeError(
"Sign Blob API requires service_account_email to be available "
"through ADC or setting `sa_email`"
)
if hasattr(self.credentials, "service_account_email"):
default_params["service_account_email"] = self.credentials.service_account_email
# sa_email has the final say of which service_account_email to be used for signing if provided
if self.sa_email:
default_params["service_account_email"] = self.sa_email
default_params["access_token"] = self.credentials.token
service_account_email, access_token = self._get_iam_sign_blob_params()
default_params["service_account_email"] = service_account_email
default_params["access_token"] = access_token

for key, value in default_params.items():
if value and key not in params:
params[key] = value

return blob.generate_signed_url(**params)

def _get_iam_sign_blob_params(self):
credentials, _ = auth.default(
scopes=['https://www.googleapis.com/auth/cloud-platform']
)
if credentials and credentials.token_state != TokenState.FRESH:
credentials.refresh(requests.Request())

try:
service_account_email = credentials.service_account_email
except AttributeError:
service_account_email = None

# sa_email has the final say of which service_account_email to be used for signing if provided
if self.sa_email:
service_account_email = self.sa_email

if not service_account_email:
raise AttributeError(
"Sign Blob API requires service_account_email to be available "
"through ADC or setting `sa_email`"
)

return service_account_email, credentials.token

0 comments on commit ac0d069

Please sign in to comment.