blob: 1ce03cfe832a3046b3d7afbe73484022784a138f [file] [log] [blame]
C.J. Collier37141e42020-02-13 13:49:49 -08001# Copyright 2016 Google LLC
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -07002#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import json
16import os
17
18import mock
19import pytest
20
21from google.auth import _default
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -070022from google.auth import app_engine
bojeil-googled4d7f382021-02-16 12:33:20 -080023from google.auth import aws
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070024from google.auth import compute_engine
Bu Sun Kim3dda7b22020-07-09 10:39:39 -070025from google.auth import credentials
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070026from google.auth import environment_vars
27from google.auth import exceptions
bojeil-googled4d7f382021-02-16 12:33:20 -080028from google.auth import external_account
29from google.auth import identity_pool
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070030from google.oauth2 import service_account
31import google.oauth2.credentials
32
33
Bu Sun Kim9eec0912019-10-21 17:04:21 -070034DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
35AUTHORIZED_USER_FILE = os.path.join(DATA_DIR, "authorized_user.json")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070036
37with open(AUTHORIZED_USER_FILE) as fh:
38 AUTHORIZED_USER_FILE_DATA = json.load(fh)
39
Thea Flowersa8d93482018-05-31 14:52:06 -070040AUTHORIZED_USER_CLOUD_SDK_FILE = os.path.join(
Bu Sun Kim9eec0912019-10-21 17:04:21 -070041 DATA_DIR, "authorized_user_cloud_sdk.json"
42)
Thea Flowersa8d93482018-05-31 14:52:06 -070043
arithmetic1728f30b45a2020-06-17 23:36:04 -070044AUTHORIZED_USER_CLOUD_SDK_WITH_QUOTA_PROJECT_ID_FILE = os.path.join(
45 DATA_DIR, "authorized_user_cloud_sdk_with_quota_project_id.json"
46)
47
Bu Sun Kim9eec0912019-10-21 17:04:21 -070048SERVICE_ACCOUNT_FILE = os.path.join(DATA_DIR, "service_account.json")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070049
Bu Sun Kim15d5fa92020-06-18 14:05:40 -070050CLIENT_SECRETS_FILE = os.path.join(DATA_DIR, "client_secrets.json")
51
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070052with open(SERVICE_ACCOUNT_FILE) as fh:
53 SERVICE_ACCOUNT_FILE_DATA = json.load(fh)
54
bojeil-googled4d7f382021-02-16 12:33:20 -080055SUBJECT_TOKEN_TEXT_FILE = os.path.join(DATA_DIR, "external_subject_token.txt")
56TOKEN_URL = "https://sts.googleapis.com/v1/token"
57AUDIENCE = "//iam.googleapis.com/projects/123456/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID"
bojeil-google10bd9fb2021-09-30 23:19:51 -070058WORKFORCE_AUDIENCE = (
59 "//iam.googleapis.com/locations/global/workforcePools/POOL_ID/providers/PROVIDER_ID"
60)
61WORKFORCE_POOL_USER_PROJECT = "WORKFORCE_POOL_USER_PROJECT_NUMBER"
bojeil-googled4d7f382021-02-16 12:33:20 -080062REGION_URL = "http://169.254.169.254/latest/meta-data/placement/availability-zone"
63SECURITY_CREDS_URL = "http://169.254.169.254/latest/meta-data/iam/security-credentials"
64CRED_VERIFICATION_URL = (
65 "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15"
66)
67IDENTITY_POOL_DATA = {
68 "type": "external_account",
69 "audience": AUDIENCE,
70 "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
71 "token_url": TOKEN_URL,
72 "credential_source": {"file": SUBJECT_TOKEN_TEXT_FILE},
73}
74AWS_DATA = {
75 "type": "external_account",
76 "audience": AUDIENCE,
77 "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request",
78 "token_url": TOKEN_URL,
79 "credential_source": {
80 "environment_id": "aws1",
81 "region_url": REGION_URL,
82 "url": SECURITY_CREDS_URL,
83 "regional_cred_verification_url": CRED_VERIFICATION_URL,
84 },
85}
bojeil-google10bd9fb2021-09-30 23:19:51 -070086SERVICE_ACCOUNT_EMAIL = "service-1234@service-name.iam.gserviceaccount.com"
87SERVICE_ACCOUNT_IMPERSONATION_URL = (
88 "https://us-east1-iamcredentials.googleapis.com/v1/projects/-"
89 + "/serviceAccounts/{}:generateAccessToken".format(SERVICE_ACCOUNT_EMAIL)
90)
91IMPERSONATED_IDENTITY_POOL_DATA = {
92 "type": "external_account",
93 "audience": AUDIENCE,
94 "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
95 "token_url": TOKEN_URL,
96 "credential_source": {"file": SUBJECT_TOKEN_TEXT_FILE},
97 "service_account_impersonation_url": SERVICE_ACCOUNT_IMPERSONATION_URL,
98}
99IMPERSONATED_AWS_DATA = {
100 "type": "external_account",
101 "audience": AUDIENCE,
102 "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request",
103 "token_url": TOKEN_URL,
104 "credential_source": {
105 "environment_id": "aws1",
106 "region_url": REGION_URL,
107 "url": SECURITY_CREDS_URL,
108 "regional_cred_verification_url": CRED_VERIFICATION_URL,
109 },
110 "service_account_impersonation_url": SERVICE_ACCOUNT_IMPERSONATION_URL,
111}
112IDENTITY_POOL_WORKFORCE_DATA = {
113 "type": "external_account",
114 "audience": WORKFORCE_AUDIENCE,
115 "subject_token_type": "urn:ietf:params:oauth:token-type:id_token",
116 "token_url": TOKEN_URL,
117 "credential_source": {"file": SUBJECT_TOKEN_TEXT_FILE},
118 "workforce_pool_user_project": WORKFORCE_POOL_USER_PROJECT,
119}
120IMPERSONATED_IDENTITY_POOL_WORKFORCE_DATA = {
121 "type": "external_account",
122 "audience": WORKFORCE_AUDIENCE,
123 "subject_token_type": "urn:ietf:params:oauth:token-type:id_token",
124 "token_url": TOKEN_URL,
125 "credential_source": {"file": SUBJECT_TOKEN_TEXT_FILE},
126 "service_account_impersonation_url": SERVICE_ACCOUNT_IMPERSONATION_URL,
127 "workforce_pool_user_project": WORKFORCE_POOL_USER_PROJECT,
128}
bojeil-googled4d7f382021-02-16 12:33:20 -0800129
Bu Sun Kim41599ae2020-09-02 12:55:42 -0600130MOCK_CREDENTIALS = mock.Mock(spec=credentials.CredentialsWithQuotaProject)
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700131MOCK_CREDENTIALS.with_quota_project.return_value = MOCK_CREDENTIALS
132
bojeil-googled4d7f382021-02-16 12:33:20 -0800133
134def get_project_id_side_effect(self, request=None):
135 # If no scopes are set, this will always return None.
136 if not self.scopes:
137 return None
138 return mock.sentinel.project_id
139
140
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700141LOAD_FILE_PATCH = mock.patch(
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700142 "google.auth._default.load_credentials_from_file",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700143 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700144 autospec=True,
145)
bojeil-googled4d7f382021-02-16 12:33:20 -0800146EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH = mock.patch.object(
147 external_account.Credentials,
148 "get_project_id",
149 side_effect=get_project_id_side_effect,
150 autospec=True,
151)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700152
153
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700154def test_load_credentials_from_missing_file():
weitaiting6e86c932017-08-12 03:26:59 +0800155 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700156 _default.load_credentials_from_file("")
weitaiting6e86c932017-08-12 03:26:59 +0800157
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700158 assert excinfo.match(r"not found")
weitaiting6e86c932017-08-12 03:26:59 +0800159
160
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700161def test_load_credentials_from_file_invalid_json(tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700162 jsonfile = tmpdir.join("invalid.json")
163 jsonfile.write("{")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700164
165 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700166 _default.load_credentials_from_file(str(jsonfile))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700167
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700168 assert excinfo.match(r"not a valid json file")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700169
170
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700171def test_load_credentials_from_file_invalid_type(tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700172 jsonfile = tmpdir.join("invalid.json")
173 jsonfile.write(json.dumps({"type": "not-a-real-type"}))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700174
175 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700176 _default.load_credentials_from_file(str(jsonfile))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700177
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700178 assert excinfo.match(r"does not have a valid type")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700179
180
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700181def test_load_credentials_from_file_authorized_user():
182 credentials, project_id = _default.load_credentials_from_file(AUTHORIZED_USER_FILE)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700183 assert isinstance(credentials, google.oauth2.credentials.Credentials)
184 assert project_id is None
185
186
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700187def test_load_credentials_from_file_no_type(tmpdir):
188 # use the client_secrets.json, which is valid json but not a
189 # loadable credentials type
190 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
191 _default.load_credentials_from_file(CLIENT_SECRETS_FILE)
192
193 assert excinfo.match(r"does not have a valid type")
194 assert excinfo.match(r"Type is None")
195
196
197def test_load_credentials_from_file_authorized_user_bad_format(tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700198 filename = tmpdir.join("authorized_user_bad.json")
199 filename.write(json.dumps({"type": "authorized_user"}))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700200
201 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700202 _default.load_credentials_from_file(str(filename))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700203
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700204 assert excinfo.match(r"Failed to load authorized user")
205 assert excinfo.match(r"missing fields")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700206
207
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700208def test_load_credentials_from_file_authorized_user_cloud_sdk():
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700209 with pytest.warns(UserWarning, match="Cloud SDK"):
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700210 credentials, project_id = _default.load_credentials_from_file(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700211 AUTHORIZED_USER_CLOUD_SDK_FILE
212 )
Thea Flowersa8d93482018-05-31 14:52:06 -0700213 assert isinstance(credentials, google.oauth2.credentials.Credentials)
214 assert project_id is None
215
arithmetic1728f30b45a2020-06-17 23:36:04 -0700216 # No warning if the json file has quota project id.
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700217 credentials, project_id = _default.load_credentials_from_file(
arithmetic1728f30b45a2020-06-17 23:36:04 -0700218 AUTHORIZED_USER_CLOUD_SDK_WITH_QUOTA_PROJECT_ID_FILE
219 )
220 assert isinstance(credentials, google.oauth2.credentials.Credentials)
221 assert project_id is None
222
Thea Flowersa8d93482018-05-31 14:52:06 -0700223
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700224def test_load_credentials_from_file_authorized_user_cloud_sdk_with_scopes():
225 with pytest.warns(UserWarning, match="Cloud SDK"):
226 credentials, project_id = _default.load_credentials_from_file(
227 AUTHORIZED_USER_CLOUD_SDK_FILE,
228 scopes=["https://www.google.com/calendar/feeds"],
229 )
230 assert isinstance(credentials, google.oauth2.credentials.Credentials)
231 assert project_id is None
232 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
233
234
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700235def test_load_credentials_from_file_authorized_user_cloud_sdk_with_quota_project():
236 credentials, project_id = _default.load_credentials_from_file(
237 AUTHORIZED_USER_CLOUD_SDK_FILE, quota_project_id="project-foo"
238 )
239
240 assert isinstance(credentials, google.oauth2.credentials.Credentials)
241 assert project_id is None
242 assert credentials.quota_project_id == "project-foo"
243
244
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700245def test_load_credentials_from_file_service_account():
246 credentials, project_id = _default.load_credentials_from_file(SERVICE_ACCOUNT_FILE)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700247 assert isinstance(credentials, service_account.Credentials)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700248 assert project_id == SERVICE_ACCOUNT_FILE_DATA["project_id"]
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700249
250
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700251def test_load_credentials_from_file_service_account_with_scopes():
252 credentials, project_id = _default.load_credentials_from_file(
253 SERVICE_ACCOUNT_FILE, scopes=["https://www.google.com/calendar/feeds"]
254 )
255 assert isinstance(credentials, service_account.Credentials)
256 assert project_id == SERVICE_ACCOUNT_FILE_DATA["project_id"]
257 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
258
259
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700260def test_load_credentials_from_file_service_account_with_quota_project():
261 credentials, project_id = _default.load_credentials_from_file(
262 SERVICE_ACCOUNT_FILE, quota_project_id="project-foo"
263 )
264 assert isinstance(credentials, service_account.Credentials)
265 assert project_id == SERVICE_ACCOUNT_FILE_DATA["project_id"]
266 assert credentials.quota_project_id == "project-foo"
267
268
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700269def test_load_credentials_from_file_service_account_bad_format(tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700270 filename = tmpdir.join("serivce_account_bad.json")
271 filename.write(json.dumps({"type": "service_account"}))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700272
273 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700274 _default.load_credentials_from_file(str(filename))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700275
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700276 assert excinfo.match(r"Failed to load service account")
277 assert excinfo.match(r"missing fields")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700278
279
bojeil-googled4d7f382021-02-16 12:33:20 -0800280@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
281def test_load_credentials_from_file_external_account_identity_pool(
282 get_project_id, tmpdir
283):
284 config_file = tmpdir.join("config.json")
285 config_file.write(json.dumps(IDENTITY_POOL_DATA))
286 credentials, project_id = _default.load_credentials_from_file(str(config_file))
287
288 assert isinstance(credentials, identity_pool.Credentials)
289 # Since no scopes are specified, the project ID cannot be determined.
290 assert project_id is None
291 assert get_project_id.called
292
293
294@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
295def test_load_credentials_from_file_external_account_aws(get_project_id, tmpdir):
296 config_file = tmpdir.join("config.json")
297 config_file.write(json.dumps(AWS_DATA))
298 credentials, project_id = _default.load_credentials_from_file(str(config_file))
299
300 assert isinstance(credentials, aws.Credentials)
301 # Since no scopes are specified, the project ID cannot be determined.
302 assert project_id is None
303 assert get_project_id.called
304
305
306@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
bojeil-google10bd9fb2021-09-30 23:19:51 -0700307def test_load_credentials_from_file_external_account_identity_pool_impersonated(
308 get_project_id, tmpdir
309):
310 config_file = tmpdir.join("config.json")
311 config_file.write(json.dumps(IMPERSONATED_IDENTITY_POOL_DATA))
312 credentials, project_id = _default.load_credentials_from_file(str(config_file))
313
314 assert isinstance(credentials, identity_pool.Credentials)
315 assert not credentials.is_user
316 assert not credentials.is_workforce_pool
317 # Since no scopes are specified, the project ID cannot be determined.
318 assert project_id is None
319 assert get_project_id.called
320
321
322@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
323def test_load_credentials_from_file_external_account_aws_impersonated(
324 get_project_id, tmpdir
325):
326 config_file = tmpdir.join("config.json")
327 config_file.write(json.dumps(IMPERSONATED_AWS_DATA))
328 credentials, project_id = _default.load_credentials_from_file(str(config_file))
329
330 assert isinstance(credentials, aws.Credentials)
331 assert not credentials.is_user
332 assert not credentials.is_workforce_pool
333 # Since no scopes are specified, the project ID cannot be determined.
334 assert project_id is None
335 assert get_project_id.called
336
337
338@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
339def test_load_credentials_from_file_external_account_workforce(get_project_id, tmpdir):
340 config_file = tmpdir.join("config.json")
341 config_file.write(json.dumps(IDENTITY_POOL_WORKFORCE_DATA))
342 credentials, project_id = _default.load_credentials_from_file(str(config_file))
343
344 assert isinstance(credentials, identity_pool.Credentials)
345 assert credentials.is_user
346 assert credentials.is_workforce_pool
347 # Since no scopes are specified, the project ID cannot be determined.
348 assert project_id is None
349 assert get_project_id.called
350
351
352@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
353def test_load_credentials_from_file_external_account_workforce_impersonated(
354 get_project_id, tmpdir
355):
356 config_file = tmpdir.join("config.json")
357 config_file.write(json.dumps(IMPERSONATED_IDENTITY_POOL_WORKFORCE_DATA))
358 credentials, project_id = _default.load_credentials_from_file(str(config_file))
359
360 assert isinstance(credentials, identity_pool.Credentials)
361 assert not credentials.is_user
362 assert credentials.is_workforce_pool
363 # Since no scopes are specified, the project ID cannot be determined.
364 assert project_id is None
365 assert get_project_id.called
366
367
368@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
bojeil-googled4d7f382021-02-16 12:33:20 -0800369def test_load_credentials_from_file_external_account_with_user_and_default_scopes(
370 get_project_id, tmpdir
371):
372 config_file = tmpdir.join("config.json")
373 config_file.write(json.dumps(IDENTITY_POOL_DATA))
374 credentials, project_id = _default.load_credentials_from_file(
375 str(config_file),
376 scopes=["https://www.google.com/calendar/feeds"],
377 default_scopes=["https://www.googleapis.com/auth/cloud-platform"],
378 )
379
380 assert isinstance(credentials, identity_pool.Credentials)
381 # Since scopes are specified, the project ID can be determined.
382 assert project_id is mock.sentinel.project_id
383 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
384 assert credentials.default_scopes == [
385 "https://www.googleapis.com/auth/cloud-platform"
386 ]
387
388
389@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
390def test_load_credentials_from_file_external_account_with_quota_project(
391 get_project_id, tmpdir
392):
393 config_file = tmpdir.join("config.json")
394 config_file.write(json.dumps(IDENTITY_POOL_DATA))
395 credentials, project_id = _default.load_credentials_from_file(
396 str(config_file), quota_project_id="project-foo"
397 )
398
399 assert isinstance(credentials, identity_pool.Credentials)
400 # Since no scopes are specified, the project ID cannot be determined.
401 assert project_id is None
402 assert credentials.quota_project_id == "project-foo"
403
404
405def test_load_credentials_from_file_external_account_bad_format(tmpdir):
406 filename = tmpdir.join("external_account_bad.json")
407 filename.write(json.dumps({"type": "external_account"}))
408
409 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
410 _default.load_credentials_from_file(str(filename))
411
412 assert excinfo.match(
413 "Failed to load external account credentials from {}".format(str(filename))
414 )
415
416
417@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
418def test_load_credentials_from_file_external_account_explicit_request(
419 get_project_id, tmpdir
420):
421 config_file = tmpdir.join("config.json")
422 config_file.write(json.dumps(IDENTITY_POOL_DATA))
423 credentials, project_id = _default.load_credentials_from_file(
424 str(config_file),
425 request=mock.sentinel.request,
426 scopes=["https://www.googleapis.com/auth/cloud-platform"],
427 )
428
429 assert isinstance(credentials, identity_pool.Credentials)
430 # Since scopes are specified, the project ID can be determined.
431 assert project_id is mock.sentinel.project_id
432 get_project_id.assert_called_with(credentials, request=mock.sentinel.request)
433
434
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700435@mock.patch.dict(os.environ, {}, clear=True)
436def test__get_explicit_environ_credentials_no_env():
437 assert _default._get_explicit_environ_credentials() == (None, None)
438
439
arithmetic172811ebaeb2021-09-07 14:38:49 -0700440@pytest.mark.parametrize("quota_project_id", [None, "project-foo"])
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700441@LOAD_FILE_PATCH
arithmetic172811ebaeb2021-09-07 14:38:49 -0700442def test__get_explicit_environ_credentials(load, quota_project_id, monkeypatch):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700443 monkeypatch.setenv(environment_vars.CREDENTIALS, "filename")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700444
arithmetic172811ebaeb2021-09-07 14:38:49 -0700445 credentials, project_id = _default._get_explicit_environ_credentials(
446 quota_project_id=quota_project_id
447 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700448
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700449 assert credentials is MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700450 assert project_id is mock.sentinel.project_id
arithmetic172811ebaeb2021-09-07 14:38:49 -0700451 load.assert_called_with("filename", quota_project_id=quota_project_id)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700452
453
454@LOAD_FILE_PATCH
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700455def test__get_explicit_environ_credentials_no_project_id(load, monkeypatch):
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700456 load.return_value = MOCK_CREDENTIALS, None
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700457 monkeypatch.setenv(environment_vars.CREDENTIALS, "filename")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700458
459 credentials, project_id = _default._get_explicit_environ_credentials()
460
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700461 assert credentials is MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700462 assert project_id is None
463
464
arithmetic172811ebaeb2021-09-07 14:38:49 -0700465@pytest.mark.parametrize("quota_project_id", [None, "project-foo"])
arithmetic1728333cb762021-02-25 15:42:32 -0800466@mock.patch(
467 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
468)
469@mock.patch("google.auth._default._get_gcloud_sdk_credentials", autospec=True)
470def test__get_explicit_environ_credentials_fallback_to_gcloud(
arithmetic172811ebaeb2021-09-07 14:38:49 -0700471 get_gcloud_creds, get_adc_path, quota_project_id, monkeypatch
arithmetic1728333cb762021-02-25 15:42:32 -0800472):
473 # Set explicit credentials path to cloud sdk credentials path.
474 get_adc_path.return_value = "filename"
475 monkeypatch.setenv(environment_vars.CREDENTIALS, "filename")
476
arithmetic172811ebaeb2021-09-07 14:38:49 -0700477 _default._get_explicit_environ_credentials(quota_project_id=quota_project_id)
arithmetic1728333cb762021-02-25 15:42:32 -0800478
479 # Check we fall back to cloud sdk flow since explicit credentials path is
480 # cloud sdk credentials path
arithmetic172811ebaeb2021-09-07 14:38:49 -0700481 get_gcloud_creds.assert_called_with(quota_project_id=quota_project_id)
arithmetic1728333cb762021-02-25 15:42:32 -0800482
483
arithmetic172811ebaeb2021-09-07 14:38:49 -0700484@pytest.mark.parametrize("quota_project_id", [None, "project-foo"])
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700485@LOAD_FILE_PATCH
Jon Wayne Parrott8784b232016-11-10 12:53:55 -0800486@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700487 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
488)
arithmetic172811ebaeb2021-09-07 14:38:49 -0700489def test__get_gcloud_sdk_credentials(get_adc_path, load, quota_project_id):
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700490 get_adc_path.return_value = SERVICE_ACCOUNT_FILE
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700491
arithmetic172811ebaeb2021-09-07 14:38:49 -0700492 credentials, project_id = _default._get_gcloud_sdk_credentials(
493 quota_project_id=quota_project_id
494 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700495
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700496 assert credentials is MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700497 assert project_id is mock.sentinel.project_id
arithmetic172811ebaeb2021-09-07 14:38:49 -0700498 load.assert_called_with(SERVICE_ACCOUNT_FILE, quota_project_id=quota_project_id)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700499
500
Jon Wayne Parrott8784b232016-11-10 12:53:55 -0800501@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700502 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
503)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700504def test__get_gcloud_sdk_credentials_non_existent(get_adc_path, tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700505 non_existent = tmpdir.join("non-existent")
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700506 get_adc_path.return_value = str(non_existent)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700507
508 credentials, project_id = _default._get_gcloud_sdk_credentials()
509
510 assert credentials is None
511 assert project_id is None
512
513
514@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700515 "google.auth._cloud_sdk.get_project_id",
516 return_value=mock.sentinel.project_id,
517 autospec=True,
518)
519@mock.patch("os.path.isfile", return_value=True, autospec=True)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700520@LOAD_FILE_PATCH
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700521def test__get_gcloud_sdk_credentials_project_id(load, unused_isfile, get_project_id):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700522 # Don't return a project ID from load file, make the function check
523 # the Cloud SDK project.
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700524 load.return_value = MOCK_CREDENTIALS, None
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700525
526 credentials, project_id = _default._get_gcloud_sdk_credentials()
527
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700528 assert credentials == MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700529 assert project_id == mock.sentinel.project_id
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700530 assert get_project_id.called
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700531
532
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700533@mock.patch("google.auth._cloud_sdk.get_project_id", return_value=None, autospec=True)
534@mock.patch("os.path.isfile", return_value=True)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700535@LOAD_FILE_PATCH
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700536def test__get_gcloud_sdk_credentials_no_project_id(load, unused_isfile, get_project_id):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700537 # Don't return a project ID from load file, make the function check
538 # the Cloud SDK project.
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700539 load.return_value = MOCK_CREDENTIALS, None
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700540
541 credentials, project_id = _default._get_gcloud_sdk_credentials()
542
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700543 assert credentials == MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700544 assert project_id is None
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700545 assert get_project_id.called
546
547
548class _AppIdentityModule(object):
549 """The interface of the App Idenity app engine module.
550 See https://cloud.google.com/appengine/docs/standard/python/refdocs\
551 /google.appengine.api.app_identity.app_identity
552 """
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700553
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700554 def get_application_id(self):
555 raise NotImplementedError()
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700556
557
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700558@pytest.fixture
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700559def app_identity(monkeypatch):
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700560 """Mocks the app_identity module for google.auth.app_engine."""
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700561 app_identity_module = mock.create_autospec(_AppIdentityModule, instance=True)
562 monkeypatch.setattr(app_engine, "app_identity", app_identity_module)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700563 yield app_identity_module
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700564
565
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400566@mock.patch.dict(os.environ)
567def test__get_gae_credentials_gen1(app_identity):
568 os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python27"
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700569 app_identity.get_application_id.return_value = mock.sentinel.project
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700570
571 credentials, project_id = _default._get_gae_credentials()
572
573 assert isinstance(credentials, app_engine.Credentials)
574 assert project_id == mock.sentinel.project
575
576
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400577@mock.patch.dict(os.environ)
578def test__get_gae_credentials_gen2():
579 os.environ["GAE_RUNTIME"] = "python37"
580 credentials, project_id = _default._get_gae_credentials()
581 assert credentials is None
582 assert project_id is None
583
584
585@mock.patch.dict(os.environ)
586def test__get_gae_credentials_gen2_backwards_compat():
587 # compat helpers may copy GAE_RUNTIME to APPENGINE_RUNTIME
588 # for backwards compatibility with code that relies on it
589 os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python37"
590 os.environ["GAE_RUNTIME"] = "python37"
591 credentials, project_id = _default._get_gae_credentials()
592 assert credentials is None
593 assert project_id is None
594
595
596def test__get_gae_credentials_env_unset():
597 assert environment_vars.LEGACY_APPENGINE_RUNTIME not in os.environ
598 assert "GAE_RUNTIME" not in os.environ
599 credentials, project_id = _default._get_gae_credentials()
600 assert credentials is None
601 assert project_id is None
602
603
604@mock.patch.dict(os.environ)
James Wilson6e0781b2018-12-20 20:38:52 -0500605def test__get_gae_credentials_no_app_engine():
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400606 # test both with and without LEGACY_APPENGINE_RUNTIME setting
607 assert environment_vars.LEGACY_APPENGINE_RUNTIME not in os.environ
608
James Wilson6e0781b2018-12-20 20:38:52 -0500609 import sys
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700610
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400611 with mock.patch.dict(sys.modules, {"google.auth.app_engine": None}):
612 credentials, project_id = _default._get_gae_credentials()
613 assert credentials is None
614 assert project_id is None
615
616 os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python27"
James Wilson6e0781b2018-12-20 20:38:52 -0500617 credentials, project_id = _default._get_gae_credentials()
618 assert credentials is None
619 assert project_id is None
620
621
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400622@mock.patch.dict(os.environ)
623@mock.patch.object(app_engine, "app_identity", new=None)
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700624def test__get_gae_credentials_no_apis():
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400625 # test both with and without LEGACY_APPENGINE_RUNTIME setting
626 assert environment_vars.LEGACY_APPENGINE_RUNTIME not in os.environ
627
628 credentials, project_id = _default._get_gae_credentials()
629 assert credentials is None
630 assert project_id is None
631
632 os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python27"
633 credentials, project_id = _default._get_gae_credentials()
634 assert credentials is None
635 assert project_id is None
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700636
637
638@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700639 "google.auth.compute_engine._metadata.ping", return_value=True, autospec=True
640)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700641@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700642 "google.auth.compute_engine._metadata.get_project_id",
643 return_value="example-project",
644 autospec=True,
645)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700646def test__get_gce_credentials(unused_get, unused_ping):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700647 credentials, project_id = _default._get_gce_credentials()
648
649 assert isinstance(credentials, compute_engine.Credentials)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700650 assert project_id == "example-project"
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700651
652
Jon Wayne Parrott8784b232016-11-10 12:53:55 -0800653@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700654 "google.auth.compute_engine._metadata.ping", return_value=False, autospec=True
655)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700656def test__get_gce_credentials_no_ping(unused_ping):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700657 credentials, project_id = _default._get_gce_credentials()
658
659 assert credentials is None
660 assert project_id is None
661
662
663@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700664 "google.auth.compute_engine._metadata.ping", return_value=True, autospec=True
665)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700666@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700667 "google.auth.compute_engine._metadata.get_project_id",
668 side_effect=exceptions.TransportError(),
669 autospec=True,
670)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700671def test__get_gce_credentials_no_project_id(unused_get, unused_ping):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700672 credentials, project_id = _default._get_gce_credentials()
673
674 assert isinstance(credentials, compute_engine.Credentials)
675 assert project_id is None
676
677
James Wilson6e0781b2018-12-20 20:38:52 -0500678def test__get_gce_credentials_no_compute_engine():
679 import sys
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700680
681 with mock.patch.dict("sys.modules"):
682 sys.modules["google.auth.compute_engine"] = None
James Wilson6e0781b2018-12-20 20:38:52 -0500683 credentials, project_id = _default._get_gce_credentials()
684 assert credentials is None
685 assert project_id is None
686
687
Jon Wayne Parrott8784b232016-11-10 12:53:55 -0800688@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700689 "google.auth.compute_engine._metadata.ping", return_value=False, autospec=True
690)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700691def test__get_gce_credentials_explicit_request(ping):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700692 _default._get_gce_credentials(mock.sentinel.request)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700693 ping.assert_called_with(request=mock.sentinel.request)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700694
695
696@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700697 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700698 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700699 autospec=True,
700)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700701def test_default_early_out(unused_get):
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700702 assert _default.default() == (MOCK_CREDENTIALS, mock.sentinel.project_id)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700703
704
705@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700706 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700707 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700708 autospec=True,
709)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700710def test_default_explict_project_id(unused_get, monkeypatch):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700711 monkeypatch.setenv(environment_vars.PROJECT, "explicit-env")
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700712 assert _default.default() == (MOCK_CREDENTIALS, "explicit-env")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700713
714
715@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700716 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700717 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700718 autospec=True,
719)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700720def test_default_explict_legacy_project_id(unused_get, monkeypatch):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700721 monkeypatch.setenv(environment_vars.LEGACY_PROJECT, "explicit-env")
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700722 assert _default.default() == (MOCK_CREDENTIALS, "explicit-env")
Jon Wayne Parrottce37cba2016-11-07 16:41:42 -0800723
724
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700725@mock.patch("logging.Logger.warning", autospec=True)
Jon Wayne Parrottce37cba2016-11-07 16:41:42 -0800726@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700727 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700728 return_value=(MOCK_CREDENTIALS, None),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700729 autospec=True,
730)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600731@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700732 "google.auth._default._get_gcloud_sdk_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700733 return_value=(MOCK_CREDENTIALS, None),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700734 autospec=True,
735)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600736@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700737 "google.auth._default._get_gae_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700738 return_value=(MOCK_CREDENTIALS, None),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700739 autospec=True,
740)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600741@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700742 "google.auth._default._get_gce_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700743 return_value=(MOCK_CREDENTIALS, None),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700744 autospec=True,
745)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600746def test_default_without_project_id(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700747 unused_gce, unused_gae, unused_sdk, unused_explicit, logger_warning
748):
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700749 assert _default.default() == (MOCK_CREDENTIALS, None)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600750 logger_warning.assert_called_with(mock.ANY, mock.ANY, mock.ANY)
751
752
753@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700754 "google.auth._default._get_explicit_environ_credentials",
755 return_value=(None, None),
756 autospec=True,
757)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700758@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700759 "google.auth._default._get_gcloud_sdk_credentials",
760 return_value=(None, None),
761 autospec=True,
762)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700763@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700764 "google.auth._default._get_gae_credentials",
765 return_value=(None, None),
766 autospec=True,
767)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700768@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700769 "google.auth._default._get_gce_credentials",
770 return_value=(None, None),
771 autospec=True,
772)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700773def test_default_fail(unused_gce, unused_gae, unused_sdk, unused_explicit):
774 with pytest.raises(exceptions.DefaultCredentialsError):
775 assert _default.default()
Jon Wayne Parrott8a7e5062016-11-07 16:45:17 -0800776
777
778@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700779 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700780 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700781 autospec=True,
782)
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700783@mock.patch(
784 "google.auth.credentials.with_scopes_if_required",
785 return_value=MOCK_CREDENTIALS,
786 autospec=True,
787)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600788def test_default_scoped(with_scopes, unused_get):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700789 scopes = ["one", "two"]
Jon Wayne Parrott8a7e5062016-11-07 16:45:17 -0800790
791 credentials, project_id = _default.default(scopes=scopes)
792
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700793 assert credentials == with_scopes.return_value
Jon Wayne Parrott8a7e5062016-11-07 16:45:17 -0800794 assert project_id == mock.sentinel.project_id
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700795 with_scopes.assert_called_once_with(MOCK_CREDENTIALS, scopes, default_scopes=None)
James Wilson6e0781b2018-12-20 20:38:52 -0500796
797
798@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700799 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700800 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700801 autospec=True,
802)
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700803def test_default_quota_project(with_quota_project):
804 credentials, project_id = _default.default(quota_project_id="project-foo")
805
806 MOCK_CREDENTIALS.with_quota_project.assert_called_once_with("project-foo")
807 assert project_id == mock.sentinel.project_id
808
809
810@mock.patch(
811 "google.auth._default._get_explicit_environ_credentials",
812 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
813 autospec=True,
814)
James Wilson6e0781b2018-12-20 20:38:52 -0500815def test_default_no_app_engine_compute_engine_module(unused_get):
816 """
817 google.auth.compute_engine and google.auth.app_engine are both optional
818 to allow not including them when using this package. This verifies
819 that default fails gracefully if these modules are absent
820 """
821 import sys
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700822
823 with mock.patch.dict("sys.modules"):
824 sys.modules["google.auth.compute_engine"] = None
825 sys.modules["google.auth.app_engine"] = None
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700826 assert _default.default() == (MOCK_CREDENTIALS, mock.sentinel.project_id)
bojeil-googled4d7f382021-02-16 12:33:20 -0800827
828
829@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
bojeil-google10bd9fb2021-09-30 23:19:51 -0700830def test_default_environ_external_credentials_identity_pool(
831 get_project_id, monkeypatch, tmpdir
832):
bojeil-googled4d7f382021-02-16 12:33:20 -0800833 config_file = tmpdir.join("config.json")
834 config_file.write(json.dumps(IDENTITY_POOL_DATA))
835 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
836
837 credentials, project_id = _default.default()
838
839 assert isinstance(credentials, identity_pool.Credentials)
bojeil-google10bd9fb2021-09-30 23:19:51 -0700840 assert not credentials.is_user
841 assert not credentials.is_workforce_pool
bojeil-googled4d7f382021-02-16 12:33:20 -0800842 # Without scopes, project ID cannot be determined.
843 assert project_id is None
844
845
846@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
bojeil-google10bd9fb2021-09-30 23:19:51 -0700847def test_default_environ_external_credentials_identity_pool_impersonated(
848 get_project_id, monkeypatch, tmpdir
849):
850 config_file = tmpdir.join("config.json")
851 config_file.write(json.dumps(IMPERSONATED_IDENTITY_POOL_DATA))
852 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
853
854 credentials, project_id = _default.default(
855 scopes=["https://www.google.com/calendar/feeds"]
856 )
857
858 assert isinstance(credentials, identity_pool.Credentials)
859 assert not credentials.is_user
860 assert not credentials.is_workforce_pool
861 assert project_id is mock.sentinel.project_id
862 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
863
864
865@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
866def test_default_environ_external_credentials_aws_impersonated(
867 get_project_id, monkeypatch, tmpdir
868):
869 config_file = tmpdir.join("config.json")
870 config_file.write(json.dumps(IMPERSONATED_AWS_DATA))
871 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
872
873 credentials, project_id = _default.default(
874 scopes=["https://www.google.com/calendar/feeds"]
875 )
876
877 assert isinstance(credentials, aws.Credentials)
878 assert not credentials.is_user
879 assert not credentials.is_workforce_pool
880 assert project_id is mock.sentinel.project_id
881 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
882
883
884@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
885def test_default_environ_external_credentials_workforce(
886 get_project_id, monkeypatch, tmpdir
887):
888 config_file = tmpdir.join("config.json")
889 config_file.write(json.dumps(IDENTITY_POOL_WORKFORCE_DATA))
890 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
891
892 credentials, project_id = _default.default(
893 scopes=["https://www.google.com/calendar/feeds"]
894 )
895
896 assert isinstance(credentials, identity_pool.Credentials)
897 assert credentials.is_user
898 assert credentials.is_workforce_pool
899 assert project_id is mock.sentinel.project_id
900 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
901
902
903@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
904def test_default_environ_external_credentials_workforce_impersonated(
905 get_project_id, monkeypatch, tmpdir
906):
907 config_file = tmpdir.join("config.json")
908 config_file.write(json.dumps(IMPERSONATED_IDENTITY_POOL_WORKFORCE_DATA))
909 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
910
911 credentials, project_id = _default.default(
912 scopes=["https://www.google.com/calendar/feeds"]
913 )
914
915 assert isinstance(credentials, identity_pool.Credentials)
916 assert not credentials.is_user
917 assert credentials.is_workforce_pool
918 assert project_id is mock.sentinel.project_id
919 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
920
921
922@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
bojeil-googled4d7f382021-02-16 12:33:20 -0800923def test_default_environ_external_credentials_with_user_and_default_scopes_and_quota_project_id(
924 get_project_id, monkeypatch, tmpdir
925):
926 config_file = tmpdir.join("config.json")
927 config_file.write(json.dumps(IDENTITY_POOL_DATA))
928 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
929
930 credentials, project_id = _default.default(
931 scopes=["https://www.google.com/calendar/feeds"],
932 default_scopes=["https://www.googleapis.com/auth/cloud-platform"],
933 quota_project_id="project-foo",
934 )
935
936 assert isinstance(credentials, identity_pool.Credentials)
937 assert project_id is mock.sentinel.project_id
938 assert credentials.quota_project_id == "project-foo"
939 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
940 assert credentials.default_scopes == [
941 "https://www.googleapis.com/auth/cloud-platform"
942 ]
943
944
945@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
946def test_default_environ_external_credentials_explicit_request_with_scopes(
947 get_project_id, monkeypatch, tmpdir
948):
949 config_file = tmpdir.join("config.json")
950 config_file.write(json.dumps(IDENTITY_POOL_DATA))
951 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
952
953 credentials, project_id = _default.default(
954 request=mock.sentinel.request,
955 scopes=["https://www.googleapis.com/auth/cloud-platform"],
956 )
957
958 assert isinstance(credentials, identity_pool.Credentials)
959 assert project_id is mock.sentinel.project_id
960 # default() will initialize new credentials via with_scopes_if_required
961 # and potentially with_quota_project.
962 # As a result the caller of get_project_id() will not match the returned
963 # credentials.
964 get_project_id.assert_called_with(mock.ANY, request=mock.sentinel.request)
965
966
967def test_default_environ_external_credentials_bad_format(monkeypatch, tmpdir):
968 filename = tmpdir.join("external_account_bad.json")
969 filename.write(json.dumps({"type": "external_account"}))
970 monkeypatch.setenv(environment_vars.CREDENTIALS, str(filename))
971
972 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
973 _default.default()
974
975 assert excinfo.match(
976 "Failed to load external account credentials from {}".format(str(filename))
977 )
arithmetic172811ebaeb2021-09-07 14:38:49 -0700978
979
980@mock.patch(
981 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
982)
983def test_default_warning_without_quota_project_id_for_user_creds(get_adc_path):
984 get_adc_path.return_value = AUTHORIZED_USER_CLOUD_SDK_FILE
985
986 with pytest.warns(UserWarning, match="Cloud SDK"):
987 credentials, project_id = _default.default(quota_project_id=None)
988
989
990@mock.patch(
991 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
992)
993def test_default_no_warning_with_quota_project_id_for_user_creds(get_adc_path):
994 get_adc_path.return_value = AUTHORIZED_USER_CLOUD_SDK_FILE
995
996 credentials, project_id = _default.default(quota_project_id="project-foo")