????
Current Path : C:/opt/pgsql/pgAdmin 4/python/Lib/site-packages/azure/identity/_credentials/ |
Current File : C:/opt/pgsql/pgAdmin 4/python/Lib/site-packages/azure/identity/_credentials/imds.py |
# ------------------------------------ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ import os from typing import Any, Optional, Dict from azure.core.exceptions import ClientAuthenticationError, HttpResponseError from azure.core.pipeline.transport import HttpRequest from azure.core.credentials import AccessToken from .. import CredentialUnavailableError from .._constants import EnvironmentVariables from .._internal import within_credential_chain from .._internal.get_token_mixin import GetTokenMixin from .._internal.managed_identity_client import ManagedIdentityClient IMDS_AUTHORITY = "http://169.254.169.254" IMDS_TOKEN_PATH = "/metadata/identity/oauth2/token" PIPELINE_SETTINGS = { "connection_timeout": 2, "retry_backoff_factor": 2, "retry_backoff_max": 60, "retry_on_status_codes": [404, 410, 429] + list(range(500, 600)), "retry_status": 5, "retry_total": 5, } def _get_request(scope: str, identity_config: Dict) -> HttpRequest: url = ( os.environ.get(EnvironmentVariables.AZURE_POD_IDENTITY_AUTHORITY_HOST, IMDS_AUTHORITY).strip("/") + IMDS_TOKEN_PATH ) request = HttpRequest("GET", url) request.format_parameters(dict({"api-version": "2018-02-01", "resource": scope}, **identity_config)) return request def _check_forbidden_response(ex: HttpResponseError) -> None: """Special case handling for Docker Desktop. Docker Desktop proxies all HTTP traffic, and if the IMDS endpoint is unreachable, it responds with a 403 with a message that contains "A socket operation was attempted to an unreachable network". :param ~azure.core.exceptions.HttpResponseError ex: The exception raised by the request :raises ~azure.core.exceptions.CredentialUnavailableError: When the IMDS endpoint is unreachable """ if ex.status_code == 403: if ex.message and "A socket operation was attempted to an unreachable network" in ex.message: error_message = f"ManagedIdentityCredential authentication unavailable. Error: {ex.message}" raise CredentialUnavailableError(message=error_message) from ex class ImdsCredential(GetTokenMixin): def __init__(self, **kwargs: Any) -> None: super(ImdsCredential, self).__init__() self._client = ManagedIdentityClient(_get_request, **dict(PIPELINE_SETTINGS, **kwargs)) if EnvironmentVariables.AZURE_POD_IDENTITY_AUTHORITY_HOST in os.environ: self._endpoint_available: Optional[bool] = True else: self._endpoint_available = None self._user_assigned_identity = "client_id" in kwargs or "identity_config" in kwargs def __enter__(self): self._client.__enter__() return self def __exit__(self, *args): self._client.__exit__(*args) def close(self) -> None: self.__exit__() def _acquire_token_silently(self, *scopes: str, **kwargs: Any) -> Optional[AccessToken]: return self._client.get_cached_token(*scopes) def _request_token(self, *scopes: str, **kwargs: Any) -> AccessToken: if within_credential_chain.get() and not self._endpoint_available: # If within a chain (e.g. DefaultAzureCredential), we do a quick check to see if the IMDS endpoint # is available to avoid hanging for a long time if the endpoint isn't available. try: self._client.request_token(*scopes, connection_timeout=1, retry_total=0) self._endpoint_available = True except HttpResponseError as ex: # IMDS responded _check_forbidden_response(ex) self._endpoint_available = True except Exception as ex: # pylint:disable=broad-except error_message = ( "ManagedIdentityCredential authentication unavailable, no response from the IMDS endpoint." ) raise CredentialUnavailableError(error_message) from ex try: token = self._client.request_token(*scopes, headers={"Metadata": "true"}) except HttpResponseError as ex: # 400 in response to a token request indicates managed identity is disabled, # or the identity with the specified client_id is not available if ex.status_code == 400: error_message = "ManagedIdentityCredential authentication unavailable. " if self._user_assigned_identity: error_message += "The requested identity has not been assigned to this resource." else: error_message += "No identity has been assigned to this resource." if ex.message: error_message += f" Error: {ex.message}" raise CredentialUnavailableError(message=error_message) from ex _check_forbidden_response(ex) # any other error is unexpected raise ClientAuthenticationError(message=ex.message, response=ex.response) from ex except Exception as ex: # pylint:disable=broad-except # if anything else was raised, assume the endpoint is unavailable error_message = "ManagedIdentityCredential authentication unavailable, no response from the IMDS endpoint." raise CredentialUnavailableError(error_message) from ex return token