blob: 836c33915bed39ba1148776aebc2709ecf8197f9 [file] [log] [blame]
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -07001# Copyright 2015 Google Inc.
2#
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
15"""Application default credentials.
16
17Implements application default credentials and project ID detection.
18"""
19
20import io
21import json
22import logging
23import os
Thea Flowersa8d93482018-05-31 14:52:06 -070024import warnings
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070025
Danny Hermes895e3692017-11-09 11:35:57 -080026import six
27
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070028from google.auth import environment_vars
29from google.auth import exceptions
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070030import google.auth.transport._http_client
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070031
32_LOGGER = logging.getLogger(__name__)
33
34# Valid types accepted for file-based credentials.
Bu Sun Kim9eec0912019-10-21 17:04:21 -070035_AUTHORIZED_USER_TYPE = "authorized_user"
36_SERVICE_ACCOUNT_TYPE = "service_account"
bojeil-google5dcd2b12021-02-09 11:05:00 -080037_EXTERNAL_ACCOUNT_TYPE = "external_account"
38_VALID_TYPES = (_AUTHORIZED_USER_TYPE, _SERVICE_ACCOUNT_TYPE, _EXTERNAL_ACCOUNT_TYPE)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070039
40# Help message when no credentials can be found.
Thea Flowersa8d93482018-05-31 14:52:06 -070041_HELP_MESSAGE = """\
42Could not automatically determine credentials. Please set {env} or \
43explicitly create credentials and re-run the application. For more \
44information, please see \
Christopher Wilcoxf1028252018-09-21 10:03:04 -070045https://cloud.google.com/docs/authentication/getting-started
Bu Sun Kim9eec0912019-10-21 17:04:21 -070046""".format(
47 env=environment_vars.CREDENTIALS
48).strip()
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070049
Thea Flowersa8d93482018-05-31 14:52:06 -070050# Warning when using Cloud SDK user credentials
51_CLOUD_SDK_CREDENTIALS_WARNING = """\
52Your application has authenticated using end user credentials from Google \
arithmetic1728f30b45a2020-06-17 23:36:04 -070053Cloud SDK without a quota project. You might receive a "quota exceeded" \
54or "API not enabled" error. We recommend you rerun \
55`gcloud auth application-default login` and make sure a quota project is \
56added. Or you can use service accounts instead. For more information \
57about service accounts, see https://cloud.google.com/docs/authentication/"""
Thea Flowersa8d93482018-05-31 14:52:06 -070058
59
60def _warn_about_problematic_credentials(credentials):
61 """Determines if the credentials are problematic.
62
63 Credentials from the Cloud SDK that are associated with Cloud SDK's project
64 are problematic because they may not have APIs enabled and have limited
65 quota. If this is the case, warn about it.
66 """
67 from google.auth import _cloud_sdk
Bu Sun Kim9eec0912019-10-21 17:04:21 -070068
Thea Flowersa8d93482018-05-31 14:52:06 -070069 if credentials.client_id == _cloud_sdk.CLOUD_SDK_CLIENT_ID:
70 warnings.warn(_CLOUD_SDK_CREDENTIALS_WARNING)
71
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070072
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -070073def load_credentials_from_file(
bojeil-google5dcd2b12021-02-09 11:05:00 -080074 filename, scopes=None, default_scopes=None, quota_project_id=None, request=None
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -070075):
Bu Sun Kim15d5fa92020-06-18 14:05:40 -070076 """Loads Google credentials from a file.
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070077
bojeil-google5dcd2b12021-02-09 11:05:00 -080078 The credentials file must be a service account key, stored authorized
79 user credentials or external account credentials.
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070080
81 Args:
82 filename (str): The full path to the credentials file.
Bu Sun Kim15d5fa92020-06-18 14:05:40 -070083 scopes (Optional[Sequence[str]]): The list of scopes for the credentials. If
84 specified, the credentials will automatically be scoped if
Bu Sun Kim3dda7b22020-07-09 10:39:39 -070085 necessary
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -070086 default_scopes (Optional[Sequence[str]]): Default scopes passed by a
87 Google client library. Use 'scopes' for user-defined scopes.
Bu Sun Kim3dda7b22020-07-09 10:39:39 -070088 quota_project_id (Optional[str]): The project ID used for
bojeil-google5dcd2b12021-02-09 11:05:00 -080089 quota and billing.
90 request (Optional[google.auth.transport.Request]): An object used to make
91 HTTP requests. This is used to determine the associated project ID
92 for a workload identity pool resource (external account credentials).
93 If not specified, then it will use a
94 google.auth.transport.requests.Request client to make requests.
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -070095
96 Returns:
97 Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded
98 credentials and the project ID. Authorized user credentials do not
bojeil-google5dcd2b12021-02-09 11:05:00 -080099 have the project ID information. External account credentials project
100 IDs may not always be determined.
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700101
102 Raises:
103 google.auth.exceptions.DefaultCredentialsError: if the file is in the
weitaiting6e86c932017-08-12 03:26:59 +0800104 wrong format or is missing.
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700105 """
weitaiting6e86c932017-08-12 03:26:59 +0800106 if not os.path.exists(filename):
107 raise exceptions.DefaultCredentialsError(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700108 "File {} was not found.".format(filename)
109 )
weitaiting6e86c932017-08-12 03:26:59 +0800110
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700111 with io.open(filename, "r") as file_obj:
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700112 try:
113 info = json.load(file_obj)
Danny Hermes895e3692017-11-09 11:35:57 -0800114 except ValueError as caught_exc:
115 new_exc = exceptions.DefaultCredentialsError(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700116 "File {} is not a valid json file.".format(filename), caught_exc
117 )
Danny Hermes895e3692017-11-09 11:35:57 -0800118 six.raise_from(new_exc, caught_exc)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700119
120 # The type key should indicate that the file is either a service account
121 # credentials file or an authorized user credentials file.
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700122 credential_type = info.get("type")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700123
124 if credential_type == _AUTHORIZED_USER_TYPE:
arithmetic1728772dac62020-03-27 14:34:13 -0700125 from google.oauth2 import credentials
Jon Wayne Parrott6dca98c2016-12-01 15:34:59 -0800126
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700127 try:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700128 credentials = credentials.Credentials.from_authorized_user_info(
129 info, scopes=scopes
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700130 )
Danny Hermes895e3692017-11-09 11:35:57 -0800131 except ValueError as caught_exc:
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700132 msg = "Failed to load authorized user credentials from {}".format(filename)
Danny Hermes0a93e872017-11-09 12:18:58 -0800133 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc)
Danny Hermes895e3692017-11-09 11:35:57 -0800134 six.raise_from(new_exc, caught_exc)
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700135 if quota_project_id:
136 credentials = credentials.with_quota_project(quota_project_id)
arithmetic1728f30b45a2020-06-17 23:36:04 -0700137 if not credentials.quota_project_id:
138 _warn_about_problematic_credentials(credentials)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700139 return credentials, None
140
141 elif credential_type == _SERVICE_ACCOUNT_TYPE:
Jon Wayne Parrott6dca98c2016-12-01 15:34:59 -0800142 from google.oauth2 import service_account
143
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700144 try:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700145 credentials = service_account.Credentials.from_service_account_info(
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700146 info, scopes=scopes, default_scopes=default_scopes
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700147 )
Danny Hermes895e3692017-11-09 11:35:57 -0800148 except ValueError as caught_exc:
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700149 msg = "Failed to load service account credentials from {}".format(filename)
Danny Hermes0a93e872017-11-09 12:18:58 -0800150 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc)
Danny Hermes895e3692017-11-09 11:35:57 -0800151 six.raise_from(new_exc, caught_exc)
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700152 if quota_project_id:
153 credentials = credentials.with_quota_project(quota_project_id)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700154 return credentials, info.get("project_id")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700155
bojeil-google5dcd2b12021-02-09 11:05:00 -0800156 elif credential_type == _EXTERNAL_ACCOUNT_TYPE:
157 credentials, project_id = _get_external_account_credentials(
158 info,
159 filename,
160 scopes=scopes,
161 default_scopes=default_scopes,
162 request=request,
163 )
164 if quota_project_id:
165 credentials = credentials.with_quota_project(quota_project_id)
166 return credentials, project_id
167
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700168 else:
169 raise exceptions.DefaultCredentialsError(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700170 "The file {file} does not have a valid type. "
171 "Type is {type}, expected one of {valid_types}.".format(
172 file=filename, type=credential_type, valid_types=_VALID_TYPES
173 )
174 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700175
176
177def _get_gcloud_sdk_credentials():
178 """Gets the credentials and project ID from the Cloud SDK."""
Jon Wayne Parrott6dca98c2016-12-01 15:34:59 -0800179 from google.auth import _cloud_sdk
180
Vaughan Hiltsecd88d42020-07-21 16:25:51 -0400181 _LOGGER.debug("Checking Cloud SDK credentials as part of auth process...")
182
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700183 # Check if application default credentials exist.
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700184 credentials_filename = _cloud_sdk.get_application_default_credentials_path()
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700185
186 if not os.path.isfile(credentials_filename):
Vaughan Hiltsecd88d42020-07-21 16:25:51 -0400187 _LOGGER.debug("Cloud SDK credentials not found on disk; not using them")
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700188 return None, None
189
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700190 credentials, project_id = load_credentials_from_file(credentials_filename)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700191
192 if not project_id:
193 project_id = _cloud_sdk.get_project_id()
194
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700195 return credentials, project_id
196
197
bojeil-google5dcd2b12021-02-09 11:05:00 -0800198def _get_explicit_environ_credentials(request=None, scopes=None, default_scopes=None):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700199 """Gets credentials from the GOOGLE_APPLICATION_CREDENTIALS environment
bojeil-google5dcd2b12021-02-09 11:05:00 -0800200 variable.
201
202 Args:
203 request (Optional[google.auth.transport.Request]): An object used to make
204 HTTP requests. This is used to determine the associated project ID
205 for a workload identity pool resource (external account credentials).
206 If not specified, then it will use a
207 google.auth.transport.requests.Request client to make requests.
208 scopes (Optional[Sequence[str]]): The list of scopes for the credentials. If
209 specified, the credentials will automatically be scoped if
210 necessary.
211 default_scopes (Optional[Sequence[str]]): Default scopes passed by a
212 Google client library. Use 'scopes' for user-defined scopes.
213
214 Returns:
215 Tuple[Optional[google.auth.credentials.Credentials], Optional[str]]: Loaded
216 credentials and the project ID. Authorized user credentials do not
217 have the project ID information. External account credentials project
218 IDs may not always be determined.
219 """
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700220 explicit_file = os.environ.get(environment_vars.CREDENTIALS)
221
Vaughan Hiltsecd88d42020-07-21 16:25:51 -0400222 _LOGGER.debug(
223 "Checking %s for explicit credentials as part of auth process...", explicit_file
224 )
225
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700226 if explicit_file is not None:
Bu Sun Kim15d5fa92020-06-18 14:05:40 -0700227 credentials, project_id = load_credentials_from_file(
bojeil-google5dcd2b12021-02-09 11:05:00 -0800228 os.environ[environment_vars.CREDENTIALS],
229 scopes=scopes,
230 default_scopes=default_scopes,
231 quota_project_id=None,
232 request=request,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700233 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700234
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700235 return credentials, project_id
236
237 else:
238 return None, None
239
240
241def _get_gae_credentials():
242 """Gets Google App Engine App Identity credentials and project ID."""
James Wilson6e0781b2018-12-20 20:38:52 -0500243 # While this library is normally bundled with app_engine, there are
244 # some cases where it's not available, so we tolerate ImportError.
245 try:
Vaughan Hiltsecd88d42020-07-21 16:25:51 -0400246 _LOGGER.debug("Checking for App Engine runtime as part of auth process...")
James Wilson6e0781b2018-12-20 20:38:52 -0500247 import google.auth.app_engine as app_engine
248 except ImportError:
Vaughan Hiltsecd88d42020-07-21 16:25:51 -0400249 _LOGGER.warning("Import of App Engine auth library failed.")
James Wilson6e0781b2018-12-20 20:38:52 -0500250 return None, None
Jon Wayne Parrott6dca98c2016-12-01 15:34:59 -0800251
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700252 try:
253 credentials = app_engine.Credentials()
254 project_id = app_engine.get_project_id()
255 return credentials, project_id
256 except EnvironmentError:
Vaughan Hiltsecd88d42020-07-21 16:25:51 -0400257 _LOGGER.debug(
258 "No App Engine library was found so cannot authentication via App Engine Identity Credentials."
259 )
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -0700260 return None, None
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700261
262
263def _get_gce_credentials(request=None):
264 """Gets credentials and project ID from the GCE Metadata Service."""
265 # Ping requires a transport, but we want application default credentials
266 # to require no arguments. So, we'll use the _http_client transport which
267 # uses http.client. This is only acceptable because the metadata server
268 # doesn't do SSL and never requires proxies.
James Wilson6e0781b2018-12-20 20:38:52 -0500269
270 # While this library is normally bundled with compute_engine, there are
271 # some cases where it's not available, so we tolerate ImportError.
272 try:
273 from google.auth import compute_engine
274 from google.auth.compute_engine import _metadata
275 except ImportError:
Vaughan Hiltsecd88d42020-07-21 16:25:51 -0400276 _LOGGER.warning("Import of Compute Engine auth library failed.")
James Wilson6e0781b2018-12-20 20:38:52 -0500277 return None, None
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700278
279 if request is None:
280 request = google.auth.transport._http_client.Request()
281
282 if _metadata.ping(request=request):
283 # Get the project ID.
284 try:
Jon Wayne Parrott5b03ba12016-10-24 13:51:26 -0700285 project_id = _metadata.get_project_id(request=request)
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700286 except exceptions.TransportError:
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700287 project_id = None
288
289 return compute_engine.Credentials(), project_id
290 else:
Vaughan Hiltsecd88d42020-07-21 16:25:51 -0400291 _LOGGER.warning(
292 "Authentication failed using Compute Engine authentication due to unavailable metadata server."
293 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700294 return None, None
295
296
bojeil-google5dcd2b12021-02-09 11:05:00 -0800297def _get_external_account_credentials(
298 info, filename, scopes=None, default_scopes=None, request=None
299):
300 """Loads external account Credentials from the parsed external account info.
301
302 The credentials information must correspond to a supported external account
303 credentials.
304
305 Args:
306 info (Mapping[str, str]): The external account info in Google format.
307 filename (str): The full path to the credentials file.
308 scopes (Optional[Sequence[str]]): The list of scopes for the credentials. If
309 specified, the credentials will automatically be scoped if
310 necessary.
311 default_scopes (Optional[Sequence[str]]): Default scopes passed by a
312 Google client library. Use 'scopes' for user-defined scopes.
313 request (Optional[google.auth.transport.Request]): An object used to make
314 HTTP requests. This is used to determine the associated project ID
315 for a workload identity pool resource (external account credentials).
316 If not specified, then it will use a
317 google.auth.transport.requests.Request client to make requests.
318
319 Returns:
320 Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded
321 credentials and the project ID. External account credentials project
322 IDs may not always be determined.
323
324 Raises:
325 google.auth.exceptions.DefaultCredentialsError: if the info dictionary
326 is in the wrong format or is missing required information.
327 """
328 # There are currently 2 types of external_account credentials.
329 try:
330 # Check if configuration corresponds to an AWS credentials.
331 from google.auth import aws
332
333 credentials = aws.Credentials.from_info(
334 info, scopes=scopes, default_scopes=default_scopes
335 )
336 except ValueError:
337 try:
338 # Check if configuration corresponds to an Identity Pool credentials.
339 from google.auth import identity_pool
340
341 credentials = identity_pool.Credentials.from_info(
342 info, scopes=scopes, default_scopes=default_scopes
343 )
344 except ValueError:
345 # If the configuration is invalid or does not correspond to any
346 # supported external_account credentials, raise an error.
347 raise exceptions.DefaultCredentialsError(
348 "Failed to load external account credentials from {}".format(filename)
349 )
350 if request is None:
351 request = google.auth.transport.requests.Request()
352
353 return credentials, credentials.get_project_id(request=request)
354
355
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700356def default(scopes=None, request=None, quota_project_id=None, default_scopes=None):
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700357 """Gets the default credentials for the current environment.
358
359 `Application Default Credentials`_ provides an easy way to obtain
360 credentials to call Google APIs for server-to-server or local applications.
361 This function acquires credentials from the environment in the following
362 order:
363
364 1. If the environment variable ``GOOGLE_APPLICATION_CREDENTIALS`` is set
365 to the path of a valid service account JSON private key file, then it is
366 loaded and returned. The project ID returned is the project ID defined
367 in the service account file if available (some older files do not
368 contain project ID information).
bojeil-google5dcd2b12021-02-09 11:05:00 -0800369
370 If the environment variable is set to the path of a valid external
371 account JSON configuration file (workload identity federation), then the
372 configuration file is used to determine and retrieve the external
373 credentials from the current environment (AWS, Azure, etc).
374 These will then be exchanged for Google access tokens via the Google STS
375 endpoint.
376 The project ID returned in this case is the one corresponding to the
377 underlying workload identity pool resource if determinable.
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700378 2. If the `Google Cloud SDK`_ is installed and has application default
379 credentials set they are loaded and returned.
380
381 To enable application default credentials with the Cloud SDK run::
382
383 gcloud auth application-default login
384
385 If the Cloud SDK has an active project, the project ID is returned. The
386 active project can be set using::
387
388 gcloud config set project
389
390 3. If the application is running in the `App Engine standard environment`_
David Buxton0323cf32020-10-29 21:26:11 +0000391 (first generation) then the credentials and project ID from the
392 `App Identity Service`_ are used.
393 4. If the application is running in `Compute Engine`_ or `Cloud Run`_ or
394 the `App Engine flexible environment`_ or the `App Engine standard
395 environment`_ (second generation) then the credentials and project ID
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700396 are obtained from the `Metadata Service`_.
397 5. If no credentials are found,
398 :class:`~google.auth.exceptions.DefaultCredentialsError` will be raised.
399
400 .. _Application Default Credentials: https://developers.google.com\
401 /identity/protocols/application-default-credentials
402 .. _Google Cloud SDK: https://cloud.google.com/sdk
403 .. _App Engine standard environment: https://cloud.google.com/appengine
404 .. _App Identity Service: https://cloud.google.com/appengine/docs/python\
405 /appidentity/
406 .. _Compute Engine: https://cloud.google.com/compute
407 .. _App Engine flexible environment: https://cloud.google.com\
408 /appengine/flexible
409 .. _Metadata Service: https://cloud.google.com/compute/docs\
410 /storing-retrieving-metadata
David Buxton0323cf32020-10-29 21:26:11 +0000411 .. _Cloud Run: https://cloud.google.com/run
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700412
413 Example::
414
415 import google.auth
416
417 credentials, project_id = google.auth.default()
418
419 Args:
Jon Wayne Parrott8a7e5062016-11-07 16:45:17 -0800420 scopes (Sequence[str]): The list of scopes for the credentials. If
421 specified, the credentials will automatically be scoped if
422 necessary.
bojeil-google5dcd2b12021-02-09 11:05:00 -0800423 request (Optional[google.auth.transport.Request]): An object used to make
424 HTTP requests. This is used to either detect whether the application
425 is running on Compute Engine or to determine the associated project
426 ID for a workload identity pool resource (external account
427 credentials). If not specified, then it will either use the standard
428 library http client to make requests for Compute Engine credentials
429 or a google.auth.transport.requests.Request client for external
430 account credentials.
431 quota_project_id (Optional[str]): The project ID used for
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700432 quota and billing.
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700433 default_scopes (Optional[Sequence[str]]): Default scopes passed by a
434 Google client library. Use 'scopes' for user-defined scopes.
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700435 Returns:
436 Tuple[~google.auth.credentials.Credentials, Optional[str]]:
437 the current environment's credentials and project ID. Project ID
438 may be None, which indicates that the Project ID could not be
439 ascertained from the environment.
440
441 Raises:
442 ~google.auth.exceptions.DefaultCredentialsError:
443 If no credentials were found, or if the credentials found were
444 invalid.
445 """
Jon Wayne Parrott6dca98c2016-12-01 15:34:59 -0800446 from google.auth.credentials import with_scopes_if_required
447
Jon Wayne Parrottce37cba2016-11-07 16:41:42 -0800448 explicit_project_id = os.environ.get(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700449 environment_vars.PROJECT, os.environ.get(environment_vars.LEGACY_PROJECT)
450 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700451
452 checkers = (
bojeil-google5dcd2b12021-02-09 11:05:00 -0800453 lambda: _get_explicit_environ_credentials(
454 request=request, scopes=scopes, default_scopes=default_scopes
455 ),
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700456 _get_gcloud_sdk_credentials,
457 _get_gae_credentials,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700458 lambda: _get_gce_credentials(request),
459 )
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700460
461 for checker in checkers:
462 credentials, project_id = checker()
463 if credentials is not None:
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700464 credentials = with_scopes_if_required(
465 credentials, scopes, default_scopes=default_scopes
466 )
Bu Sun Kimab2be5d2020-07-15 16:49:27 -0700467 if quota_project_id:
468 credentials = credentials.with_quota_project(quota_project_id)
469
Jacob Hayes15af07b2017-12-13 14:09:47 -0600470 effective_project_id = explicit_project_id or project_id
471 if not effective_project_id:
472 _LOGGER.warning(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700473 "No project ID could be determined. Consider running "
474 "`gcloud config set project` or setting the %s "
475 "environment variable",
476 environment_vars.PROJECT,
477 )
Jacob Hayes15af07b2017-12-13 14:09:47 -0600478 return credentials, effective_project_id
Jon Wayne Parrottaadb3de2016-10-19 09:34:05 -0700479
480 raise exceptions.DefaultCredentialsError(_HELP_MESSAGE)