blob: c70ceaa57da3cd51805e7a4ed832119afc1fb09c [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"
58REGION_URL = "http://169.254.169.254/latest/meta-data/placement/availability-zone"
59SECURITY_CREDS_URL = "http://169.254.169.254/latest/meta-data/iam/security-credentials"
60CRED_VERIFICATION_URL = (
61 "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15"
62)
63IDENTITY_POOL_DATA = {
64 "type": "external_account",
65 "audience": AUDIENCE,
66 "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
67 "token_url": TOKEN_URL,
68 "credential_source": {"file": SUBJECT_TOKEN_TEXT_FILE},
69}
70AWS_DATA = {
71 "type": "external_account",
72 "audience": AUDIENCE,
73 "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request",
74 "token_url": TOKEN_URL,
75 "credential_source": {
76 "environment_id": "aws1",
77 "region_url": REGION_URL,
78 "url": SECURITY_CREDS_URL,
79 "regional_cred_verification_url": CRED_VERIFICATION_URL,
80 },
81}
82
Bu Sun Kim41599ae2020-09-02 12:55:42 -060083MOCK_CREDENTIALS = mock.Mock(spec=credentials.CredentialsWithQuotaProject)
Bu Sun Kim3dda7b22020-07-09 10:39:39 -070084MOCK_CREDENTIALS.with_quota_project.return_value = MOCK_CREDENTIALS
85
bojeil-googled4d7f382021-02-16 12:33:20 -080086
87def get_project_id_side_effect(self, request=None):
88 # If no scopes are set, this will always return None.
89 if not self.scopes:
90 return None
91 return mock.sentinel.project_id
92
93
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070094LOAD_FILE_PATCH = mock.patch(
Bu Sun Kim15d5fa92020-06-18 14:05:40 -070095 "google.auth._default.load_credentials_from_file",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -070096 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -070097 autospec=True,
98)
bojeil-googled4d7f382021-02-16 12:33:20 -080099EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH = mock.patch.object(
100 external_account.Credentials,
101 "get_project_id",
102 side_effect=get_project_id_side_effect,
103 autospec=True,
104)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700105
106
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700107def test_load_credentials_from_missing_file():
weitaiting6e86c932017-08-12 03:26:59 +0800108 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700109 _default.load_credentials_from_file("")
weitaiting6e86c932017-08-12 03:26:59 +0800110
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700111 assert excinfo.match(r"not found")
weitaiting6e86c932017-08-12 03:26:59 +0800112
113
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700114def test_load_credentials_from_file_invalid_json(tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700115 jsonfile = tmpdir.join("invalid.json")
116 jsonfile.write("{")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700117
118 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700119 _default.load_credentials_from_file(str(jsonfile))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700120
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700121 assert excinfo.match(r"not a valid json file")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700122
123
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700124def test_load_credentials_from_file_invalid_type(tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700125 jsonfile = tmpdir.join("invalid.json")
126 jsonfile.write(json.dumps({"type": "not-a-real-type"}))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700127
128 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700129 _default.load_credentials_from_file(str(jsonfile))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700130
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700131 assert excinfo.match(r"does not have a valid type")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700132
133
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700134def test_load_credentials_from_file_authorized_user():
135 credentials, project_id = _default.load_credentials_from_file(AUTHORIZED_USER_FILE)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700136 assert isinstance(credentials, google.oauth2.credentials.Credentials)
137 assert project_id is None
138
139
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700140def test_load_credentials_from_file_no_type(tmpdir):
141 # use the client_secrets.json, which is valid json but not a
142 # loadable credentials type
143 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
144 _default.load_credentials_from_file(CLIENT_SECRETS_FILE)
145
146 assert excinfo.match(r"does not have a valid type")
147 assert excinfo.match(r"Type is None")
148
149
150def test_load_credentials_from_file_authorized_user_bad_format(tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700151 filename = tmpdir.join("authorized_user_bad.json")
152 filename.write(json.dumps({"type": "authorized_user"}))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700153
154 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700155 _default.load_credentials_from_file(str(filename))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700156
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700157 assert excinfo.match(r"Failed to load authorized user")
158 assert excinfo.match(r"missing fields")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700159
160
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700161def test_load_credentials_from_file_authorized_user_cloud_sdk():
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700162 with pytest.warns(UserWarning, match="Cloud SDK"):
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700163 credentials, project_id = _default.load_credentials_from_file(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700164 AUTHORIZED_USER_CLOUD_SDK_FILE
165 )
Thea Flowersa8d93482018-05-31 14:52:06 -0700166 assert isinstance(credentials, google.oauth2.credentials.Credentials)
167 assert project_id is None
168
arithmetic1728f30b45a2020-06-17 23:36:04 -0700169 # No warning if the json file has quota project id.
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700170 credentials, project_id = _default.load_credentials_from_file(
arithmetic1728f30b45a2020-06-17 23:36:04 -0700171 AUTHORIZED_USER_CLOUD_SDK_WITH_QUOTA_PROJECT_ID_FILE
172 )
173 assert isinstance(credentials, google.oauth2.credentials.Credentials)
174 assert project_id is None
175
Thea Flowersa8d93482018-05-31 14:52:06 -0700176
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700177def test_load_credentials_from_file_authorized_user_cloud_sdk_with_scopes():
178 with pytest.warns(UserWarning, match="Cloud SDK"):
179 credentials, project_id = _default.load_credentials_from_file(
180 AUTHORIZED_USER_CLOUD_SDK_FILE,
181 scopes=["https://www.google.com/calendar/feeds"],
182 )
183 assert isinstance(credentials, google.oauth2.credentials.Credentials)
184 assert project_id is None
185 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
186
187
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700188def test_load_credentials_from_file_authorized_user_cloud_sdk_with_quota_project():
189 credentials, project_id = _default.load_credentials_from_file(
190 AUTHORIZED_USER_CLOUD_SDK_FILE, quota_project_id="project-foo"
191 )
192
193 assert isinstance(credentials, google.oauth2.credentials.Credentials)
194 assert project_id is None
195 assert credentials.quota_project_id == "project-foo"
196
197
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700198def test_load_credentials_from_file_service_account():
199 credentials, project_id = _default.load_credentials_from_file(SERVICE_ACCOUNT_FILE)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700200 assert isinstance(credentials, service_account.Credentials)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700201 assert project_id == SERVICE_ACCOUNT_FILE_DATA["project_id"]
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700202
203
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700204def test_load_credentials_from_file_service_account_with_scopes():
205 credentials, project_id = _default.load_credentials_from_file(
206 SERVICE_ACCOUNT_FILE, scopes=["https://www.google.com/calendar/feeds"]
207 )
208 assert isinstance(credentials, service_account.Credentials)
209 assert project_id == SERVICE_ACCOUNT_FILE_DATA["project_id"]
210 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
211
212
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700213def test_load_credentials_from_file_service_account_with_quota_project():
214 credentials, project_id = _default.load_credentials_from_file(
215 SERVICE_ACCOUNT_FILE, quota_project_id="project-foo"
216 )
217 assert isinstance(credentials, service_account.Credentials)
218 assert project_id == SERVICE_ACCOUNT_FILE_DATA["project_id"]
219 assert credentials.quota_project_id == "project-foo"
220
221
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700222def test_load_credentials_from_file_service_account_bad_format(tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700223 filename = tmpdir.join("serivce_account_bad.json")
224 filename.write(json.dumps({"type": "service_account"}))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700225
226 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700227 _default.load_credentials_from_file(str(filename))
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700228
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700229 assert excinfo.match(r"Failed to load service account")
230 assert excinfo.match(r"missing fields")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700231
232
bojeil-googled4d7f382021-02-16 12:33:20 -0800233@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
234def test_load_credentials_from_file_external_account_identity_pool(
235 get_project_id, tmpdir
236):
237 config_file = tmpdir.join("config.json")
238 config_file.write(json.dumps(IDENTITY_POOL_DATA))
239 credentials, project_id = _default.load_credentials_from_file(str(config_file))
240
241 assert isinstance(credentials, identity_pool.Credentials)
242 # Since no scopes are specified, the project ID cannot be determined.
243 assert project_id is None
244 assert get_project_id.called
245
246
247@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
248def test_load_credentials_from_file_external_account_aws(get_project_id, tmpdir):
249 config_file = tmpdir.join("config.json")
250 config_file.write(json.dumps(AWS_DATA))
251 credentials, project_id = _default.load_credentials_from_file(str(config_file))
252
253 assert isinstance(credentials, aws.Credentials)
254 # Since no scopes are specified, the project ID cannot be determined.
255 assert project_id is None
256 assert get_project_id.called
257
258
259@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
260def test_load_credentials_from_file_external_account_with_user_and_default_scopes(
261 get_project_id, tmpdir
262):
263 config_file = tmpdir.join("config.json")
264 config_file.write(json.dumps(IDENTITY_POOL_DATA))
265 credentials, project_id = _default.load_credentials_from_file(
266 str(config_file),
267 scopes=["https://www.google.com/calendar/feeds"],
268 default_scopes=["https://www.googleapis.com/auth/cloud-platform"],
269 )
270
271 assert isinstance(credentials, identity_pool.Credentials)
272 # Since scopes are specified, the project ID can be determined.
273 assert project_id is mock.sentinel.project_id
274 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
275 assert credentials.default_scopes == [
276 "https://www.googleapis.com/auth/cloud-platform"
277 ]
278
279
280@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
281def test_load_credentials_from_file_external_account_with_quota_project(
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(
287 str(config_file), quota_project_id="project-foo"
288 )
289
290 assert isinstance(credentials, identity_pool.Credentials)
291 # Since no scopes are specified, the project ID cannot be determined.
292 assert project_id is None
293 assert credentials.quota_project_id == "project-foo"
294
295
296def test_load_credentials_from_file_external_account_bad_format(tmpdir):
297 filename = tmpdir.join("external_account_bad.json")
298 filename.write(json.dumps({"type": "external_account"}))
299
300 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
301 _default.load_credentials_from_file(str(filename))
302
303 assert excinfo.match(
304 "Failed to load external account credentials from {}".format(str(filename))
305 )
306
307
308@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
309def test_load_credentials_from_file_external_account_explicit_request(
310 get_project_id, tmpdir
311):
312 config_file = tmpdir.join("config.json")
313 config_file.write(json.dumps(IDENTITY_POOL_DATA))
314 credentials, project_id = _default.load_credentials_from_file(
315 str(config_file),
316 request=mock.sentinel.request,
317 scopes=["https://www.googleapis.com/auth/cloud-platform"],
318 )
319
320 assert isinstance(credentials, identity_pool.Credentials)
321 # Since scopes are specified, the project ID can be determined.
322 assert project_id is mock.sentinel.project_id
323 get_project_id.assert_called_with(credentials, request=mock.sentinel.request)
324
325
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700326@mock.patch.dict(os.environ, {}, clear=True)
327def test__get_explicit_environ_credentials_no_env():
328 assert _default._get_explicit_environ_credentials() == (None, None)
329
330
arithmetic172811ebaeb2021-09-07 14:38:49 -0700331@pytest.mark.parametrize("quota_project_id", [None, "project-foo"])
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700332@LOAD_FILE_PATCH
arithmetic172811ebaeb2021-09-07 14:38:49 -0700333def test__get_explicit_environ_credentials(load, quota_project_id, monkeypatch):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700334 monkeypatch.setenv(environment_vars.CREDENTIALS, "filename")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700335
arithmetic172811ebaeb2021-09-07 14:38:49 -0700336 credentials, project_id = _default._get_explicit_environ_credentials(
337 quota_project_id=quota_project_id
338 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700339
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700340 assert credentials is MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700341 assert project_id is mock.sentinel.project_id
arithmetic172811ebaeb2021-09-07 14:38:49 -0700342 load.assert_called_with("filename", quota_project_id=quota_project_id)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700343
344
345@LOAD_FILE_PATCH
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700346def test__get_explicit_environ_credentials_no_project_id(load, monkeypatch):
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700347 load.return_value = MOCK_CREDENTIALS, None
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700348 monkeypatch.setenv(environment_vars.CREDENTIALS, "filename")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700349
350 credentials, project_id = _default._get_explicit_environ_credentials()
351
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700352 assert credentials is MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700353 assert project_id is None
354
355
arithmetic172811ebaeb2021-09-07 14:38:49 -0700356@pytest.mark.parametrize("quota_project_id", [None, "project-foo"])
arithmetic1728333cb762021-02-25 15:42:32 -0800357@mock.patch(
358 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
359)
360@mock.patch("google.auth._default._get_gcloud_sdk_credentials", autospec=True)
361def test__get_explicit_environ_credentials_fallback_to_gcloud(
arithmetic172811ebaeb2021-09-07 14:38:49 -0700362 get_gcloud_creds, get_adc_path, quota_project_id, monkeypatch
arithmetic1728333cb762021-02-25 15:42:32 -0800363):
364 # Set explicit credentials path to cloud sdk credentials path.
365 get_adc_path.return_value = "filename"
366 monkeypatch.setenv(environment_vars.CREDENTIALS, "filename")
367
arithmetic172811ebaeb2021-09-07 14:38:49 -0700368 _default._get_explicit_environ_credentials(quota_project_id=quota_project_id)
arithmetic1728333cb762021-02-25 15:42:32 -0800369
370 # Check we fall back to cloud sdk flow since explicit credentials path is
371 # cloud sdk credentials path
arithmetic172811ebaeb2021-09-07 14:38:49 -0700372 get_gcloud_creds.assert_called_with(quota_project_id=quota_project_id)
arithmetic1728333cb762021-02-25 15:42:32 -0800373
374
arithmetic172811ebaeb2021-09-07 14:38:49 -0700375@pytest.mark.parametrize("quota_project_id", [None, "project-foo"])
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700376@LOAD_FILE_PATCH
Jon Wayne Parrott8784b232016-11-10 12:53:55 -0800377@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700378 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
379)
arithmetic172811ebaeb2021-09-07 14:38:49 -0700380def test__get_gcloud_sdk_credentials(get_adc_path, load, quota_project_id):
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700381 get_adc_path.return_value = SERVICE_ACCOUNT_FILE
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700382
arithmetic172811ebaeb2021-09-07 14:38:49 -0700383 credentials, project_id = _default._get_gcloud_sdk_credentials(
384 quota_project_id=quota_project_id
385 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700386
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700387 assert credentials is MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700388 assert project_id is mock.sentinel.project_id
arithmetic172811ebaeb2021-09-07 14:38:49 -0700389 load.assert_called_with(SERVICE_ACCOUNT_FILE, quota_project_id=quota_project_id)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700390
391
Jon Wayne Parrott8784b232016-11-10 12:53:55 -0800392@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700393 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
394)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700395def test__get_gcloud_sdk_credentials_non_existent(get_adc_path, tmpdir):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700396 non_existent = tmpdir.join("non-existent")
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700397 get_adc_path.return_value = str(non_existent)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700398
399 credentials, project_id = _default._get_gcloud_sdk_credentials()
400
401 assert credentials is None
402 assert project_id is None
403
404
405@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700406 "google.auth._cloud_sdk.get_project_id",
407 return_value=mock.sentinel.project_id,
408 autospec=True,
409)
410@mock.patch("os.path.isfile", return_value=True, autospec=True)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700411@LOAD_FILE_PATCH
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700412def test__get_gcloud_sdk_credentials_project_id(load, unused_isfile, get_project_id):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700413 # Don't return a project ID from load file, make the function check
414 # the Cloud SDK project.
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700415 load.return_value = MOCK_CREDENTIALS, None
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700416
417 credentials, project_id = _default._get_gcloud_sdk_credentials()
418
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700419 assert credentials == MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700420 assert project_id == mock.sentinel.project_id
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700421 assert get_project_id.called
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700422
423
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700424@mock.patch("google.auth._cloud_sdk.get_project_id", return_value=None, autospec=True)
425@mock.patch("os.path.isfile", return_value=True)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700426@LOAD_FILE_PATCH
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700427def test__get_gcloud_sdk_credentials_no_project_id(load, unused_isfile, get_project_id):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700428 # Don't return a project ID from load file, make the function check
429 # the Cloud SDK project.
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700430 load.return_value = MOCK_CREDENTIALS, None
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700431
432 credentials, project_id = _default._get_gcloud_sdk_credentials()
433
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700434 assert credentials == MOCK_CREDENTIALS
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700435 assert project_id is None
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700436 assert get_project_id.called
437
438
439class _AppIdentityModule(object):
440 """The interface of the App Idenity app engine module.
441 See https://cloud.google.com/appengine/docs/standard/python/refdocs\
442 /google.appengine.api.app_identity.app_identity
443 """
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700444
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700445 def get_application_id(self):
446 raise NotImplementedError()
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700447
448
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700449@pytest.fixture
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700450def app_identity(monkeypatch):
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700451 """Mocks the app_identity module for google.auth.app_engine."""
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700452 app_identity_module = mock.create_autospec(_AppIdentityModule, instance=True)
453 monkeypatch.setattr(app_engine, "app_identity", app_identity_module)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700454 yield app_identity_module
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700455
456
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400457@mock.patch.dict(os.environ)
458def test__get_gae_credentials_gen1(app_identity):
459 os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python27"
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700460 app_identity.get_application_id.return_value = mock.sentinel.project
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700461
462 credentials, project_id = _default._get_gae_credentials()
463
464 assert isinstance(credentials, app_engine.Credentials)
465 assert project_id == mock.sentinel.project
466
467
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400468@mock.patch.dict(os.environ)
469def test__get_gae_credentials_gen2():
470 os.environ["GAE_RUNTIME"] = "python37"
471 credentials, project_id = _default._get_gae_credentials()
472 assert credentials is None
473 assert project_id is None
474
475
476@mock.patch.dict(os.environ)
477def test__get_gae_credentials_gen2_backwards_compat():
478 # compat helpers may copy GAE_RUNTIME to APPENGINE_RUNTIME
479 # for backwards compatibility with code that relies on it
480 os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python37"
481 os.environ["GAE_RUNTIME"] = "python37"
482 credentials, project_id = _default._get_gae_credentials()
483 assert credentials is None
484 assert project_id is None
485
486
487def test__get_gae_credentials_env_unset():
488 assert environment_vars.LEGACY_APPENGINE_RUNTIME not in os.environ
489 assert "GAE_RUNTIME" not in os.environ
490 credentials, project_id = _default._get_gae_credentials()
491 assert credentials is None
492 assert project_id is None
493
494
495@mock.patch.dict(os.environ)
James Wilson6e0781b2018-12-20 20:38:52 -0500496def test__get_gae_credentials_no_app_engine():
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400497 # test both with and without LEGACY_APPENGINE_RUNTIME setting
498 assert environment_vars.LEGACY_APPENGINE_RUNTIME not in os.environ
499
James Wilson6e0781b2018-12-20 20:38:52 -0500500 import sys
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700501
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400502 with mock.patch.dict(sys.modules, {"google.auth.app_engine": None}):
503 credentials, project_id = _default._get_gae_credentials()
504 assert credentials is None
505 assert project_id is None
506
507 os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python27"
James Wilson6e0781b2018-12-20 20:38:52 -0500508 credentials, project_id = _default._get_gae_credentials()
509 assert credentials is None
510 assert project_id is None
511
512
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400513@mock.patch.dict(os.environ)
514@mock.patch.object(app_engine, "app_identity", new=None)
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700515def test__get_gae_credentials_no_apis():
Zev Goldstein7f7d92d2021-07-23 15:52:46 -0400516 # test both with and without LEGACY_APPENGINE_RUNTIME setting
517 assert environment_vars.LEGACY_APPENGINE_RUNTIME not in os.environ
518
519 credentials, project_id = _default._get_gae_credentials()
520 assert credentials is None
521 assert project_id is None
522
523 os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python27"
524 credentials, project_id = _default._get_gae_credentials()
525 assert credentials is None
526 assert project_id is None
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700527
528
529@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700530 "google.auth.compute_engine._metadata.ping", return_value=True, autospec=True
531)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700532@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700533 "google.auth.compute_engine._metadata.get_project_id",
534 return_value="example-project",
535 autospec=True,
536)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700537def test__get_gce_credentials(unused_get, unused_ping):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700538 credentials, project_id = _default._get_gce_credentials()
539
540 assert isinstance(credentials, compute_engine.Credentials)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700541 assert project_id == "example-project"
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700542
543
Jon Wayne Parrott8784b232016-11-10 12:53:55 -0800544@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700545 "google.auth.compute_engine._metadata.ping", return_value=False, autospec=True
546)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700547def test__get_gce_credentials_no_ping(unused_ping):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700548 credentials, project_id = _default._get_gce_credentials()
549
550 assert credentials is None
551 assert project_id is None
552
553
554@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700555 "google.auth.compute_engine._metadata.ping", return_value=True, autospec=True
556)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700557@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700558 "google.auth.compute_engine._metadata.get_project_id",
559 side_effect=exceptions.TransportError(),
560 autospec=True,
561)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700562def test__get_gce_credentials_no_project_id(unused_get, unused_ping):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700563 credentials, project_id = _default._get_gce_credentials()
564
565 assert isinstance(credentials, compute_engine.Credentials)
566 assert project_id is None
567
568
James Wilson6e0781b2018-12-20 20:38:52 -0500569def test__get_gce_credentials_no_compute_engine():
570 import sys
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700571
572 with mock.patch.dict("sys.modules"):
573 sys.modules["google.auth.compute_engine"] = None
James Wilson6e0781b2018-12-20 20:38:52 -0500574 credentials, project_id = _default._get_gce_credentials()
575 assert credentials is None
576 assert project_id is None
577
578
Jon Wayne Parrott8784b232016-11-10 12:53:55 -0800579@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700580 "google.auth.compute_engine._metadata.ping", return_value=False, autospec=True
581)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700582def test__get_gce_credentials_explicit_request(ping):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700583 _default._get_gce_credentials(mock.sentinel.request)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700584 ping.assert_called_with(request=mock.sentinel.request)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700585
586
587@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700588 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700589 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700590 autospec=True,
591)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700592def test_default_early_out(unused_get):
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700593 assert _default.default() == (MOCK_CREDENTIALS, mock.sentinel.project_id)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700594
595
596@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700597 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700598 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700599 autospec=True,
600)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700601def test_default_explict_project_id(unused_get, monkeypatch):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700602 monkeypatch.setenv(environment_vars.PROJECT, "explicit-env")
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700603 assert _default.default() == (MOCK_CREDENTIALS, "explicit-env")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700604
605
606@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700607 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700608 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700609 autospec=True,
610)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700611def test_default_explict_legacy_project_id(unused_get, monkeypatch):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700612 monkeypatch.setenv(environment_vars.LEGACY_PROJECT, "explicit-env")
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700613 assert _default.default() == (MOCK_CREDENTIALS, "explicit-env")
Jon Wayne Parrottce37cba2016-11-07 16:41:42 -0800614
615
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700616@mock.patch("logging.Logger.warning", autospec=True)
Jon Wayne Parrottce37cba2016-11-07 16:41:42 -0800617@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700618 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700619 return_value=(MOCK_CREDENTIALS, None),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700620 autospec=True,
621)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600622@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700623 "google.auth._default._get_gcloud_sdk_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700624 return_value=(MOCK_CREDENTIALS, None),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700625 autospec=True,
626)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600627@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700628 "google.auth._default._get_gae_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700629 return_value=(MOCK_CREDENTIALS, None),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700630 autospec=True,
631)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600632@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700633 "google.auth._default._get_gce_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700634 return_value=(MOCK_CREDENTIALS, None),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700635 autospec=True,
636)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600637def test_default_without_project_id(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700638 unused_gce, unused_gae, unused_sdk, unused_explicit, logger_warning
639):
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700640 assert _default.default() == (MOCK_CREDENTIALS, None)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600641 logger_warning.assert_called_with(mock.ANY, mock.ANY, mock.ANY)
642
643
644@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700645 "google.auth._default._get_explicit_environ_credentials",
646 return_value=(None, None),
647 autospec=True,
648)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700649@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700650 "google.auth._default._get_gcloud_sdk_credentials",
651 return_value=(None, None),
652 autospec=True,
653)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700654@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700655 "google.auth._default._get_gae_credentials",
656 return_value=(None, None),
657 autospec=True,
658)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700659@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700660 "google.auth._default._get_gce_credentials",
661 return_value=(None, None),
662 autospec=True,
663)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700664def test_default_fail(unused_gce, unused_gae, unused_sdk, unused_explicit):
665 with pytest.raises(exceptions.DefaultCredentialsError):
666 assert _default.default()
Jon Wayne Parrott8a7e5062016-11-07 16:45:17 -0800667
668
669@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700670 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700671 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700672 autospec=True,
673)
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700674@mock.patch(
675 "google.auth.credentials.with_scopes_if_required",
676 return_value=MOCK_CREDENTIALS,
677 autospec=True,
678)
Jacob Hayes15af07b2017-12-13 14:09:47 -0600679def test_default_scoped(with_scopes, unused_get):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700680 scopes = ["one", "two"]
Jon Wayne Parrott8a7e5062016-11-07 16:45:17 -0800681
682 credentials, project_id = _default.default(scopes=scopes)
683
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700684 assert credentials == with_scopes.return_value
Jon Wayne Parrott8a7e5062016-11-07 16:45:17 -0800685 assert project_id == mock.sentinel.project_id
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700686 with_scopes.assert_called_once_with(MOCK_CREDENTIALS, scopes, default_scopes=None)
James Wilson6e0781b2018-12-20 20:38:52 -0500687
688
689@mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700690 "google.auth._default._get_explicit_environ_credentials",
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700691 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700692 autospec=True,
693)
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700694def test_default_quota_project(with_quota_project):
695 credentials, project_id = _default.default(quota_project_id="project-foo")
696
697 MOCK_CREDENTIALS.with_quota_project.assert_called_once_with("project-foo")
698 assert project_id == mock.sentinel.project_id
699
700
701@mock.patch(
702 "google.auth._default._get_explicit_environ_credentials",
703 return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
704 autospec=True,
705)
James Wilson6e0781b2018-12-20 20:38:52 -0500706def test_default_no_app_engine_compute_engine_module(unused_get):
707 """
708 google.auth.compute_engine and google.auth.app_engine are both optional
709 to allow not including them when using this package. This verifies
710 that default fails gracefully if these modules are absent
711 """
712 import sys
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700713
714 with mock.patch.dict("sys.modules"):
715 sys.modules["google.auth.compute_engine"] = None
716 sys.modules["google.auth.app_engine"] = None
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700717 assert _default.default() == (MOCK_CREDENTIALS, mock.sentinel.project_id)
bojeil-googled4d7f382021-02-16 12:33:20 -0800718
719
720@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
721def test_default_environ_external_credentials(get_project_id, monkeypatch, tmpdir):
722 config_file = tmpdir.join("config.json")
723 config_file.write(json.dumps(IDENTITY_POOL_DATA))
724 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
725
726 credentials, project_id = _default.default()
727
728 assert isinstance(credentials, identity_pool.Credentials)
729 # Without scopes, project ID cannot be determined.
730 assert project_id is None
731
732
733@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
734def test_default_environ_external_credentials_with_user_and_default_scopes_and_quota_project_id(
735 get_project_id, monkeypatch, tmpdir
736):
737 config_file = tmpdir.join("config.json")
738 config_file.write(json.dumps(IDENTITY_POOL_DATA))
739 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
740
741 credentials, project_id = _default.default(
742 scopes=["https://www.google.com/calendar/feeds"],
743 default_scopes=["https://www.googleapis.com/auth/cloud-platform"],
744 quota_project_id="project-foo",
745 )
746
747 assert isinstance(credentials, identity_pool.Credentials)
748 assert project_id is mock.sentinel.project_id
749 assert credentials.quota_project_id == "project-foo"
750 assert credentials.scopes == ["https://www.google.com/calendar/feeds"]
751 assert credentials.default_scopes == [
752 "https://www.googleapis.com/auth/cloud-platform"
753 ]
754
755
756@EXTERNAL_ACCOUNT_GET_PROJECT_ID_PATCH
757def test_default_environ_external_credentials_explicit_request_with_scopes(
758 get_project_id, monkeypatch, tmpdir
759):
760 config_file = tmpdir.join("config.json")
761 config_file.write(json.dumps(IDENTITY_POOL_DATA))
762 monkeypatch.setenv(environment_vars.CREDENTIALS, str(config_file))
763
764 credentials, project_id = _default.default(
765 request=mock.sentinel.request,
766 scopes=["https://www.googleapis.com/auth/cloud-platform"],
767 )
768
769 assert isinstance(credentials, identity_pool.Credentials)
770 assert project_id is mock.sentinel.project_id
771 # default() will initialize new credentials via with_scopes_if_required
772 # and potentially with_quota_project.
773 # As a result the caller of get_project_id() will not match the returned
774 # credentials.
775 get_project_id.assert_called_with(mock.ANY, request=mock.sentinel.request)
776
777
778def test_default_environ_external_credentials_bad_format(monkeypatch, tmpdir):
779 filename = tmpdir.join("external_account_bad.json")
780 filename.write(json.dumps({"type": "external_account"}))
781 monkeypatch.setenv(environment_vars.CREDENTIALS, str(filename))
782
783 with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
784 _default.default()
785
786 assert excinfo.match(
787 "Failed to load external account credentials from {}".format(str(filename))
788 )
arithmetic172811ebaeb2021-09-07 14:38:49 -0700789
790
791@mock.patch(
792 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
793)
794def test_default_warning_without_quota_project_id_for_user_creds(get_adc_path):
795 get_adc_path.return_value = AUTHORIZED_USER_CLOUD_SDK_FILE
796
797 with pytest.warns(UserWarning, match="Cloud SDK"):
798 credentials, project_id = _default.default(quota_project_id=None)
799
800
801@mock.patch(
802 "google.auth._cloud_sdk.get_application_default_credentials_path", autospec=True
803)
804def test_default_no_warning_with_quota_project_id_for_user_creds(get_adc_path):
805 get_adc_path.return_value = AUTHORIZED_USER_CLOUD_SDK_FILE
806
807 credentials, project_id = _default.default(quota_project_id="project-foo")