Skip to content

Refactor GS authentication to use default credentials #514

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Fixed issue with GS credentials, using default auth enables a wider set of authentication methods in GS (Issue [#390](https://github.com/drivendataorg/cloudpathlib/issues/390), PR [#514](https://github.com/drivendataorg/cloudpathlib/pull/514), thanks @ljyanesm)
- Fixed `rmtree` fail on Azure with no `hns` and more than 256 blobs to drop (Issue [#509](https://github.com/drivendataorg/cloudpathlib/issues/509), PR [#508](https://github.com/drivendataorg/cloudpathlib/pull/508), thanks @alikefia)

## v0.21.0 (2025-03-03)
Expand Down
29 changes: 16 additions & 13 deletions cloudpathlib/gs/gsclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from google.auth.credentials import Credentials
from google.api_core.retry import Retry

from google.auth import default as google_default_auth
from google.auth.exceptions import DefaultCredentialsError
from google.cloud.storage import Client as StorageClient

Expand Down Expand Up @@ -51,18 +52,14 @@
):
"""Class constructor. Sets up a [`Storage
Client`](https://googleapis.dev/python/storage/latest/client.html).
Supports the following authentication methods of `Storage Client`.
Supports, in this order, the following authentication methods of `Storage Client`.

- Environment variable `"GOOGLE_APPLICATION_CREDENTIALS"` containing a
path to a JSON credentials file for a Google service account. See
[Authenticating as a Service
Account](https://cloud.google.com/docs/authentication/production).
- File path to a JSON credentials file for a Google service account.
- OAuth2 Credentials object and a project name.
- Instantiated and already authenticated `Storage Client`.
- OAuth2 Credentials object and a project name.
- File path to a JSON credentials file for a Google service account.
- Google Cloud SDK default credentials. See [How Application Default Credentials works](https://cloud.google.com/docs/authentication/application-default-credentials)

If multiple methods are used, priority order is reverse of list above
(later in list takes priority). If no authentication methods are used,
If no authentication methods are used,
then the client will be instantiated as anonymous, which will only have
access to public buckets.

Expand Down Expand Up @@ -91,18 +88,24 @@
timeout (Optional[float]): Cloud Storage [timeout value](https://cloud.google.com/python/docs/reference/storage/1.39.0/retry_timeout)
retry (Optional[google.api_core.retry.Retry]): Cloud Storage [retry configuration](https://cloud.google.com/python/docs/reference/storage/1.39.0/retry_timeout#configuring-retries)
"""
if application_credentials is None:
application_credentials = os.getenv("GOOGLE_APPLICATION_CREDENTIALS")

# don't check `GOOGLE_APPLICATION_CREDENTIALS` since `google_default_auth` already does that
# use explicit client
if storage_client is not None:
self.client = storage_client
# use explicit credentials
elif credentials is not None:
self.client = StorageClient(credentials=credentials, project=project)
# use explicit credential file
elif application_credentials is not None:
self.client = StorageClient.from_service_account_json(application_credentials)
# use default credentials based on SDK precedence
else:
try:
self.client = StorageClient()
# use `google_default_auth` instead of `StorageClient()` since it
# handles precedence of creds in different locations properly
credentials, default_project = google_default_auth()
project = project or default_project # use explicit project if present
self.client = StorageClient(credentials=credentials, project=project)

Check warning on line 108 in cloudpathlib/gs/gsclient.py

View check run for this annotation

Codecov / codecov/patch

cloudpathlib/gs/gsclient.py#L107-L108

Added lines #L107 - L108 were not covered by tests
except DefaultCredentialsError:
self.client = StorageClient.create_anonymous_client()

Expand Down
Loading