-
Notifications
You must be signed in to change notification settings - Fork 69
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
Migrating to Google Auth Library #221
Conversation
@shcheklein I've raise a new PR above. Please do take a look when you have time |
@junpeng-jp hey, sure. Please don't hesitate to Request a review via a link at the top. Otherwise it was not clear if it's still in progress or not. Thanks again for the effort. I'll try to find time to review it this week. |
@shcheklein Not sure why but I don't see a button to request a reviewer for this PR. Are you able to help me here? |
@junpeng-jp ah, no worries. If it doesn't work- that's fine. Just ping me in the comment. Sorry for the delay, this PR needs more attention and I need to find time to check it out. |
pydrive2/auth.py
Outdated
@@ -1,28 +1,31 @@ | |||
import json | |||
import webbrowser | |||
import httplib2 | |||
import oauth2client.clientsecrets as clientsecrets | |||
import json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have import json
already ^^
pydrive2/auth.py
Outdated
"""Decorator to check if the auth is valid and loads auth if not.""" | ||
""" | ||
Decorator to check the self.auth & self.http object in a decorated API call. | ||
Loads a new GoogleAuth or Http object if not the needed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if not the needed
- needs to be fixed
pydrive2/auth.py
Outdated
self._credentials = None | ||
|
||
# Lazy loading, read-only properties | ||
# these look like functions but are actually getters for the read only properties |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this explanation, it's quite common pattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
almost all of these properties should be private? which ones do we want to expose?
pydrive2/storage.py
Outdated
|
||
|
||
class CredentialBackend(object): | ||
"""Adapter that provides a consistent interface to read and write credential files""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
write credential files -> write credentials
pydrive2/auth.py
Outdated
|
||
try: | ||
self.credentials = self._default_storage.get() | ||
auth_info = self.default_storage.read_credentials(credentials_file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think storage should be per file name. Otherwise we have to keep providing credentials_file
everywhere + we use the same lock for all credential
files potentially
auth_info, scopes=auth_info["scopes"] | ||
) | ||
except ValueError: | ||
warn( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, could you remind me please about the use case? can we drop this?
pydrive2/auth.py
Outdated
if self._default_storage is None: | ||
raise InvalidConfigError( | ||
"Backend `file` is not configured, specify " | ||
"credentials file to read in the settings " | ||
"file or pass an explicit value" | ||
) | ||
else: | ||
self._default_storage = Storage(credentials_file) | ||
self._default_storage = FileBackend() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
information is lost at this point that this storage is from the specified credentials_file
. I'm not 100% understand the use case why would someone do auth.LoadCredentialsFile("some/custom/path")
, but it looks like we are changing the behavior here ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, before it was important since the credentials object was triggering save on refresh, not sure again yet if this is important here ...
self.service = build( | ||
"drive", "v2", http=self.http, cache_discovery=False | ||
raise DeprecationWarning( | ||
"Manual authorization of HTTP will be deprecated as the" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, but we do have AuthorizedHttp(...)
call which is similar to the self.credentials.authorize(self.http)
. In this case again, I'm not sure why it (the public Authorize
call) was needed in the first place. Probably for some custom auth flow. Would be great to get more information on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Authorize
is being used in the Auth above that won't work anymore. And it's needed for custom flow logic like this https://docs.iterative.ai/PyDrive2/oauth/#building-your-own-authentication-flow .
pydrive2/auth.py
Outdated
except AccessTokenRefreshError as error: | ||
raise RefreshError("Access token refresh failed: %s" % error) | ||
raise DeprecationWarning( | ||
"Manual refresh will be deprecated as the" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is deprecated ...
|
||
@property | ||
def credentials(self): | ||
if not self._credentials: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need / have to support this as a lazy / self-initializing logic for credentials?
btw, have you seen the:
client_config = ApiAttribute("client_config")
flow = ApiAttribute("flow")
credentials = ApiAttribute("credentials")
http = ApiAttribute("http")
service = ApiAttribute("service")
auth_method = ApiAttribute("auth_method")
how those coexist with these properties?
@shcheklein @junpeng-jp any update on this PR? I really need the automatic auth using GCP service account credentials. |
@lappazos please give it a try https://docs.iterative.ai/PyDrive2/oauth/#authentication-with-a-service-account . You don't need to wait for this PR to be merged. |
@shcheklein so i did - i couldn't find where this function is implemented. |
@lappazos please, let's move this to a separate issue/discussion. This is not related I think to this PR. |
@junpeng-jp @shcheklein is this PR stuck? |
Closing as stale |
Just noting that it would be nice if this PR can be "brought back to life/completed" to enable features like "service account impersonation", etc. Background: IIUC, it seems like using "service account impersonation" is preferred to downloading a "service account key", as the key is long-lived, requires manual rotation, etc. Whereas "impersonation" allows you to just fetch a temporary token for the service account (using your existing user credentials) While I'm not 100% certain it is required, I think that using the updated google oauth libraries are probably the best way to enable these features. I was able to get it running locally (using mostly default settings for PyDrive2, and creating "impersonated application-default credentials" with:
To make the "application default credentials" be the "impersonated service account" ones. I was ALSO able to get a test version running on a google cloud run container (where a google managed "service account" is used to run the service, and I was able to get that service account to "impersonate" an existing service account (which already has access to certain drive folders) and get things working that way also. It did require a bit of work (monkey patching the GoogleAuth.ServiceAuth() method to set self._credential to be the impersonated one). I think that would be a "fairly small update" to allow impersonated service accounts cleanly (if this PR is revived). At any rate, just noting that this PR does appear to be pretty useful, and hoping that this can be brought back to life / completed (as it appears to be pretty far along / functional). Eric |
Summary of changes
#89
#89
#173
Removing manual refresh & authorization header injection code as this is now handle by the Google Auth library
self.Refresh()
&self.Authorize()
methodsself.Get_Http_Object()
method to use theAuthorizedHttp
object from google's HTTP migration helper library