Skip to content

Commit 8baeee9

Browse files
committed
Add from_impersonated_account_info method to ImperstonatedCredentials
1 parent a249e3b commit 8baeee9

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

google/auth/impersonated_credentials.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,92 @@ def with_scopes(self, scopes, default_scopes=None):
410410
cred._target_scopes = scopes or default_scopes
411411
return cred
412412

413+
@classmethod
414+
def _source_credentials_from_impersonated_account_info(cls, info):
415+
"""Creates a Credentials instance from parsed authorized user info.
416+
417+
Args:
418+
info (Mapping[str, str]): The authorized user info in Google
419+
format.
420+
421+
Returns:
422+
google.oauth2.credentials.Credentials: The constructed
423+
credentials.
424+
425+
Raises:
426+
InvalidType: If the source_credentials are not a support impersonation type
427+
ValueError: If the info is not in the expected format.
428+
"""
429+
_AUTHORIZED_USER_TYPE = "authorized_user"
430+
_SERVICE_ACCOUNT_TYPE = "service_account"
431+
_EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = "external_account_authorized_user"
432+
433+
source_credentials_info = info.get("source_credentials")
434+
source_credentials_type = source_credentials_info.get("type")
435+
if source_credentials_type == _AUTHORIZED_USER_TYPE:
436+
from google.oauth2 import credentials
437+
source_credentials, _ = credentials.Credentials.from_authorized_user_info(
438+
info
439+
)
440+
elif source_credentials_type == _SERVICE_ACCOUNT_TYPE:
441+
from google.oauth2 import service_account
442+
source_credentials, _ = service_account.Credentials.from_service_account_info(
443+
source_credentials_info
444+
)
445+
elif source_credentials_type == _EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE:
446+
from google.auth import external_account_authorized_user
447+
source_credentials = external_account_authorized_user.Credentials.from_info(
448+
source_credentials_info
449+
)
450+
else:
451+
raise exceptions.InvalidType(
452+
"source credential of type {} is not supported.".format(
453+
source_credentials_type
454+
)
455+
)
456+
457+
return source_credentials
458+
459+
@classmethod
460+
def from_impersonated_account_info(cls, info, scopes=None):
461+
"""Creates a Credentials instance from parsed authorized user info.
462+
463+
Args:
464+
info (Mapping[str, str]): The authorized user info in Google
465+
format.
466+
scopes (Sequence[str]): Optional list of scopes to include in the
467+
credentials.
468+
469+
Returns:
470+
google.oauth2.credentials.Credentials: The constructed
471+
credentials.
472+
473+
Raises:
474+
InvalidType: If the source_credentials are not a support impersonation type
475+
ValueError: If the info is not in the expected format.
476+
"""
477+
source_credentials = cls._source_credentials_from_impersonated_account_info(info)
478+
479+
impersonation_url = info.get("service_account_impersonation_url")
480+
start_index = impersonation_url.rfind("/")
481+
end_index = impersonation_url.find(":generateAccessToken")
482+
if start_index == -1 or end_index == -1 or start_index > end_index:
483+
raise exceptions.InvalidValue(
484+
"Cannot extract target principal from {}".format(impersonation_url)
485+
)
486+
target_principal = impersonation_url[start_index + 1 : end_index]
487+
488+
delegates = info.get("delegates")
489+
quota_project_id = info.get("quota_project_id")
490+
491+
return cls(
492+
source_credentials,
493+
target_principal,
494+
scopes,
495+
delegates,
496+
quota_project_id=quota_project_id
497+
)
498+
413499

414500
class IDTokenCredentials(credentials.CredentialsWithQuotaProject):
415501
"""Open ID Connect ID Token-based service account credentials.

0 commit comments

Comments
 (0)