mirror of
https://chromium.googlesource.com/chromium/tools/depot_tools.git
synced 2026-01-11 18:51:29 +00:00
gerrit_util: add ReAuth support to ensure_authenticated
This CL makes it possible for ensure_authenticated to check whether the current credential would satisfy ReAuth requirement. Right now, only GitCredsAuthenticator performs additional ReAuth check. For other Authenticator, either ReAuth is not relevant (e.g. SSO), or not supported or implied (e.g. .gitcookies). This CL does nothing on its own, because ensure_autheticated with ReAuth is opt-in. Subsequent CL will update callsites to pass in ReAuthContext to make the check effective. Bug: 451651615 Change-Id: Idb1e70c52aaa844e672331fad8d462a2a7577d45 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/7104363 Commit-Queue: Jiewei Qian <qjw@chromium.org> Reviewed-by: Scott Lee <ddoman@chromium.org> Reviewed-by: Allen Li <ayatane@chromium.org>
This commit is contained in:
@@ -275,13 +275,24 @@ class _Authenticator(object):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def ensure_authenticated(self, *, gerrit_host: str,
|
||||
git_host: str) -> Tuple[bool, str]:
|
||||
def ensure_authenticated(
|
||||
self,
|
||||
*,
|
||||
gerrit_host: str,
|
||||
git_host: str,
|
||||
reauth_context: Optional[auth.ReAuthContext] = None
|
||||
) -> Tuple[bool, str]:
|
||||
"""Returns (bypassable, error message).
|
||||
|
||||
If the error message is empty, there is no error to report.
|
||||
If bypassable is true, the caller will allow the user to continue past the
|
||||
error.
|
||||
|
||||
If `reauth_context` is provided, additionally checks whether the
|
||||
authentication information satisfies the ReAuth requirement.
|
||||
|
||||
For the ReAuth check, Gerrit `host` attribute in `reauth_context` takes
|
||||
precedence over `gerrit_host` argument.
|
||||
"""
|
||||
return (True, '')
|
||||
|
||||
@@ -346,15 +357,21 @@ def debug_auth() -> Tuple[str, str]:
|
||||
return authn.__class__.__name__, authn.debug_summary_state()
|
||||
|
||||
|
||||
def ensure_authenticated(*, gerrit_host: str,
|
||||
git_host: str) -> Tuple[bool, str]:
|
||||
def ensure_authenticated(
|
||||
*,
|
||||
gerrit_host: str,
|
||||
git_host: str,
|
||||
reauth_context: Optional[auth.ReAuthContext] = None
|
||||
) -> Tuple[bool, str]:
|
||||
"""Returns (bypassable, error message).
|
||||
|
||||
If the error message is empty, there is no error to report. If bypassable is
|
||||
true, the caller will allow the user to continue past the error.
|
||||
"""
|
||||
return _Authenticator.get().ensure_authenticated(gerrit_host=gerrit_host,
|
||||
git_host=git_host)
|
||||
return _Authenticator.get().ensure_authenticated(
|
||||
gerrit_host=gerrit_host,
|
||||
git_host=git_host,
|
||||
reauth_context=reauth_context)
|
||||
|
||||
|
||||
class SSOAuthenticator(_Authenticator):
|
||||
@@ -707,13 +724,24 @@ class CookiesAuthenticator(_Authenticator):
|
||||
else:
|
||||
conn.req_headers['Authorization'] = f'Bearer {cred}'
|
||||
|
||||
def ensure_authenticated(self, *, gerrit_host: str,
|
||||
git_host: str) -> Tuple[bool, str]:
|
||||
def ensure_authenticated(
|
||||
self,
|
||||
*,
|
||||
gerrit_host: str,
|
||||
git_host: str,
|
||||
reauth_context: Optional[auth.ReAuthContext] = None
|
||||
) -> Tuple[bool, str]:
|
||||
"""Returns (bypassable, error message).
|
||||
|
||||
If the error message is empty, there is no error to report.
|
||||
If bypassable is true, the caller will allow the user to continue past the
|
||||
error.
|
||||
|
||||
Some bots are still using .gitcookies. They're marked as trusted robots,
|
||||
and therefore already satisfies ReAuth requirement. So we don't need to
|
||||
perform extra ReAuth checks here for bots.
|
||||
|
||||
Human users shouldn't be using .gitcookies by now.
|
||||
"""
|
||||
# Lazy-loader to identify Gerrit and Git hosts.
|
||||
gerrit_auth = self._get_auth_for_host(gerrit_host)
|
||||
@@ -974,6 +1002,24 @@ class GitCredsAuthenticator(_Authenticator):
|
||||
return self.gerrit_account_exists(gerrit_host)
|
||||
return False
|
||||
|
||||
def ensure_authenticated(
|
||||
self,
|
||||
*,
|
||||
gerrit_host: str,
|
||||
git_host: str,
|
||||
reauth_context: Optional[auth.ReAuthContext] = None
|
||||
) -> Tuple[bool, str]:
|
||||
try:
|
||||
if not reauth_context:
|
||||
self._authenticator.get_access_token()
|
||||
else:
|
||||
self._authenticator.get_authorization_header(reauth_context)
|
||||
return (True, '')
|
||||
except (auth.GitLoginRequiredError, auth.GitReAuthRequiredError,
|
||||
auth.GitUnknownError) as e:
|
||||
return (False, str(e))
|
||||
|
||||
|
||||
|
||||
class NoAuthenticator(_Authenticator):
|
||||
"""_Authenticator implementation that does no auth.
|
||||
@@ -1031,11 +1077,24 @@ class ChainedAuthenticator(_Authenticator):
|
||||
def debug_summary_state(self) -> str:
|
||||
return ''
|
||||
|
||||
def ensure_authenticated(self, *, gerrit_host: str,
|
||||
git_host: str) -> Tuple[bool, str]:
|
||||
def ensure_authenticated(
|
||||
self,
|
||||
*,
|
||||
gerrit_host: str,
|
||||
git_host: str,
|
||||
reauth_context: Optional[auth.ReAuthContext] = None
|
||||
) -> Tuple[bool, str]:
|
||||
for a in self.applicable_authenticators(gerrit_host=gerrit_host):
|
||||
return a.ensure_authenticated(gerrit_host=gerrit_host,
|
||||
git_host=git_host)
|
||||
bypassable, err_msg = a.ensure_authenticated(
|
||||
gerrit_host=gerrit_host,
|
||||
git_host=git_host,
|
||||
reauth_context=reauth_context)
|
||||
if err_msg:
|
||||
logging.info(
|
||||
"%s.ensure_authenticated() returns an %s error: %s",
|
||||
a.__class__.__name__,
|
||||
"a bypassable" if bypassable else "an", err_msg)
|
||||
return bypassable, err_msg
|
||||
return (False,
|
||||
f'{self!r} has no applicable authenticator for {gerrit_host}')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user