diff --git a/src/gam/__init__.py b/src/gam/__init__.py index 8f744847..8d977a8e 100755 --- a/src/gam/__init__.py +++ b/src/gam/__init__.py @@ -7853,6 +7853,29 @@ def doShowServiceAccountKeys(): display.print_json(keys) +def create_signjwt_serviceaccount(): + _checkForExistingProjectFiles() + sa_info = { + 'type': 'service_account', + 'key_type': 'signjwt', + 'token_uri': 'https://oauth2.googleapis.com/token' + } + try: + creds, sa_info['project_id'] = google.auth.default() + except google.auth.exceptions.DefaultCredentialsError as e: + controlflow.system_error_exit(2, e) + request = transport.create_request() + creds.refresh(request) + sa_info['client_email'] = creds.service_account_email + oa2 = buildGAPIObjectNoAuthentication('oauth2') + token_info = gapi.call(oa2, 'tokeninfo', access_token=creds.token) + sa_info['client_id'] = token_info['issued_to'] + sa_output = json.dumps(sa_info, indent=4, sort_keys=True) + fileutils.write_file(GC_Values[GC_OAUTH2SERVICE_JSON], + sa_output, + continue_on_error=False) + + def doCreateOrRotateServiceAccountKeys(iam=None, project_id=None, client_email=None, @@ -11573,6 +11596,8 @@ def ProcessGAMCommand(args): gapi_chat.create_message() elif argument in ['caalevel']: gapi_caa.create_access_level() + elif argument in ['signjwtserviceaccount']: + create_signjwt_serviceaccount() else: controlflow.invalid_argument_exit(argument, 'gam create') sys.exit(0) diff --git a/src/gam/auth/signjwt.py b/src/gam/auth/signjwt.py index d76a0d65..cb324f32 100644 --- a/src/gam/auth/signjwt.py +++ b/src/gam/auth/signjwt.py @@ -2,10 +2,12 @@ import datetime import json -from google.auth import _helpers, default +import google.auth +from google.auth._helpers import datetime_to_secs, scopes_to_string, utcnow import google.oauth2.service_account from googleapiclient.discovery import build +from gam import controlflow from gam import gapi _DEFAULT_TOKEN_LIFETIME_SECS = 3600 # 1 hour in seconds @@ -15,14 +17,14 @@ _GOOGLE_OAUTH2_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token" class JWTCredentials(google.auth.jwt.Credentials): ''' Class used for DASA ''' def _make_jwt(self): - now = _helpers.utcnow() + now = utcnow() lifetime = datetime.timedelta(seconds=self._token_lifetime) expiry = now + lifetime payload = { "iss": self._issuer, "sub": self._subject, - "iat": _helpers.datetime_to_secs(now), - "exp": _helpers.datetime_to_secs(expiry), + "iat": datetime_to_secs(now), + "exp": datetime_to_secs(expiry), } if self._audience: payload["aud"] = self._audience @@ -35,15 +37,15 @@ class Credentials(google.oauth2.service_account.Credentials): ''' Class used for DwD ''' def _make_authorization_grant_assertion(self): - now = _helpers.utcnow() + now = utcnow() lifetime = datetime.timedelta(seconds=_DEFAULT_TOKEN_LIFETIME_SECS) expiry = now + lifetime payload = { - "iat": _helpers.datetime_to_secs(now), - "exp": _helpers.datetime_to_secs(expiry), + "iat": datetime_to_secs(now), + "exp": datetime_to_secs(expiry), "iss": self._service_account_email, "aud": _GOOGLE_OAUTH2_TOKEN_ENDPOINT, - "scope": _helpers.scopes_to_string(self._scopes or ()), + "scope": scopes_to_string(self._scopes or ()), } payload.update(self._additional_claims) @@ -69,7 +71,10 @@ class SignJwt(google.auth.crypt.Signer): def sign(self, message): ''' Call IAM Credentials SignJWT API to get our signed JWT ''' - credentials, _ = default() + try: + credentials, _ = google.auth.default() + except google.auth.exceptions.DefaultCredentialsError as e: + controlflow.system_error_exit(2, e) iamc = build('iamcredentials', 'v1', credentials=credentials) response = gapi.call(iamc.projects().serviceAccounts(), 'signJwt',