Skip to content

Commit 13ffc87

Browse files
committed
Unit tests, formatting, and clean up.
1 parent 4df4da0 commit 13ffc87

File tree

6 files changed

+69
-44
lines changed

6 files changed

+69
-44
lines changed

google/auth/_default.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ def _get_impersonated_service_account_credentials(filename, info, scopes):
484484
from google.auth import impersonated_credentials
485485

486486
try:
487-
credentials = impersonated_credentials.Credentials.from_impersonated_account_info(
487+
credentials = impersonated_credentials.Credentials.from_impersonated_service_account_info(
488488
info, scopes=scopes
489489
)
490490
except ValueError as caught_exc:

google/auth/impersonated_credentials.py

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747

4848
_GOOGLE_OAUTH2_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token"
4949

50+
_SOURCE_CREDENTIAL_AUTHORIZED_USER_TYPE = "authorized_user"
51+
_SOURCE_CREDENTIAL_SERVICE_ACCOUNT_TYPE = "service_account"
52+
_SOURCE_CREDENTIAL_EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = (
53+
"external_account_authorized_user"
54+
)
55+
5056

5157
def _make_iam_token_request(
5258
request,
@@ -411,39 +417,45 @@ def with_scopes(self, scopes, default_scopes=None):
411417
return cred
412418

413419
@classmethod
414-
def _source_credentials_from_impersonated_account_info(cls, info):
415-
"""Creates a Credentials instance from parsed authorized user info.
420+
def from_impersonated_service_account_info(cls, info, scopes=None):
421+
"""Creates a Credentials instance from parsed impersonated service account credentials info.
416422
417423
Args:
418-
info (Mapping[str, str]): The authorized user info in Google
424+
info (Mapping[str, str]): The impersonated service account credentials info in Google
419425
format.
426+
scopes (Sequence[str]): Optional list of scopes to include in the
427+
credentials.
420428
421429
Returns:
422430
google.oauth2.credentials.Credentials: The constructed
423431
credentials.
424432
425433
Raises:
426-
InvalidType: If the source_credentials are not a support impersonation type
427-
ValueError: If the source_credentials info is not in the expected format.
434+
InvalidType: If the info["source_credentials"] are not a supported impersonation type
435+
InvalidValue: If the info["service_account_impersonation_url"] is not in the expected format.
436+
ValueError: If the info is not in the expected format.
428437
"""
429-
_AUTHORIZED_USER_TYPE = "authorized_user"
430-
_SERVICE_ACCOUNT_TYPE = "service_account"
431-
_EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = "external_account_authorized_user"
432438

433439
source_credentials_info = info.get("source_credentials")
434440
source_credentials_type = source_credentials_info.get("type")
435-
if source_credentials_type == _AUTHORIZED_USER_TYPE:
441+
if source_credentials_type == _SOURCE_CREDENTIAL_AUTHORIZED_USER_TYPE:
436442
from google.oauth2 import credentials
443+
437444
source_credentials = credentials.Credentials.from_authorized_user_info(
438445
source_credentials_info
439446
)
440-
elif source_credentials_type == _SERVICE_ACCOUNT_TYPE:
447+
elif source_credentials_type == _SOURCE_CREDENTIAL_SERVICE_ACCOUNT_TYPE:
441448
from google.oauth2 import service_account
449+
442450
source_credentials = service_account.Credentials.from_service_account_info(
443451
source_credentials_info
444452
)
445-
elif source_credentials_type == _EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE:
453+
elif (
454+
source_credentials_type
455+
== _SOURCE_CREDENTIAL_EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE
456+
):
446457
from google.auth import external_account_authorized_user
458+
447459
source_credentials = external_account_authorized_user.Credentials.from_info(
448460
source_credentials_info
449461
)
@@ -454,28 +466,6 @@ def _source_credentials_from_impersonated_account_info(cls, info):
454466
)
455467
)
456468

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-
479469
impersonation_url = info.get("service_account_impersonation_url")
480470
start_index = impersonation_url.rfind("/")
481471
end_index = impersonation_url.find(":generateAccessToken")
@@ -484,7 +474,6 @@ def from_impersonated_account_info(cls, info, scopes=None):
484474
"Cannot extract target principal from {}".format(impersonation_url)
485475
)
486476
target_principal = impersonation_url[start_index + 1 : end_index]
487-
488477
delegates = info.get("delegates")
489478
quota_project_id = info.get("quota_project_id")
490479

@@ -493,7 +482,7 @@ def from_impersonated_account_info(cls, info, scopes=None):
493482
target_principal,
494483
scopes,
495484
delegates,
496-
quota_project_id=quota_project_id
485+
quota_project_id=quota_project_id,
497486
)
498487

499488

google/oauth2/credentials.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,6 @@ def from_authorized_user_info(cls, info, scopes=None):
457457
Raises:
458458
ValueError: If the info is not in the expected format.
459459
"""
460-
print("NTRACE: from_authorizer_user_info")
461-
print(info)
462460
keys_needed = set(("refresh_token", "client_id", "client_secret"))
463461
missing = keys_needed.difference(info.keys())
464462

google/oauth2/id_token.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,16 +287,15 @@ def fetch_id_token_credentials(audience, request=None):
287287
elif info.get("type") == "impersonated_service_account":
288288
from google.auth import impersonated_credentials
289289

290-
target_credentials = impersonated_credentials.Credentials.from_impersonated_account_info(
290+
target_credentials = impersonated_credentials.Credentials.from_impersonated_service_account_info(
291291
info
292292
)
293293

294-
id_creds = impersonated_credentials.IDTokenCredentials(
294+
return impersonated_credentials.IDTokenCredentials(
295295
target_credentials=target_credentials,
296296
target_audience=audience,
297297
include_email=True,
298298
)
299-
return id_creds
300299
except ValueError as caught_exc:
301300
new_exc = exceptions.DefaultCredentialsError(
302301
"GOOGLE_APPLICATION_CREDENTIALS is not valid service account credentials.",

tests/oauth2/test_id_token.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,18 @@
2020

2121
from google.auth import environment_vars
2222
from google.auth import exceptions
23+
from google.auth import impersonated_credentials
2324
from google.auth import transport
2425
from google.oauth2 import id_token
2526
from google.oauth2 import service_account
26-
from google.auth import impersonated_credentials
2727

2828
SERVICE_ACCOUNT_FILE = os.path.join(
2929
os.path.dirname(__file__), "../data/service_account.json"
3030
)
3131

3232
IMPERSONATED_SERVICE_ACCOUNT_FILE = os.path.join(
33-
os.path.dirname(__file__), "../data/impersonated_service_account_authorized_user_source.json"
33+
os.path.dirname(__file__),
34+
"../data/impersonated_service_account_authorized_user_source.json",
3435
)
3536

3637
ID_TOKEN_AUDIENCE = "https://pubsub.googleapis.com"
@@ -269,7 +270,6 @@ def test_fetch_id_token_credentials_from_explicit_cred_json_file(monkeypatch):
269270

270271

271272
def test_fetch_id_token_credentials_from_impersonated_cred_json_file(monkeypatch):
272-
## Test: Can I Fetch ID token Credentials?
273273
monkeypatch.setenv(environment_vars.CREDENTIALS, IMPERSONATED_SERVICE_ACCOUNT_FILE)
274274

275275
cred = id_token.fetch_id_token_credentials(ID_TOKEN_AUDIENCE)

tests/test_impersonated_credentials.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import copy
1516
import datetime
1617
import http.client as http_client
1718
import json
@@ -35,6 +36,9 @@
3536
PRIVATE_KEY_BYTES = fh.read()
3637

3738
SERVICE_ACCOUNT_JSON_FILE = os.path.join(DATA_DIR, "service_account.json")
39+
IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE = os.path.join(
40+
DATA_DIR, "impersonated_service_account_authorized_user_source.json"
41+
)
3842

3943
ID_TOKEN_DATA = (
4044
"eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmMzc1ODkwOGI3OTIyOTNhZDk3N2Ew"
@@ -49,6 +53,9 @@
4953
with open(SERVICE_ACCOUNT_JSON_FILE, "rb") as fh:
5054
SERVICE_ACCOUNT_INFO = json.load(fh)
5155

56+
with open(IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE, "rb") as fh:
57+
IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_INFO = json.load(fh)
58+
5259
SIGNER = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES, "1")
5360
TOKEN_URI = "https://example.com/oauth2/token"
5461

@@ -148,6 +155,38 @@ def make_credentials(
148155
iam_endpoint_override=iam_endpoint_override,
149156
)
150157

158+
def test_from_impersonated_service_account_info(self):
159+
credentials = impersonated_credentials.Credentials.from_impersonated_service_account_info(
160+
IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_INFO
161+
)
162+
assert isinstance(credentials, impersonated_credentials.Credentials)
163+
164+
def test_from_impersonated_service_account_info_with_invalid_source_credentials_type(
165+
self
166+
):
167+
info = copy.deepcopy(IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_INFO)
168+
assert "source_credentials" in info
169+
# Set the source_credentials to an invalid type
170+
info["source_credentials"]["type"] = "invalid_type"
171+
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
172+
impersonated_credentials.Credentials.from_impersonated_service_account_info(
173+
info
174+
)
175+
assert excinfo.match(
176+
"source credential of type {} is not supported".format("invalid_type")
177+
)
178+
179+
def test_from_impersonated_service_account_info_with_invalid_impersonation_url(
180+
self
181+
):
182+
info = copy.deepcopy(IMPERSONATED_SERVICE_ACCOUNT_AUTHORIZED_USER_SOURCE_INFO)
183+
info["service_account_impersonation_url"] = "invalid_url"
184+
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
185+
impersonated_credentials.Credentials.from_impersonated_service_account_info(
186+
info
187+
)
188+
assert excinfo.match(r"Cannot extract target principal from")
189+
151190
def test_get_cred_info(self):
152191
credentials = self.make_credentials()
153192
assert not credentials.get_cred_info()

0 commit comments

Comments
 (0)