Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/auth/_default.py: 18%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

218 statements  

1# 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""" 

19from __future__ import annotations 

20 

21import io 

22import json 

23import logging 

24import os 

25from typing import Optional, Sequence, TYPE_CHECKING 

26import warnings 

27 

28from google.auth import environment_vars 

29from google.auth import exceptions 

30 

31if TYPE_CHECKING: # pragma: NO COVER 

32 import google.auth.credentials.Credentials # type: ignore 

33 import google.auth.transport.Request # type: ignore 

34 

35_LOGGER = logging.getLogger(__name__) 

36 

37# Valid types accepted for file-based credentials. 

38_AUTHORIZED_USER_TYPE = "authorized_user" 

39_SERVICE_ACCOUNT_TYPE = "service_account" 

40_EXTERNAL_ACCOUNT_TYPE = "external_account" 

41_EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = "external_account_authorized_user" 

42_IMPERSONATED_SERVICE_ACCOUNT_TYPE = "impersonated_service_account" 

43_GDCH_SERVICE_ACCOUNT_TYPE = "gdch_service_account" 

44_VALID_TYPES = ( 

45 _AUTHORIZED_USER_TYPE, 

46 _SERVICE_ACCOUNT_TYPE, 

47 _EXTERNAL_ACCOUNT_TYPE, 

48 _EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE, 

49 _IMPERSONATED_SERVICE_ACCOUNT_TYPE, 

50 _GDCH_SERVICE_ACCOUNT_TYPE, 

51) 

52 

53# Help message when no credentials can be found. 

54_CLOUD_SDK_MISSING_CREDENTIALS = """\ 

55Your default credentials were not found. To set up Application Default Credentials, \ 

56see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.\ 

57""" 

58 

59# Warning when using Cloud SDK user credentials 

60_CLOUD_SDK_CREDENTIALS_WARNING = """\ 

61Your application has authenticated using end user credentials from Google \ 

62Cloud SDK without a quota project. You might receive a "quota exceeded" \ 

63or "API not enabled" error. See the following page for troubleshooting: \ 

64https://cloud.google.com/docs/authentication/adc-troubleshooting/user-creds. \ 

65""" 

66 

67_GENERIC_LOAD_METHOD_WARNING = """\ 

68The {} method is deprecated because of a potential security risk. 

69 

70This method does not validate the credential configuration. The security 

71risk occurs when a credential configuration is accepted from a source that 

72is not under your control and used without validation on your side. 

73 

74If you know that you will be loading credential configurations of a 

75specific type, it is recommended to use a credential-type-specific 

76load method. 

77This will ensure that an unexpected credential type with potential for 

78malicious intent is not loaded unintentionally. You might still have to do 

79validation for certain credential types. Please follow the recommendations 

80for that method. For example, if you want to load only service accounts, 

81you can create the service account credentials explicitly: 

82 

83``` 

84from google.oauth2 import service_account 

85creds = service_account.Credentials.from_service_account_file(filename) 

86``` 

87 

88If you are loading your credential configuration from an untrusted source and have 

89not mitigated the risks (e.g. by validating the configuration yourself), make 

90these changes as soon as possible to prevent security risks to your environment. 

91 

92Regardless of the method used, it is always your responsibility to validate 

93configurations received from external sources. 

94 

95Refer to https://cloud.google.com/docs/authentication/external/externally-sourced-credentials 

96for more details. 

97""" 

98 

99# The subject token type used for AWS external_account credentials. 

100_AWS_SUBJECT_TOKEN_TYPE = "urn:ietf:params:aws:token-type:aws4_request" 

101 

102 

103def _warn_about_problematic_credentials(credentials): 

104 """Determines if the credentials are problematic. 

105 

106 Credentials from the Cloud SDK that are associated with Cloud SDK's project 

107 are problematic because they may not have APIs enabled and have limited 

108 quota. If this is the case, warn about it. 

109 """ 

110 from google.auth import _cloud_sdk 

111 

112 if credentials.client_id == _cloud_sdk.CLOUD_SDK_CLIENT_ID: 

113 warnings.warn(_CLOUD_SDK_CREDENTIALS_WARNING) 

114 

115 

116def _warn_about_generic_load_method(method_name): # pragma: NO COVER 

117 """Warns that a generic load method is being used. 

118 

119 This is to discourage use of the generic load methods in favor of 

120 more specific methods. The generic methods are more likely to lead to 

121 security issues if the input is not validated. 

122 

123 Args: 

124 method_name (str): The name of the method being used. 

125 """ 

126 

127 warnings.warn(_GENERIC_LOAD_METHOD_WARNING.format(method_name), DeprecationWarning) 

128 

129 

130def load_credentials_from_file( 

131 filename, scopes=None, default_scopes=None, quota_project_id=None, request=None 

132): 

133 """Loads Google credentials from a file. 

134 

135 The credentials file must be a service account key, stored authorized 

136 user credentials, external account credentials, or impersonated service 

137 account credentials. 

138 

139 .. warning:: 

140 Important: If you accept a credential configuration (credential JSON/File/Stream) 

141 from an external source for authentication to Google Cloud Platform, you must 

142 validate it before providing it to any Google API or client library. Providing an 

143 unvalidated credential configuration to Google APIs or libraries can compromise 

144 the security of your systems and data. For more information, refer to 

145 `Validate credential configurations from external sources`_. 

146 

147 .. _Validate credential configurations from external sources: 

148 https://cloud.google.com/docs/authentication/external/externally-sourced-credentials 

149 

150 Args: 

151 filename (str): The full path to the credentials file. 

152 scopes (Optional[Sequence[str]]): The list of scopes for the credentials. If 

153 specified, the credentials will automatically be scoped if 

154 necessary 

155 default_scopes (Optional[Sequence[str]]): Default scopes passed by a 

156 Google client library. Use 'scopes' for user-defined scopes. 

157 quota_project_id (Optional[str]): The project ID used for 

158 quota and billing. 

159 request (Optional[google.auth.transport.Request]): An object used to make 

160 HTTP requests. This is used to determine the associated project ID 

161 for a workload identity pool resource (external account credentials). 

162 If not specified, then it will use a 

163 google.auth.transport.requests.Request client to make requests. 

164 

165 Returns: 

166 Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded 

167 credentials and the project ID. Authorized user credentials do not 

168 have the project ID information. External account credentials project 

169 IDs may not always be determined. 

170 

171 Raises: 

172 google.auth.exceptions.DefaultCredentialsError: if the file is in the 

173 wrong format or is missing. 

174 """ 

175 _warn_about_generic_load_method("load_credentials_from_file") 

176 

177 if not os.path.exists(filename): 

178 raise exceptions.DefaultCredentialsError( 

179 "File {} was not found.".format(filename) 

180 ) 

181 

182 with io.open(filename, "r") as file_obj: 

183 try: 

184 info = json.load(file_obj) 

185 except ValueError as caught_exc: 

186 new_exc = exceptions.DefaultCredentialsError( 

187 "File {} is not a valid json file.".format(filename), caught_exc 

188 ) 

189 raise new_exc from caught_exc 

190 return _load_credentials_from_info( 

191 filename, info, scopes, default_scopes, quota_project_id, request 

192 ) 

193 

194 

195def load_credentials_from_dict( 

196 info, scopes=None, default_scopes=None, quota_project_id=None, request=None 

197): 

198 """Loads Google credentials from a dict. 

199 

200 The credentials file must be a service account key, stored authorized 

201 user credentials, external account credentials, or impersonated service 

202 account credentials. 

203 

204 .. warning:: 

205 Important: If you accept a credential configuration (credential JSON/File/Stream) 

206 from an external source for authentication to Google Cloud Platform, you must 

207 validate it before providing it to any Google API or client library. Providing an 

208 unvalidated credential configuration to Google APIs or libraries can compromise 

209 the security of your systems and data. For more information, refer to 

210 `Validate credential configurations from external sources`_. 

211 

212 .. _Validate credential configurations from external sources: 

213 https://cloud.google.com/docs/authentication/external/externally-sourced-credentials 

214 

215 Args: 

216 info (Dict[str, Any]): A dict object containing the credentials 

217 scopes (Optional[Sequence[str]]): The list of scopes for the credentials. If 

218 specified, the credentials will automatically be scoped if 

219 necessary 

220 default_scopes (Optional[Sequence[str]]): Default scopes passed by a 

221 Google client library. Use 'scopes' for user-defined scopes. 

222 quota_project_id (Optional[str]): The project ID used for 

223 quota and billing. 

224 request (Optional[google.auth.transport.Request]): An object used to make 

225 HTTP requests. This is used to determine the associated project ID 

226 for a workload identity pool resource (external account credentials). 

227 If not specified, then it will use a 

228 google.auth.transport.requests.Request client to make requests. 

229 

230 Returns: 

231 Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded 

232 credentials and the project ID. Authorized user credentials do not 

233 have the project ID information. External account credentials project 

234 IDs may not always be determined. 

235 

236 Raises: 

237 google.auth.exceptions.DefaultCredentialsError: if the file is in the 

238 wrong format or is missing. 

239 """ 

240 _warn_about_generic_load_method("load_credentials_from_dict") 

241 if not isinstance(info, dict): 

242 raise exceptions.DefaultCredentialsError( 

243 "info object was of type {} but dict type was expected.".format(type(info)) 

244 ) 

245 

246 return _load_credentials_from_info( 

247 "dict object", info, scopes, default_scopes, quota_project_id, request 

248 ) 

249 

250 

251def _load_credentials_from_info( 

252 filename, info, scopes, default_scopes, quota_project_id, request 

253): 

254 from google.auth.credentials import CredentialsWithQuotaProject 

255 

256 credential_type = info.get("type") 

257 

258 if credential_type == _AUTHORIZED_USER_TYPE: 

259 credentials, project_id = _get_authorized_user_credentials( 

260 filename, info, scopes 

261 ) 

262 

263 elif credential_type == _SERVICE_ACCOUNT_TYPE: 

264 credentials, project_id = _get_service_account_credentials( 

265 filename, info, scopes, default_scopes 

266 ) 

267 

268 elif credential_type == _EXTERNAL_ACCOUNT_TYPE: 

269 credentials, project_id = _get_external_account_credentials( 

270 info, 

271 filename, 

272 scopes=scopes, 

273 default_scopes=default_scopes, 

274 request=request, 

275 ) 

276 

277 elif credential_type == _EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE: 

278 credentials, project_id = _get_external_account_authorized_user_credentials( 

279 filename, info, request 

280 ) 

281 

282 elif credential_type == _IMPERSONATED_SERVICE_ACCOUNT_TYPE: 

283 credentials, project_id = _get_impersonated_service_account_credentials( 

284 filename, info, scopes 

285 ) 

286 elif credential_type == _GDCH_SERVICE_ACCOUNT_TYPE: 

287 credentials, project_id = _get_gdch_service_account_credentials(filename, info) 

288 else: 

289 raise exceptions.DefaultCredentialsError( 

290 "The file {file} does not have a valid type. " 

291 "Type is {type}, expected one of {valid_types}.".format( 

292 file=filename, type=credential_type, valid_types=_VALID_TYPES 

293 ) 

294 ) 

295 if isinstance(credentials, CredentialsWithQuotaProject): 

296 credentials = _apply_quota_project_id(credentials, quota_project_id) 

297 return credentials, project_id 

298 

299 

300def _get_gcloud_sdk_credentials(quota_project_id=None): 

301 """Gets the credentials and project ID from the Cloud SDK.""" 

302 from google.auth import _cloud_sdk 

303 

304 _LOGGER.debug("Checking Cloud SDK credentials as part of auth process...") 

305 

306 # Check if application default credentials exist. 

307 credentials_filename = _cloud_sdk.get_application_default_credentials_path() 

308 

309 if not os.path.isfile(credentials_filename): 

310 _LOGGER.debug("Cloud SDK credentials not found on disk; not using them") 

311 return None, None 

312 

313 with warnings.catch_warnings(): 

314 warnings.simplefilter("ignore", DeprecationWarning) 

315 credentials, project_id = load_credentials_from_file( 

316 credentials_filename, quota_project_id=quota_project_id 

317 ) 

318 credentials._cred_file_path = credentials_filename 

319 

320 if not project_id: 

321 project_id = _cloud_sdk.get_project_id() 

322 

323 return credentials, project_id 

324 

325 

326def _get_explicit_environ_credentials(quota_project_id=None): 

327 """Gets credentials from the GOOGLE_APPLICATION_CREDENTIALS environment 

328 variable.""" 

329 from google.auth import _cloud_sdk 

330 

331 cloud_sdk_adc_path = _cloud_sdk.get_application_default_credentials_path() 

332 explicit_file = os.environ.get(environment_vars.CREDENTIALS, "") 

333 

334 _LOGGER.debug( 

335 "Checking '%s' for explicit credentials as part of auth process...", 

336 explicit_file, 

337 ) 

338 

339 if explicit_file != "" and explicit_file == cloud_sdk_adc_path: 

340 # Cloud sdk flow calls gcloud to fetch project id, so if the explicit 

341 # file path is cloud sdk credentials path, then we should fall back 

342 # to cloud sdk flow, otherwise project id cannot be obtained. 

343 _LOGGER.debug( 

344 "Explicit credentials path '%s' is the same as Cloud SDK credentials path, fall back to Cloud SDK credentials flow...", 

345 explicit_file, 

346 ) 

347 return _get_gcloud_sdk_credentials(quota_project_id=quota_project_id) 

348 

349 if explicit_file != "": 

350 with warnings.catch_warnings(): 

351 warnings.simplefilter("ignore", DeprecationWarning) 

352 credentials, project_id = load_credentials_from_file( 

353 os.environ[environment_vars.CREDENTIALS], 

354 quota_project_id=quota_project_id, 

355 ) 

356 credentials._cred_file_path = f"{explicit_file} file via the GOOGLE_APPLICATION_CREDENTIALS environment variable" 

357 return credentials, project_id 

358 

359 else: 

360 return None, None 

361 

362 

363def _get_gae_credentials(): 

364 """Gets Google App Engine App Identity credentials and project ID.""" 

365 # If not GAE gen1, prefer the metadata service even if the GAE APIs are 

366 # available as per https://google.aip.dev/auth/4115. 

367 if os.environ.get(environment_vars.LEGACY_APPENGINE_RUNTIME) != "python27": 

368 return None, None 

369 

370 # While this library is normally bundled with app_engine, there are 

371 # some cases where it's not available, so we tolerate ImportError. 

372 try: 

373 _LOGGER.debug("Checking for App Engine runtime as part of auth process...") 

374 import google.auth.app_engine as app_engine 

375 except ImportError: 

376 _LOGGER.warning("Import of App Engine auth library failed.") 

377 return None, None 

378 

379 try: 

380 credentials = app_engine.Credentials() 

381 project_id = app_engine.get_project_id() 

382 return credentials, project_id 

383 except EnvironmentError: 

384 _LOGGER.debug( 

385 "No App Engine library was found so cannot authentication via App Engine Identity Credentials." 

386 ) 

387 return None, None 

388 

389 

390def _get_gce_credentials(request=None, quota_project_id=None): 

391 """Gets credentials and project ID from the GCE Metadata Service.""" 

392 # While this library is normally bundled with compute_engine, there are 

393 # some cases where it's not available, so we tolerate ImportError. 

394 # Compute Engine requires optional `requests` dependency. 

395 try: 

396 from google.auth import compute_engine 

397 from google.auth.compute_engine import _metadata 

398 import google.auth.transport.requests 

399 except ImportError: 

400 _LOGGER.warning("Import of Compute Engine auth library failed.") 

401 return None, None 

402 

403 if request is None: 

404 request = google.auth.transport.requests.Request() 

405 

406 if _metadata.is_on_gce(request=request): 

407 # Get the project ID. 

408 try: 

409 project_id = _metadata.get_project_id(request=request) 

410 except exceptions.TransportError: 

411 project_id = None 

412 

413 cred = compute_engine.Credentials() 

414 cred = _apply_quota_project_id(cred, quota_project_id) 

415 

416 return cred, project_id 

417 else: 

418 _LOGGER.warning( 

419 "Authentication failed using Compute Engine authentication due to unavailable metadata server." 

420 ) 

421 return None, None 

422 

423 

424def _get_external_account_credentials( 

425 info, filename, scopes=None, default_scopes=None, request=None 

426): 

427 """Loads external account Credentials from the parsed external account info. 

428 

429 The credentials information must correspond to a supported external account 

430 credentials. 

431 

432 Args: 

433 info (Mapping[str, str]): The external account info in Google format. 

434 filename (str): The full path to the credentials file. 

435 scopes (Optional[Sequence[str]]): The list of scopes for the credentials. If 

436 specified, the credentials will automatically be scoped if 

437 necessary. 

438 default_scopes (Optional[Sequence[str]]): Default scopes passed by a 

439 Google client library. Use 'scopes' for user-defined scopes. 

440 request (Optional[google.auth.transport.Request]): An object used to make 

441 HTTP requests. This is used to determine the associated project ID 

442 for a workload identity pool resource (external account credentials). 

443 If not specified, then it will use a 

444 google.auth.transport.requests.Request client to make requests. 

445 

446 Returns: 

447 Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded 

448 credentials and the project ID. External account credentials project 

449 IDs may not always be determined. 

450 

451 Raises: 

452 google.auth.exceptions.DefaultCredentialsError: if the info dictionary 

453 is in the wrong format or is missing required information. 

454 """ 

455 # There are currently 3 types of external_account credentials. 

456 if info.get("subject_token_type") == _AWS_SUBJECT_TOKEN_TYPE: 

457 # Check if configuration corresponds to an AWS credentials. 

458 from google.auth import aws 

459 

460 credentials = aws.Credentials.from_info( 

461 info, scopes=scopes, default_scopes=default_scopes 

462 ) 

463 elif ( 

464 info.get("credential_source") is not None 

465 and info.get("credential_source").get("executable") is not None 

466 ): 

467 from google.auth import pluggable 

468 

469 credentials = pluggable.Credentials.from_info( 

470 info, scopes=scopes, default_scopes=default_scopes 

471 ) 

472 else: 

473 try: 

474 # Check if configuration corresponds to an Identity Pool credentials. 

475 from google.auth import identity_pool 

476 

477 credentials = identity_pool.Credentials.from_info( 

478 info, scopes=scopes, default_scopes=default_scopes 

479 ) 

480 except ValueError: 

481 # If the configuration is invalid or does not correspond to any 

482 # supported external_account credentials, raise an error. 

483 raise exceptions.DefaultCredentialsError( 

484 "Failed to load external account credentials from {}".format(filename) 

485 ) 

486 if request is None: 

487 import google.auth.transport.requests 

488 

489 request = google.auth.transport.requests.Request() 

490 

491 return credentials, credentials.get_project_id(request=request) 

492 

493 

494def _get_external_account_authorized_user_credentials( 

495 filename, info, scopes=None, default_scopes=None, request=None 

496): 

497 try: 

498 from google.auth import external_account_authorized_user 

499 

500 credentials = external_account_authorized_user.Credentials.from_info(info) 

501 except ValueError: 

502 raise exceptions.DefaultCredentialsError( 

503 "Failed to load external account authorized user credentials from {}".format( 

504 filename 

505 ) 

506 ) 

507 

508 return credentials, None 

509 

510 

511def _get_authorized_user_credentials(filename, info, scopes=None): 

512 from google.oauth2 import credentials 

513 

514 try: 

515 credentials = credentials.Credentials.from_authorized_user_info( 

516 info, scopes=scopes 

517 ) 

518 except ValueError as caught_exc: 

519 msg = "Failed to load authorized user credentials from {}".format(filename) 

520 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) 

521 raise new_exc from caught_exc 

522 return credentials, None 

523 

524 

525def _get_service_account_credentials(filename, info, scopes=None, default_scopes=None): 

526 from google.oauth2 import service_account 

527 

528 try: 

529 credentials = service_account.Credentials.from_service_account_info( 

530 info, scopes=scopes, default_scopes=default_scopes 

531 ) 

532 except ValueError as caught_exc: 

533 msg = "Failed to load service account credentials from {}".format(filename) 

534 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) 

535 raise new_exc from caught_exc 

536 return credentials, info.get("project_id") 

537 

538 

539def _get_impersonated_service_account_credentials(filename, info, scopes): 

540 from google.auth import impersonated_credentials 

541 

542 try: 

543 credentials = ( 

544 impersonated_credentials.Credentials.from_impersonated_service_account_info( 

545 info, scopes=scopes 

546 ) 

547 ) 

548 except ValueError as caught_exc: 

549 msg = "Failed to load impersonated service account credentials from {}".format( 

550 filename 

551 ) 

552 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) 

553 raise new_exc from caught_exc 

554 return credentials, None 

555 

556 

557def _get_gdch_service_account_credentials(filename, info): 

558 from google.oauth2 import gdch_credentials 

559 

560 try: 

561 credentials = ( 

562 gdch_credentials.ServiceAccountCredentials.from_service_account_info(info) 

563 ) 

564 except ValueError as caught_exc: 

565 msg = "Failed to load GDCH service account credentials from {}".format(filename) 

566 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) 

567 raise new_exc from caught_exc 

568 return credentials, info.get("project") 

569 

570 

571def get_api_key_credentials(key): 

572 """Return credentials with the given API key.""" 

573 from google.auth import api_key 

574 

575 return api_key.Credentials(key) 

576 

577 

578def _apply_quota_project_id(credentials, quota_project_id): 

579 if quota_project_id: 

580 credentials = credentials.with_quota_project(quota_project_id) 

581 else: 

582 credentials = credentials.with_quota_project_from_environment() 

583 

584 from google.oauth2 import credentials as authorized_user_credentials 

585 

586 if isinstance(credentials, authorized_user_credentials.Credentials) and ( 

587 not credentials.quota_project_id 

588 ): 

589 _warn_about_problematic_credentials(credentials) 

590 return credentials 

591 

592 

593def default( 

594 scopes: Optional[Sequence[str]] = None, 

595 request: Optional["google.auth.transport.Request"] = None, 

596 quota_project_id: Optional[str] = None, 

597 default_scopes: Optional[Sequence[str]] = None, 

598) -> tuple["google.auth.credentials.Credentials", Optional[str]]: 

599 """Gets the default credentials for the current environment. 

600 

601 `Application Default Credentials`_ provides an easy way to obtain 

602 credentials to call Google APIs for server-to-server or local applications. 

603 This function acquires credentials from the environment in the following 

604 order: 

605 

606 1. If the environment variable ``GOOGLE_APPLICATION_CREDENTIALS`` is set 

607 to the path of a valid service account JSON private key file, then it is 

608 loaded and returned. The project ID returned is the project ID defined 

609 in the service account file if available (some older files do not 

610 contain project ID information). 

611 

612 If the environment variable is set to the path of a valid external 

613 account JSON configuration file (workload identity federation), then the 

614 configuration file is used to determine and retrieve the external 

615 credentials from the current environment (AWS, Azure, etc). 

616 These will then be exchanged for Google access tokens via the Google STS 

617 endpoint. 

618 The project ID returned in this case is the one corresponding to the 

619 underlying workload identity pool resource if determinable. 

620 

621 If the environment variable is set to the path of a valid GDCH service 

622 account JSON file (`Google Distributed Cloud Hosted`_), then a GDCH 

623 credential will be returned. The project ID returned is the project 

624 specified in the JSON file. 

625 2. If the `Google Cloud SDK`_ is installed and has application default 

626 credentials set they are loaded and returned. 

627 

628 To enable application default credentials with the Cloud SDK run:: 

629 

630 gcloud auth application-default login 

631 

632 If the Cloud SDK has an active project, the project ID is returned. The 

633 active project can be set using:: 

634 

635 gcloud config set project 

636 

637 3. If the application is running in the `App Engine standard environment`_ 

638 (first generation) then the credentials and project ID from the 

639 `App Identity Service`_ are used. 

640 4. If the application is running in `Compute Engine`_ or `Cloud Run`_ or 

641 the `App Engine flexible environment`_ or the `App Engine standard 

642 environment`_ (second generation) then the credentials and project ID 

643 are obtained from the `Metadata Service`_. 

644 5. If no credentials are found, 

645 :class:`~google.auth.exceptions.DefaultCredentialsError` will be raised. 

646 

647 .. _Application Default Credentials: https://developers.google.com\ 

648 /identity/protocols/application-default-credentials 

649 .. _Google Cloud SDK: https://cloud.google.com/sdk 

650 .. _App Engine standard environment: https://cloud.google.com/appengine 

651 .. _App Identity Service: https://cloud.google.com/appengine/docs/python\ 

652 /appidentity/ 

653 .. _Compute Engine: https://cloud.google.com/compute 

654 .. _App Engine flexible environment: https://cloud.google.com\ 

655 /appengine/flexible 

656 .. _Metadata Service: https://cloud.google.com/compute/docs\ 

657 /storing-retrieving-metadata 

658 .. _Cloud Run: https://cloud.google.com/run 

659 .. _Google Distributed Cloud Hosted: https://cloud.google.com/blog/topics\ 

660 /hybrid-cloud/announcing-google-distributed-cloud-edge-and-hosted 

661 

662 Example:: 

663 

664 import google.auth 

665 

666 credentials, project_id = google.auth.default() 

667 

668 Args: 

669 scopes (Sequence[str]): The list of scopes for the credentials. If 

670 specified, the credentials will automatically be scoped if 

671 necessary. 

672 request (Optional[google.auth.transport.Request]): An object used to make 

673 HTTP requests. This is used to either detect whether the application 

674 is running on Compute Engine or to determine the associated project 

675 ID for a workload identity pool resource (external account 

676 credentials). If not specified, then it will either use the standard 

677 library http client to make requests for Compute Engine credentials 

678 or a google.auth.transport.requests.Request client for external 

679 account credentials. 

680 quota_project_id (Optional[str]): The project ID used for 

681 quota and billing. 

682 default_scopes (Optional[Sequence[str]]): Default scopes passed by a 

683 Google client library. Use 'scopes' for user-defined scopes. 

684 Returns: 

685 Tuple[~google.auth.credentials.Credentials, Optional[str]]: 

686 the current environment's credentials and project ID. Project ID 

687 may be None, which indicates that the Project ID could not be 

688 ascertained from the environment. 

689 

690 Raises: 

691 ~google.auth.exceptions.DefaultCredentialsError: 

692 If no credentials were found, or if the credentials found were 

693 invalid. 

694 """ 

695 from google.auth.credentials import with_scopes_if_required 

696 from google.auth.credentials import CredentialsWithQuotaProject 

697 

698 explicit_project_id = os.environ.get( 

699 environment_vars.PROJECT, os.environ.get(environment_vars.LEGACY_PROJECT) 

700 ) 

701 

702 checkers = ( 

703 # Avoid passing scopes here to prevent passing scopes to user credentials. 

704 # with_scopes_if_required() below will ensure scopes/default scopes are 

705 # safely set on the returned credentials since requires_scopes will 

706 # guard against setting scopes on user credentials. 

707 lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id), 

708 lambda: _get_gcloud_sdk_credentials(quota_project_id=quota_project_id), 

709 _get_gae_credentials, 

710 lambda: _get_gce_credentials(request, quota_project_id=quota_project_id), 

711 ) 

712 

713 for checker in checkers: 

714 credentials, project_id = checker() 

715 if credentials is not None: 

716 credentials = with_scopes_if_required( 

717 credentials, scopes, default_scopes=default_scopes 

718 ) 

719 

720 effective_project_id = explicit_project_id or project_id 

721 

722 # For external account credentials, scopes are required to determine 

723 # the project ID. Try to get the project ID again if not yet 

724 # determined. 

725 if not effective_project_id and callable( 

726 getattr(credentials, "get_project_id", None) 

727 ): 

728 if request is None: 

729 import google.auth.transport.requests 

730 

731 request = google.auth.transport.requests.Request() 

732 effective_project_id = credentials.get_project_id(request=request) 

733 

734 if quota_project_id and isinstance( 

735 credentials, CredentialsWithQuotaProject 

736 ): 

737 credentials = credentials.with_quota_project(quota_project_id) 

738 

739 if not effective_project_id: 

740 _LOGGER.warning( 

741 "No project ID could be determined. Consider running " 

742 "`gcloud config set project` or setting the %s " 

743 "environment variable", 

744 environment_vars.PROJECT, 

745 ) 

746 return credentials, effective_project_id 

747 

748 raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)