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

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

225 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""" 

19 

20import io 

21import json 

22import logging 

23import os 

24import warnings 

25 

26from google.auth import environment_vars 

27from google.auth import exceptions 

28import google.auth.transport._http_client 

29 

30_LOGGER = logging.getLogger(__name__) 

31 

32# Valid types accepted for file-based credentials. 

33_AUTHORIZED_USER_TYPE = "authorized_user" 

34_SERVICE_ACCOUNT_TYPE = "service_account" 

35_EXTERNAL_ACCOUNT_TYPE = "external_account" 

36_EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = "external_account_authorized_user" 

37_IMPERSONATED_SERVICE_ACCOUNT_TYPE = "impersonated_service_account" 

38_GDCH_SERVICE_ACCOUNT_TYPE = "gdch_service_account" 

39_VALID_TYPES = ( 

40 _AUTHORIZED_USER_TYPE, 

41 _SERVICE_ACCOUNT_TYPE, 

42 _EXTERNAL_ACCOUNT_TYPE, 

43 _EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE, 

44 _IMPERSONATED_SERVICE_ACCOUNT_TYPE, 

45 _GDCH_SERVICE_ACCOUNT_TYPE, 

46) 

47 

48# Help message when no credentials can be found. 

49_CLOUD_SDK_MISSING_CREDENTIALS = """\ 

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

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

52""" 

53 

54# Warning when using Cloud SDK user credentials 

55_CLOUD_SDK_CREDENTIALS_WARNING = """\ 

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

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

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

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

60""" 

61 

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

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

64 

65 

66def _warn_about_problematic_credentials(credentials): 

67 """Determines if the credentials are problematic. 

68 

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

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

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

72 """ 

73 from google.auth import _cloud_sdk 

74 

75 if credentials.client_id == _cloud_sdk.CLOUD_SDK_CLIENT_ID: 

76 warnings.warn(_CLOUD_SDK_CREDENTIALS_WARNING) 

77 

78 

79def load_credentials_from_file( 

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

81): 

82 """Loads Google credentials from a file. 

83 

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

85 user credentials, external account credentials, or impersonated service 

86 account credentials. 

87 

88 .. warning:: 

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

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

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

92 unvalidated credential configuration to Google APIs or libraries can compromise 

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

94 `Validate credential configurations from external sources`_. 

95 

96 .. _Validate credential configurations from external sources: 

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

98 

99 Args: 

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

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

102 specified, the credentials will automatically be scoped if 

103 necessary 

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

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

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

107 quota and billing. 

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

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

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

111 If not specified, then it will use a 

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

113 

114 Returns: 

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

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

117 have the project ID information. External account credentials project 

118 IDs may not always be determined. 

119 

120 Raises: 

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

122 wrong format or is missing. 

123 """ 

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

125 raise exceptions.DefaultCredentialsError( 

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

127 ) 

128 

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

130 try: 

131 info = json.load(file_obj) 

132 except ValueError as caught_exc: 

133 new_exc = exceptions.DefaultCredentialsError( 

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

135 ) 

136 raise new_exc from caught_exc 

137 return _load_credentials_from_info( 

138 filename, info, scopes, default_scopes, quota_project_id, request 

139 ) 

140 

141 

142def load_credentials_from_dict( 

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

144): 

145 """Loads Google credentials from a dict. 

146 

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

148 user credentials, external account credentials, or impersonated service 

149 account credentials. 

150 

151 .. warning:: 

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

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

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

155 unvalidated credential configuration to Google APIs or libraries can compromise 

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

157 `Validate credential configurations from external sources`_. 

158 

159 .. _Validate credential configurations from external sources: 

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

161 

162 Args: 

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

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

165 specified, the credentials will automatically be scoped if 

166 necessary 

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

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

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

170 quota and billing. 

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

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

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

174 If not specified, then it will use a 

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

176 

177 Returns: 

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

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

180 have the project ID information. External account credentials project 

181 IDs may not always be determined. 

182 

183 Raises: 

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

185 wrong format or is missing. 

186 """ 

187 if not isinstance(info, dict): 

188 raise exceptions.DefaultCredentialsError( 

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

190 ) 

191 

192 return _load_credentials_from_info( 

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

194 ) 

195 

196 

197def _load_credentials_from_info( 

198 filename, info, scopes, default_scopes, quota_project_id, request 

199): 

200 from google.auth.credentials import CredentialsWithQuotaProject 

201 

202 credential_type = info.get("type") 

203 

204 if credential_type == _AUTHORIZED_USER_TYPE: 

205 credentials, project_id = _get_authorized_user_credentials( 

206 filename, info, scopes 

207 ) 

208 

209 elif credential_type == _SERVICE_ACCOUNT_TYPE: 

210 credentials, project_id = _get_service_account_credentials( 

211 filename, info, scopes, default_scopes 

212 ) 

213 

214 elif credential_type == _EXTERNAL_ACCOUNT_TYPE: 

215 credentials, project_id = _get_external_account_credentials( 

216 info, 

217 filename, 

218 scopes=scopes, 

219 default_scopes=default_scopes, 

220 request=request, 

221 ) 

222 

223 elif credential_type == _EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE: 

224 credentials, project_id = _get_external_account_authorized_user_credentials( 

225 filename, info, request 

226 ) 

227 

228 elif credential_type == _IMPERSONATED_SERVICE_ACCOUNT_TYPE: 

229 credentials, project_id = _get_impersonated_service_account_credentials( 

230 filename, info, scopes 

231 ) 

232 elif credential_type == _GDCH_SERVICE_ACCOUNT_TYPE: 

233 credentials, project_id = _get_gdch_service_account_credentials(filename, info) 

234 else: 

235 raise exceptions.DefaultCredentialsError( 

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

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

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

239 ) 

240 ) 

241 if isinstance(credentials, CredentialsWithQuotaProject): 

242 credentials = _apply_quota_project_id(credentials, quota_project_id) 

243 return credentials, project_id 

244 

245 

246def _get_gcloud_sdk_credentials(quota_project_id=None): 

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

248 from google.auth import _cloud_sdk 

249 

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

251 

252 # Check if application default credentials exist. 

253 credentials_filename = _cloud_sdk.get_application_default_credentials_path() 

254 

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

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

257 return None, None 

258 

259 credentials, project_id = load_credentials_from_file( 

260 credentials_filename, quota_project_id=quota_project_id 

261 ) 

262 credentials._cred_file_path = credentials_filename 

263 

264 if not project_id: 

265 project_id = _cloud_sdk.get_project_id() 

266 

267 return credentials, project_id 

268 

269 

270def _get_explicit_environ_credentials(quota_project_id=None): 

271 """Gets credentials from the GOOGLE_APPLICATION_CREDENTIALS environment 

272 variable.""" 

273 from google.auth import _cloud_sdk 

274 

275 cloud_sdk_adc_path = _cloud_sdk.get_application_default_credentials_path() 

276 explicit_file = os.environ.get(environment_vars.CREDENTIALS) 

277 

278 _LOGGER.debug( 

279 "Checking %s for explicit credentials as part of auth process...", explicit_file 

280 ) 

281 

282 if explicit_file is not None and explicit_file == cloud_sdk_adc_path: 

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

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

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

286 _LOGGER.debug( 

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

288 explicit_file, 

289 ) 

290 return _get_gcloud_sdk_credentials(quota_project_id=quota_project_id) 

291 

292 if explicit_file is not None: 

293 credentials, project_id = load_credentials_from_file( 

294 os.environ[environment_vars.CREDENTIALS], quota_project_id=quota_project_id 

295 ) 

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

297 

298 return credentials, project_id 

299 

300 else: 

301 return None, None 

302 

303 

304def _get_gae_credentials(): 

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

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

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

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

309 return None, None 

310 

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

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

313 try: 

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

315 import google.auth.app_engine as app_engine 

316 except ImportError: 

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

318 return None, None 

319 

320 try: 

321 credentials = app_engine.Credentials() 

322 project_id = app_engine.get_project_id() 

323 return credentials, project_id 

324 except EnvironmentError: 

325 _LOGGER.debug( 

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

327 ) 

328 return None, None 

329 

330 

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

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

333 # Ping requires a transport, but we want application default credentials 

334 # to require no arguments. So, we'll use the _http_client transport which 

335 # uses http.client. This is only acceptable because the metadata server 

336 # doesn't do SSL and never requires proxies. 

337 

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

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

340 try: 

341 from google.auth import compute_engine 

342 from google.auth.compute_engine import _metadata 

343 except ImportError: 

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

345 return None, None 

346 

347 if request is None: 

348 request = google.auth.transport._http_client.Request() 

349 

350 if _metadata.is_on_gce(request=request): 

351 # Get the project ID. 

352 try: 

353 project_id = _metadata.get_project_id(request=request) 

354 except exceptions.TransportError: 

355 project_id = None 

356 

357 cred = compute_engine.Credentials() 

358 cred = _apply_quota_project_id(cred, quota_project_id) 

359 

360 return cred, project_id 

361 else: 

362 _LOGGER.warning( 

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

364 ) 

365 return None, None 

366 

367 

368def _get_external_account_credentials( 

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

370): 

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

372 

373 The credentials information must correspond to a supported external account 

374 credentials. 

375 

376 Args: 

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

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

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

380 specified, the credentials will automatically be scoped if 

381 necessary. 

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

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

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

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

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

387 If not specified, then it will use a 

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

389 

390 Returns: 

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

392 credentials and the project ID. External account credentials project 

393 IDs may not always be determined. 

394 

395 Raises: 

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

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

398 """ 

399 # There are currently 3 types of external_account credentials. 

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

401 # Check if configuration corresponds to an AWS credentials. 

402 from google.auth import aws 

403 

404 credentials = aws.Credentials.from_info( 

405 info, scopes=scopes, default_scopes=default_scopes 

406 ) 

407 elif ( 

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

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

410 ): 

411 from google.auth import pluggable 

412 

413 credentials = pluggable.Credentials.from_info( 

414 info, scopes=scopes, default_scopes=default_scopes 

415 ) 

416 else: 

417 try: 

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

419 from google.auth import identity_pool 

420 

421 credentials = identity_pool.Credentials.from_info( 

422 info, scopes=scopes, default_scopes=default_scopes 

423 ) 

424 except ValueError: 

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

426 # supported external_account credentials, raise an error. 

427 raise exceptions.DefaultCredentialsError( 

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

429 ) 

430 if request is None: 

431 import google.auth.transport.requests 

432 

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

434 

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

436 

437 

438def _get_external_account_authorized_user_credentials( 

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

440): 

441 try: 

442 from google.auth import external_account_authorized_user 

443 

444 credentials = external_account_authorized_user.Credentials.from_info(info) 

445 except ValueError: 

446 raise exceptions.DefaultCredentialsError( 

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

448 filename 

449 ) 

450 ) 

451 

452 return credentials, None 

453 

454 

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

456 from google.oauth2 import credentials 

457 

458 try: 

459 credentials = credentials.Credentials.from_authorized_user_info( 

460 info, scopes=scopes 

461 ) 

462 except ValueError as caught_exc: 

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

464 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) 

465 raise new_exc from caught_exc 

466 return credentials, None 

467 

468 

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

470 from google.oauth2 import service_account 

471 

472 try: 

473 credentials = service_account.Credentials.from_service_account_info( 

474 info, scopes=scopes, default_scopes=default_scopes 

475 ) 

476 except ValueError as caught_exc: 

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

478 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) 

479 raise new_exc from caught_exc 

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

481 

482 

483def _get_impersonated_service_account_credentials(filename, info, scopes): 

484 from google.auth import impersonated_credentials 

485 

486 try: 

487 source_credentials_info = info.get("source_credentials") 

488 source_credentials_type = source_credentials_info.get("type") 

489 if source_credentials_type == _AUTHORIZED_USER_TYPE: 

490 source_credentials, _ = _get_authorized_user_credentials( 

491 filename, source_credentials_info 

492 ) 

493 elif source_credentials_type == _SERVICE_ACCOUNT_TYPE: 

494 source_credentials, _ = _get_service_account_credentials( 

495 filename, source_credentials_info 

496 ) 

497 elif source_credentials_type == _EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE: 

498 source_credentials, _ = _get_external_account_authorized_user_credentials( 

499 filename, source_credentials_info 

500 ) 

501 else: 

502 raise exceptions.InvalidType( 

503 "source credential of type {} is not supported.".format( 

504 source_credentials_type 

505 ) 

506 ) 

507 impersonation_url = info.get("service_account_impersonation_url") 

508 start_index = impersonation_url.rfind("/") 

509 end_index = impersonation_url.find(":generateAccessToken") 

510 if start_index == -1 or end_index == -1 or start_index > end_index: 

511 raise exceptions.InvalidValue( 

512 "Cannot extract target principal from {}".format(impersonation_url) 

513 ) 

514 target_principal = impersonation_url[start_index + 1 : end_index] 

515 delegates = info.get("delegates") 

516 quota_project_id = info.get("quota_project_id") 

517 credentials = impersonated_credentials.Credentials( 

518 source_credentials, 

519 target_principal, 

520 scopes, 

521 delegates, 

522 quota_project_id=quota_project_id, 

523 ) 

524 except ValueError as caught_exc: 

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

526 filename 

527 ) 

528 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) 

529 raise new_exc from caught_exc 

530 return credentials, None 

531 

532 

533def _get_gdch_service_account_credentials(filename, info): 

534 from google.oauth2 import gdch_credentials 

535 

536 try: 

537 credentials = gdch_credentials.ServiceAccountCredentials.from_service_account_info( 

538 info 

539 ) 

540 except ValueError as caught_exc: 

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

542 new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) 

543 raise new_exc from caught_exc 

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

545 

546 

547def get_api_key_credentials(key): 

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

549 from google.auth import api_key 

550 

551 return api_key.Credentials(key) 

552 

553 

554def _apply_quota_project_id(credentials, quota_project_id): 

555 if quota_project_id: 

556 credentials = credentials.with_quota_project(quota_project_id) 

557 else: 

558 credentials = credentials.with_quota_project_from_environment() 

559 

560 from google.oauth2 import credentials as authorized_user_credentials 

561 

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

563 not credentials.quota_project_id 

564 ): 

565 _warn_about_problematic_credentials(credentials) 

566 return credentials 

567 

568 

569def default(scopes=None, request=None, quota_project_id=None, default_scopes=None): 

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

571 

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

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

574 This function acquires credentials from the environment in the following 

575 order: 

576 

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

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

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

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

581 contain project ID information). 

582 

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

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

585 configuration file is used to determine and retrieve the external 

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

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

588 endpoint. 

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

590 underlying workload identity pool resource if determinable. 

591 

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

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

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

595 specified in the JSON file. 

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

597 credentials set they are loaded and returned. 

598 

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

600 

601 gcloud auth application-default login 

602 

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

604 active project can be set using:: 

605 

606 gcloud config set project 

607 

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

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

610 `App Identity Service`_ are used. 

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

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

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

614 are obtained from the `Metadata Service`_. 

615 5. If no credentials are found, 

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

617 

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

619 /identity/protocols/application-default-credentials 

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

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

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

623 /appidentity/ 

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

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

626 /appengine/flexible 

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

628 /storing-retrieving-metadata 

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

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

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

632 

633 Example:: 

634 

635 import google.auth 

636 

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

638 

639 Args: 

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

641 specified, the credentials will automatically be scoped if 

642 necessary. 

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

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

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

646 ID for a workload identity pool resource (external account 

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

648 library http client to make requests for Compute Engine credentials 

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

650 account credentials. 

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

652 quota and billing. 

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

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

655 Returns: 

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

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

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

659 ascertained from the environment. 

660 

661 Raises: 

662 ~google.auth.exceptions.DefaultCredentialsError: 

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

664 invalid. 

665 """ 

666 from google.auth.credentials import with_scopes_if_required 

667 from google.auth.credentials import CredentialsWithQuotaProject 

668 

669 explicit_project_id = os.environ.get( 

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

671 ) 

672 

673 checkers = ( 

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

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

676 # safely set on the returned credentials since requires_scopes will 

677 # guard against setting scopes on user credentials. 

678 lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id), 

679 lambda: _get_gcloud_sdk_credentials(quota_project_id=quota_project_id), 

680 _get_gae_credentials, 

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

682 ) 

683 

684 for checker in checkers: 

685 credentials, project_id = checker() 

686 if credentials is not None: 

687 credentials = with_scopes_if_required( 

688 credentials, scopes, default_scopes=default_scopes 

689 ) 

690 

691 effective_project_id = explicit_project_id or project_id 

692 

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

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

695 # determined. 

696 if not effective_project_id and callable( 

697 getattr(credentials, "get_project_id", None) 

698 ): 

699 if request is None: 

700 import google.auth.transport.requests 

701 

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

703 effective_project_id = credentials.get_project_id(request=request) 

704 

705 if quota_project_id and isinstance( 

706 credentials, CredentialsWithQuotaProject 

707 ): 

708 credentials = credentials.with_quota_project(quota_project_id) 

709 

710 if not effective_project_id: 

711 _LOGGER.warning( 

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

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

714 "environment variable", 

715 environment_vars.PROJECT, 

716 ) 

717 return credentials, effective_project_id 

718 

719 raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)