py2docfx 0.1.20rc2195074__py3-none-any.whl → 0.1.20rc2245107__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/api.py +3 -2
- py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/legacy.py +17 -1
- py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/version.py +1 -1
- py2docfx/venv/basevenv/Lib/site-packages/requests/__version__.py +2 -2
- py2docfx/venv/basevenv/Lib/site-packages/requests/adapters.py +17 -40
- py2docfx/venv/basevenv/Lib/site-packages/requests/sessions.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/core/_version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_authentication.py +21 -9
- py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_authentication_async.py +21 -9
- py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_retry.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_bearer_token_provider.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/authorization_code.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azd_cli.py +82 -17
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_cli.py +28 -5
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_powershell.py +28 -4
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/broker.py +79 -0
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/chained.py +9 -3
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/default.py +153 -53
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/imds.py +25 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/shared_cache.py +12 -5
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/vscode.py +163 -144
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/workload_identity.py +23 -12
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/__init__.py +4 -0
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/interactive.py +14 -2
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/pipeline.py +4 -2
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/utils.py +96 -0
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_bearer_token_provider.py +3 -3
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/authorization_code.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azd_cli.py +32 -13
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azure_cli.py +26 -5
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azure_powershell.py +13 -2
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/chained.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/default.py +120 -55
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/imds.py +27 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/on_behalf_of.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/shared_cache.py +12 -5
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/vscode.py +15 -67
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/workload_identity.py +17 -13
- py2docfx/venv/venv1/Lib/site-packages/cffi/__init__.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/cffi/cparser.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cffi/recompiler.py +5 -5
- py2docfx/venv/venv1/Lib/site-packages/cffi/setuptools_ext.py +13 -0
- py2docfx/venv/venv1/Lib/site-packages/cffi/vengine_cpy.py +3 -0
- py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/api.py +3 -2
- py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/legacy.py +17 -1
- py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/__about__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/__init__.py +0 -13
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/_oid.py +8 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/asn1/__init__.py +10 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/asn1/asn1.py +116 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py +3 -9
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi +32 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi +23 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi +1 -13
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py +16 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py +16 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py +0 -2
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py +8 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py +0 -47
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py +6 -91
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py +1 -3
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/utils.py +0 -2
- py2docfx/venv/venv1/Lib/site-packages/cryptography/x509/name.py +2 -3
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/__init__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/any_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/api_pb2.py +12 -8
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor.py +398 -246
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor_pb2.py +74 -72
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor_pool.py +5 -4
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/duration_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/empty_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/field_mask_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/api_implementation.py +0 -6
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/extension_dict.py +3 -3
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/field_mask.py +3 -3
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/python_edition_defaults.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/python_message.py +10 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/type_checkers.py +47 -5
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/json_format.py +55 -32
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/runtime_version.py +6 -26
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/source_context_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/struct_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/text_format.py +30 -19
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/timestamp_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/type_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/wrappers_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/pycparser/__init__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/pycparser/c_generator.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/pycparser/c_lexer.py +14 -0
- py2docfx/venv/venv1/Lib/site-packages/pycparser/c_parser.py +30 -7
- py2docfx/venv/venv1/Lib/site-packages/pycparser/lextab.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/pycparser/yacctab.py +132 -127
- py2docfx/venv/venv1/Lib/site-packages/requests/__version__.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/requests/adapters.py +17 -40
- py2docfx/venv/venv1/Lib/site-packages/requests/sessions.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/typing_extensions.py +91 -18
- {py2docfx-0.1.20rc2195074.dist-info → py2docfx-0.1.20rc2245107.dist-info}/METADATA +1 -1
- {py2docfx-0.1.20rc2195074.dist-info → py2docfx-0.1.20rc2245107.dist-info}/RECORD +104 -103
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/linux_vscode_adapter.py +0 -100
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/macos_vscode_adapter.py +0 -34
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/win_vscode_adapter.py +0 -77
- {py2docfx-0.1.20rc2195074.dist-info → py2docfx-0.1.20rc2245107.dist-info}/WHEEL +0 -0
- {py2docfx-0.1.20rc2195074.dist-info → py2docfx-0.1.20rc2245107.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
# ------------------------------------
|
2
|
+
# Copyright (c) Microsoft Corporation.
|
3
|
+
# Licensed under the MIT License.
|
4
|
+
# ------------------------------------
|
5
|
+
import sys
|
6
|
+
from typing import Any
|
7
|
+
|
8
|
+
import msal
|
9
|
+
from azure.core.credentials import AccessToken, AccessTokenInfo, SupportsTokenInfo
|
10
|
+
from .._exceptions import CredentialUnavailableError
|
11
|
+
from .._internal.utils import get_broker_credential, is_wsl
|
12
|
+
|
13
|
+
|
14
|
+
class BrokerCredential(SupportsTokenInfo):
|
15
|
+
"""A broker credential that handles prerequisite checking and falls back appropriately.
|
16
|
+
|
17
|
+
This credential checks if the azure-identity-broker package is available and the platform
|
18
|
+
is supported. If both conditions are met, it uses the real broker credential. Otherwise,
|
19
|
+
it raises CredentialUnavailableError with an appropriate message.
|
20
|
+
"""
|
21
|
+
|
22
|
+
def __init__(self, **kwargs: Any) -> None:
|
23
|
+
|
24
|
+
self._tenant_id = kwargs.pop("tenant_id", None)
|
25
|
+
self._client_id = kwargs.pop("client_id", None)
|
26
|
+
self._broker_credential = None
|
27
|
+
self._unavailable_message = None
|
28
|
+
|
29
|
+
# Check prerequisites and initialize the appropriate credential
|
30
|
+
broker_credential_class = get_broker_credential()
|
31
|
+
if broker_credential_class and (sys.platform.startswith("win") or is_wsl()):
|
32
|
+
# The silent auth flow for brokered auth is available on Windows/WSL with the broker package
|
33
|
+
try:
|
34
|
+
broker_credential_args = {
|
35
|
+
"tenant_id": self._tenant_id,
|
36
|
+
"parent_window_handle": msal.PublicClientApplication.CONSOLE_WINDOW_HANDLE,
|
37
|
+
"use_default_broker_account": True,
|
38
|
+
"disable_interactive_fallback": True,
|
39
|
+
**kwargs,
|
40
|
+
}
|
41
|
+
if self._client_id:
|
42
|
+
broker_credential_args["client_id"] = self._client_id
|
43
|
+
self._broker_credential = broker_credential_class(**broker_credential_args)
|
44
|
+
except Exception as ex: # pylint: disable=broad-except
|
45
|
+
self._unavailable_message = f"InteractiveBrowserBrokerCredential initialization failed: {ex}"
|
46
|
+
else:
|
47
|
+
# Determine the specific reason for unavailability
|
48
|
+
if broker_credential_class is None:
|
49
|
+
self._unavailable_message = (
|
50
|
+
"InteractiveBrowserBrokerCredential unavailable. "
|
51
|
+
"The 'azure-identity-broker' package is required to use brokered authentication."
|
52
|
+
)
|
53
|
+
else:
|
54
|
+
self._unavailable_message = (
|
55
|
+
"InteractiveBrowserBrokerCredential unavailable. "
|
56
|
+
"Brokered authentication is only supported on Windows and WSL platforms."
|
57
|
+
)
|
58
|
+
|
59
|
+
def get_token(self, *scopes: str, **kwargs: Any) -> AccessToken:
|
60
|
+
if self._broker_credential:
|
61
|
+
return self._broker_credential.get_token(*scopes, **kwargs)
|
62
|
+
raise CredentialUnavailableError(message=self._unavailable_message)
|
63
|
+
|
64
|
+
def get_token_info(self, *scopes: str, **kwargs: Any) -> AccessTokenInfo:
|
65
|
+
if self._broker_credential:
|
66
|
+
return self._broker_credential.get_token_info(*scopes, **kwargs)
|
67
|
+
raise CredentialUnavailableError(message=self._unavailable_message)
|
68
|
+
|
69
|
+
def __enter__(self) -> "BrokerCredential":
|
70
|
+
if self._broker_credential:
|
71
|
+
self._broker_credential.__enter__()
|
72
|
+
return self
|
73
|
+
|
74
|
+
def __exit__(self, *args):
|
75
|
+
if self._broker_credential:
|
76
|
+
self._broker_credential.__exit__(*args)
|
77
|
+
|
78
|
+
def close(self) -> None:
|
79
|
+
self.__exit__()
|
@@ -23,10 +23,16 @@ _LOGGER = logging.getLogger(__name__)
|
|
23
23
|
def _get_error_message(history):
|
24
24
|
attempts = []
|
25
25
|
for credential, error in history:
|
26
|
+
# Check if credential has a custom name (for DACErrorReporter instances)
|
27
|
+
if hasattr(credential, "_credential_name"):
|
28
|
+
credential_name = credential._credential_name # pylint: disable=protected-access
|
29
|
+
else:
|
30
|
+
credential_name = credential.__class__.__name__
|
31
|
+
|
26
32
|
if error:
|
27
|
-
attempts.append("{}: {}".format(
|
33
|
+
attempts.append("{}: {}".format(credential_name, error))
|
28
34
|
else:
|
29
|
-
attempts.append(
|
35
|
+
attempts.append(credential_name)
|
30
36
|
return """
|
31
37
|
Attempted credentials:\n\t{}""".format(
|
32
38
|
"\n\t".join(attempts)
|
@@ -41,7 +47,7 @@ class ChainedTokenCredential:
|
|
41
47
|
<"https://aka.ms/azsdk/python/identity/credential-chains#chainedtokencredential-overview">`__.
|
42
48
|
|
43
49
|
:param credentials: credential instances to form the chain
|
44
|
-
:type credentials: ~azure.core.credentials.
|
50
|
+
:type credentials: ~azure.core.credentials.TokenProvider
|
45
51
|
|
46
52
|
.. admonition:: Example:
|
47
53
|
|
@@ -6,10 +6,18 @@ import logging
|
|
6
6
|
import os
|
7
7
|
from typing import List, Any, Optional, cast
|
8
8
|
|
9
|
-
from azure.core.credentials import
|
9
|
+
from azure.core.credentials import (
|
10
|
+
AccessToken,
|
11
|
+
AccessTokenInfo,
|
12
|
+
TokenRequestOptions,
|
13
|
+
SupportsTokenInfo,
|
14
|
+
TokenCredential,
|
15
|
+
)
|
16
|
+
from .. import CredentialUnavailableError
|
10
17
|
from .._constants import EnvironmentVariables
|
11
|
-
from .._internal import get_default_authority, normalize_authority, within_dac
|
18
|
+
from .._internal.utils import get_default_authority, normalize_authority, within_dac, process_credential_exclusions
|
12
19
|
from .azure_powershell import AzurePowerShellCredential
|
20
|
+
from .broker import BrokerCredential
|
13
21
|
from .browser import InteractiveBrowserCredential
|
14
22
|
from .chained import ChainedTokenCredential
|
15
23
|
from .environment import EnvironmentCredential
|
@@ -23,6 +31,32 @@ from .workload_identity import WorkloadIdentityCredential
|
|
23
31
|
_LOGGER = logging.getLogger(__name__)
|
24
32
|
|
25
33
|
|
34
|
+
class FailedDACCredential:
|
35
|
+
"""This acts as a substitute for a credential that has failed to initialize in the DAC chain.
|
36
|
+
|
37
|
+
This allows instantiation errors to be reported in ChainTokenCredential if all token requests fail.
|
38
|
+
"""
|
39
|
+
|
40
|
+
def __init__(self, credential_name: str, error: str) -> None:
|
41
|
+
self._error = error
|
42
|
+
self._credential_name = credential_name
|
43
|
+
|
44
|
+
def get_token(self, *scopes: str, **kwargs: Any) -> AccessToken:
|
45
|
+
raise CredentialUnavailableError(self._error)
|
46
|
+
|
47
|
+
def get_token_info(self, *scopes, options: Optional[TokenRequestOptions] = None, **kwargs: Any) -> AccessTokenInfo:
|
48
|
+
raise CredentialUnavailableError(self._error)
|
49
|
+
|
50
|
+
def __enter__(self) -> "FailedDACCredential":
|
51
|
+
return self
|
52
|
+
|
53
|
+
def __exit__(self, *args: Any) -> None:
|
54
|
+
pass
|
55
|
+
|
56
|
+
def close(self) -> None:
|
57
|
+
pass
|
58
|
+
|
59
|
+
|
26
60
|
class DefaultAzureCredential(ChainedTokenCredential):
|
27
61
|
"""A credential capable of handling most Azure SDK authentication scenarios. For more information, See
|
28
62
|
`Usage guidance for DefaultAzureCredential
|
@@ -42,6 +76,8 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
42
76
|
5. The identity currently logged in to the Azure CLI.
|
43
77
|
6. The identity currently logged in to Azure PowerShell.
|
44
78
|
7. The identity currently logged in to the Azure Developer CLI.
|
79
|
+
8. Brokered authentication. On Windows and WSL only, this uses the default account logged in via
|
80
|
+
Web Account Manager (WAM) if the `azure-identity-broker` package is installed.
|
45
81
|
|
46
82
|
This default behavior is configurable with keyword arguments.
|
47
83
|
|
@@ -64,9 +100,13 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
64
100
|
**False**.
|
65
101
|
:keyword bool exclude_interactive_browser_credential: Whether to exclude interactive browser authentication (see
|
66
102
|
:class:`~azure.identity.InteractiveBrowserCredential`). Defaults to **True**.
|
103
|
+
:keyword bool exclude_broker_credential: Whether to exclude the broker credential from the credential chain.
|
104
|
+
Defaults to **False**.
|
67
105
|
:keyword str interactive_browser_tenant_id: Tenant ID to use when authenticating a user through
|
68
106
|
:class:`~azure.identity.InteractiveBrowserCredential`. Defaults to the value of environment variable
|
69
107
|
AZURE_TENANT_ID, if any. If unspecified, users will authenticate in their home tenants.
|
108
|
+
:keyword str broker_tenant_id: The tenant ID to use when using brokered authentication. Defaults to the value of
|
109
|
+
environment variable AZURE_TENANT_ID, if any. If unspecified, users will authenticate in their home tenants.
|
70
110
|
:keyword str managed_identity_client_id: The client ID of a user-assigned managed identity. Defaults to the value
|
71
111
|
of the environment variable AZURE_CLIENT_ID, if any. If not specified, a system-assigned identity will be used.
|
72
112
|
:keyword str workload_identity_client_id: The client ID of an identity assigned to the pod. Defaults to the value
|
@@ -75,16 +115,20 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
75
115
|
Defaults to the value of environment variable AZURE_TENANT_ID, if any.
|
76
116
|
:keyword str interactive_browser_client_id: The client ID to be used in interactive browser credential. If not
|
77
117
|
specified, users will authenticate to an Azure development application.
|
118
|
+
:keyword str broker_client_id: The client ID to be used in brokered authentication. If not specified, users will
|
119
|
+
authenticate to an Azure development application.
|
78
120
|
:keyword str shared_cache_username: Preferred username for :class:`~azure.identity.SharedTokenCacheCredential`.
|
79
121
|
Defaults to the value of environment variable AZURE_USERNAME, if any.
|
80
122
|
:keyword str shared_cache_tenant_id: Preferred tenant for :class:`~azure.identity.SharedTokenCacheCredential`.
|
81
123
|
Defaults to the value of environment variable AZURE_TENANT_ID, if any.
|
82
124
|
:keyword str visual_studio_code_tenant_id: Tenant ID to use when authenticating with
|
83
|
-
:class:`~azure.identity.VisualStudioCodeCredential`. Defaults to the
|
84
|
-
|
85
|
-
Directory work or school accounts.
|
125
|
+
:class:`~azure.identity.VisualStudioCodeCredential`. Defaults to the tenant specified in the authentication
|
126
|
+
record file used by the Azure Resources extension.
|
86
127
|
:keyword int process_timeout: The timeout in seconds to use for developer credentials that run
|
87
128
|
subprocesses (e.g. AzureCliCredential, AzurePowerShellCredential). Defaults to **10** seconds.
|
129
|
+
:keyword bool require_envvar: If **True**, require that the AZURE_TOKEN_CREDENTIALS environment variable be set
|
130
|
+
to a value denoting the credential type or credential group to use. If unset or empty, DefaultAzureCredential
|
131
|
+
will raise a `ValueError`. Defaults to **False**.
|
88
132
|
|
89
133
|
.. admonition:: Example:
|
90
134
|
|
@@ -101,18 +145,10 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
101
145
|
raise TypeError("'tenant_id' is not supported in DefaultAzureCredential.")
|
102
146
|
|
103
147
|
authority = kwargs.pop("authority", None)
|
104
|
-
|
105
|
-
vscode_tenant_id = kwargs.pop(
|
106
|
-
"visual_studio_code_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
|
107
|
-
)
|
108
|
-
vscode_args = dict(kwargs)
|
109
|
-
if authority:
|
110
|
-
vscode_args["authority"] = authority
|
111
|
-
if vscode_tenant_id:
|
112
|
-
vscode_args["tenant_id"] = vscode_tenant_id
|
113
|
-
|
114
148
|
authority = normalize_authority(authority) if authority else get_default_authority()
|
115
149
|
|
150
|
+
vscode_tenant_id = kwargs.pop("visual_studio_code_tenant_id", None)
|
151
|
+
|
116
152
|
interactive_browser_tenant_id = kwargs.pop(
|
117
153
|
"interactive_browser_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
|
118
154
|
)
|
@@ -126,59 +162,113 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
126
162
|
)
|
127
163
|
interactive_browser_client_id = kwargs.pop("interactive_browser_client_id", None)
|
128
164
|
|
165
|
+
broker_tenant_id = kwargs.pop("broker_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID))
|
166
|
+
broker_client_id = kwargs.pop("broker_client_id", None)
|
167
|
+
|
129
168
|
shared_cache_username = kwargs.pop("shared_cache_username", os.environ.get(EnvironmentVariables.AZURE_USERNAME))
|
130
169
|
shared_cache_tenant_id = kwargs.pop(
|
131
170
|
"shared_cache_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
|
132
171
|
)
|
133
172
|
|
134
173
|
process_timeout = kwargs.pop("process_timeout", 10)
|
135
|
-
|
136
|
-
|
137
|
-
exclude_workload_identity_credential = kwargs.pop("exclude_workload_identity_credential", False)
|
138
|
-
exclude_environment_credential = kwargs.pop("exclude_environment_credential", False)
|
139
|
-
exclude_managed_identity_credential = kwargs.pop("exclude_managed_identity_credential", False)
|
140
|
-
exclude_shared_token_cache_credential = kwargs.pop("exclude_shared_token_cache_credential", False)
|
141
|
-
exclude_visual_studio_code_credential = kwargs.pop("exclude_visual_studio_code_credential", True)
|
142
|
-
exclude_developer_cli_credential = kwargs.pop("exclude_developer_cli_credential", False)
|
143
|
-
exclude_cli_credential = kwargs.pop("exclude_cli_credential", False)
|
144
|
-
exclude_interactive_browser_credential = kwargs.pop("exclude_interactive_browser_credential", True)
|
145
|
-
exclude_powershell_credential = kwargs.pop("exclude_powershell_credential", False)
|
146
|
-
|
147
|
-
if token_credentials_env == "dev":
|
148
|
-
# In dev mode, use only developer credentials
|
149
|
-
exclude_environment_credential = True
|
150
|
-
exclude_managed_identity_credential = True
|
151
|
-
exclude_workload_identity_credential = True
|
152
|
-
elif token_credentials_env == "prod":
|
153
|
-
# In prod mode, use only production credentials
|
154
|
-
exclude_shared_token_cache_credential = True
|
155
|
-
exclude_visual_studio_code_credential = True
|
156
|
-
exclude_cli_credential = True
|
157
|
-
exclude_developer_cli_credential = True
|
158
|
-
exclude_powershell_credential = True
|
159
|
-
exclude_interactive_browser_credential = True
|
160
|
-
elif token_credentials_env != "":
|
161
|
-
# If the environment variable is set to something other than dev or prod, raise an error
|
174
|
+
require_envvar = kwargs.pop("require_envvar", False)
|
175
|
+
if require_envvar and not os.environ.get(EnvironmentVariables.AZURE_TOKEN_CREDENTIALS):
|
162
176
|
raise ValueError(
|
163
|
-
|
164
|
-
"
|
177
|
+
"AZURE_TOKEN_CREDENTIALS environment variable is required but is not set or is empty. "
|
178
|
+
"Set it to 'dev', 'prod', or a specific credential name."
|
165
179
|
)
|
166
180
|
|
181
|
+
# Define credential configuration mapping
|
182
|
+
credential_config = {
|
183
|
+
"environment": {
|
184
|
+
"exclude_param": "exclude_environment_credential",
|
185
|
+
"env_name": "environmentcredential",
|
186
|
+
"default_exclude": False,
|
187
|
+
},
|
188
|
+
"workload_identity": {
|
189
|
+
"exclude_param": "exclude_workload_identity_credential",
|
190
|
+
"env_name": "workloadidentitycredential",
|
191
|
+
"default_exclude": False,
|
192
|
+
},
|
193
|
+
"managed_identity": {
|
194
|
+
"exclude_param": "exclude_managed_identity_credential",
|
195
|
+
"env_name": "managedidentitycredential",
|
196
|
+
"default_exclude": False,
|
197
|
+
},
|
198
|
+
"shared_token_cache": {
|
199
|
+
"exclude_param": "exclude_shared_token_cache_credential",
|
200
|
+
"default_exclude": False,
|
201
|
+
},
|
202
|
+
"visual_studio_code": {
|
203
|
+
"exclude_param": "exclude_visual_studio_code_credential",
|
204
|
+
"env_name": "visualstudiocodecredential",
|
205
|
+
"default_exclude": False,
|
206
|
+
},
|
207
|
+
"cli": {
|
208
|
+
"exclude_param": "exclude_cli_credential",
|
209
|
+
"env_name": "azureclicredential",
|
210
|
+
"default_exclude": False,
|
211
|
+
},
|
212
|
+
"developer_cli": {
|
213
|
+
"exclude_param": "exclude_developer_cli_credential",
|
214
|
+
"env_name": "azuredeveloperclicredential",
|
215
|
+
"default_exclude": False,
|
216
|
+
},
|
217
|
+
"powershell": {
|
218
|
+
"exclude_param": "exclude_powershell_credential",
|
219
|
+
"env_name": "azurepowershellcredential",
|
220
|
+
"default_exclude": False,
|
221
|
+
},
|
222
|
+
"interactive_browser": {
|
223
|
+
"exclude_param": "exclude_interactive_browser_credential",
|
224
|
+
"env_name": "interactivebrowsercredential",
|
225
|
+
"default_exclude": True,
|
226
|
+
},
|
227
|
+
"broker": {
|
228
|
+
"exclude_param": "exclude_broker_credential",
|
229
|
+
"default_exclude": False,
|
230
|
+
},
|
231
|
+
}
|
232
|
+
|
233
|
+
# Extract user-provided exclude flags and set defaults
|
234
|
+
exclude_flags = {}
|
235
|
+
user_excludes = {}
|
236
|
+
for cred_key, config in credential_config.items():
|
237
|
+
param_name = cast(str, config["exclude_param"])
|
238
|
+
user_excludes[cred_key] = kwargs.pop(param_name, None)
|
239
|
+
exclude_flags[cred_key] = config["default_exclude"]
|
240
|
+
|
241
|
+
# Process AZURE_TOKEN_CREDENTIALS environment variable and apply user overrides
|
242
|
+
exclude_flags = process_credential_exclusions(credential_config, exclude_flags, user_excludes)
|
243
|
+
|
244
|
+
# Extract individual exclude flags for backward compatibility
|
245
|
+
exclude_environment_credential = exclude_flags["environment"]
|
246
|
+
exclude_workload_identity_credential = exclude_flags["workload_identity"]
|
247
|
+
exclude_managed_identity_credential = exclude_flags["managed_identity"]
|
248
|
+
exclude_shared_token_cache_credential = exclude_flags["shared_token_cache"]
|
249
|
+
exclude_visual_studio_code_credential = exclude_flags["visual_studio_code"]
|
250
|
+
exclude_cli_credential = exclude_flags["cli"]
|
251
|
+
exclude_developer_cli_credential = exclude_flags["developer_cli"]
|
252
|
+
exclude_powershell_credential = exclude_flags["powershell"]
|
253
|
+
exclude_interactive_browser_credential = exclude_flags["interactive_browser"]
|
254
|
+
exclude_broker_credential = exclude_flags["broker"]
|
255
|
+
|
167
256
|
credentials: List[SupportsTokenInfo] = []
|
168
257
|
within_dac.set(True)
|
169
258
|
if not exclude_environment_credential:
|
170
259
|
credentials.append(EnvironmentCredential(authority=authority, _within_dac=True, **kwargs))
|
171
260
|
if not exclude_workload_identity_credential:
|
172
|
-
|
173
|
-
client_id = workload_identity_client_id
|
261
|
+
try:
|
174
262
|
credentials.append(
|
175
263
|
WorkloadIdentityCredential(
|
176
|
-
client_id=cast(str,
|
264
|
+
client_id=cast(str, workload_identity_client_id),
|
177
265
|
tenant_id=workload_identity_tenant_id,
|
178
|
-
token_file_path=os.environ
|
266
|
+
token_file_path=os.environ.get(EnvironmentVariables.AZURE_FEDERATED_TOKEN_FILE),
|
179
267
|
**kwargs,
|
180
268
|
)
|
181
269
|
)
|
270
|
+
except ValueError as ex:
|
271
|
+
credentials.append(FailedDACCredential("WorkloadIdentityCredential", error=str(ex)))
|
182
272
|
if not exclude_managed_identity_credential:
|
183
273
|
credentials.append(
|
184
274
|
ManagedIdentityCredential(
|
@@ -197,7 +287,7 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
197
287
|
except Exception as ex: # pylint:disable=broad-except
|
198
288
|
_LOGGER.info("Shared token cache is unavailable: '%s'", ex)
|
199
289
|
if not exclude_visual_studio_code_credential:
|
200
|
-
credentials.append(VisualStudioCodeCredential(
|
290
|
+
credentials.append(VisualStudioCodeCredential(tenant_id=vscode_tenant_id))
|
201
291
|
if not exclude_cli_credential:
|
202
292
|
credentials.append(AzureCliCredential(process_timeout=process_timeout))
|
203
293
|
if not exclude_powershell_credential:
|
@@ -213,6 +303,12 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
213
303
|
)
|
214
304
|
else:
|
215
305
|
credentials.append(InteractiveBrowserCredential(tenant_id=interactive_browser_tenant_id, **kwargs))
|
306
|
+
if not exclude_broker_credential:
|
307
|
+
broker_credential_args = {"tenant_id": broker_tenant_id, **kwargs}
|
308
|
+
if broker_client_id:
|
309
|
+
broker_credential_args["client_id"] = broker_client_id
|
310
|
+
credentials.append(BrokerCredential(**broker_credential_args))
|
311
|
+
|
216
312
|
within_dac.set(False)
|
217
313
|
super(DefaultAzureCredential, self).__init__(*credentials)
|
218
314
|
|
@@ -245,8 +341,10 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
245
341
|
)
|
246
342
|
return token
|
247
343
|
within_dac.set(True)
|
248
|
-
|
249
|
-
|
344
|
+
try:
|
345
|
+
token = super().get_token(*scopes, claims=claims, tenant_id=tenant_id, **kwargs)
|
346
|
+
finally:
|
347
|
+
within_dac.set(False)
|
250
348
|
return token
|
251
349
|
|
252
350
|
def get_token_info(self, *scopes: str, options: Optional[TokenRequestOptions] = None) -> AccessTokenInfo:
|
@@ -274,6 +372,8 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
274
372
|
return token_info
|
275
373
|
|
276
374
|
within_dac.set(True)
|
277
|
-
|
278
|
-
|
375
|
+
try:
|
376
|
+
token_info = cast(SupportsTokenInfo, super()).get_token_info(*scopes, options=options)
|
377
|
+
finally:
|
378
|
+
within_dac.set(False)
|
279
379
|
return token_info
|
@@ -6,9 +6,11 @@ import os
|
|
6
6
|
import json
|
7
7
|
from typing import Any, Optional, Dict
|
8
8
|
|
9
|
+
from azure.core.pipeline import PipelineResponse
|
9
10
|
from azure.core.exceptions import ClientAuthenticationError, HttpResponseError
|
10
11
|
from azure.core.pipeline.transport import HttpRequest
|
11
12
|
from azure.core.credentials import AccessTokenInfo
|
13
|
+
from azure.core.pipeline.policies import RetryPolicy
|
12
14
|
|
13
15
|
from .. import CredentialUnavailableError
|
14
16
|
from .._constants import EnvironmentVariables
|
@@ -31,6 +33,28 @@ PIPELINE_SETTINGS = {
|
|
31
33
|
}
|
32
34
|
|
33
35
|
|
36
|
+
class ImdsRetryPolicy(RetryPolicy):
|
37
|
+
"""Custom retry policy for IMDS credential with extended retry duration for 410 responses.
|
38
|
+
|
39
|
+
This policy ensures that specifically for 410 status codes, the total exponential backoff duration
|
40
|
+
is at least 70 seconds to handle temporary IMDS endpoint unavailability.
|
41
|
+
For other status codes, it uses the standard retry behavior.
|
42
|
+
"""
|
43
|
+
|
44
|
+
def __init__(self, **kwargs: Any) -> None:
|
45
|
+
# Increased backoff factor to ensure at least 70 seconds retry duration for 410 responses.
|
46
|
+
# Five retries, with each retry sleeping for [0.0s, 5.0s, 10.0s, 20.0s, 40.0s] between attempts (75s total)
|
47
|
+
self.backoff_factor_for_410 = 2.5
|
48
|
+
super().__init__(**kwargs)
|
49
|
+
|
50
|
+
def is_retry(self, settings: Dict[str, Any], response: PipelineResponse[Any, Any]) -> bool:
|
51
|
+
if response.http_response.status_code == 410:
|
52
|
+
settings["backoff"] = self.backoff_factor_for_410
|
53
|
+
else:
|
54
|
+
settings["backoff"] = self.backoff_factor
|
55
|
+
return super().is_retry(settings, response)
|
56
|
+
|
57
|
+
|
34
58
|
def _get_request(scope: str, identity_config: Dict) -> HttpRequest:
|
35
59
|
url = (
|
36
60
|
os.environ.get(EnvironmentVariables.AZURE_POD_IDENTITY_AUTHORITY_HOST, IMDS_AUTHORITY).strip("/")
|
@@ -58,7 +82,7 @@ def _check_forbidden_response(ex: HttpResponseError) -> None:
|
|
58
82
|
|
59
83
|
class ImdsCredential(MsalManagedIdentityClient):
|
60
84
|
def __init__(self, **kwargs: Any) -> None:
|
61
|
-
super(
|
85
|
+
super().__init__(retry_policy_class=ImdsRetryPolicy, **dict(PIPELINE_SETTINGS, **kwargs))
|
62
86
|
self._config = kwargs
|
63
87
|
|
64
88
|
if EnvironmentVariables.AZURE_POD_IDENTITY_AUTHORITY_HOST in os.environ:
|
@@ -8,7 +8,7 @@ from azure.core.credentials import AccessToken, TokenRequestOptions, AccessToken
|
|
8
8
|
from .silent import SilentAuthenticationCredential
|
9
9
|
from .. import CredentialUnavailableError
|
10
10
|
from .._constants import DEVELOPER_SIGN_ON_CLIENT_ID
|
11
|
-
from .._internal import AadClient, AadClientBase
|
11
|
+
from .._internal import AadClient, AadClientBase, within_dac
|
12
12
|
from .._internal.decorators import log_get_token
|
13
13
|
from .._internal.shared_token_cache import NO_TOKEN, SharedTokenCacheBase
|
14
14
|
|
@@ -191,10 +191,17 @@ class _SharedTokenCacheCredential(SharedTokenCacheBase):
|
|
191
191
|
|
192
192
|
# try each refresh token, returning the first access token acquired
|
193
193
|
for refresh_token in self._get_refresh_tokens(account, is_cae=is_cae):
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
194
|
+
try:
|
195
|
+
token = cast(AadClient, self._client).obtain_token_by_refresh_token(
|
196
|
+
scopes, refresh_token, claims=claims, tenant_id=tenant_id, enable_cae=is_cae, **kwargs
|
197
|
+
)
|
198
|
+
return token
|
199
|
+
except Exception as e: # pylint: disable=broad-except
|
200
|
+
if within_dac.get():
|
201
|
+
raise CredentialUnavailableError( # pylint: disable=raise-missing-from
|
202
|
+
message=getattr(e, "message", str(e)), response=getattr(e, "response", None)
|
203
|
+
)
|
204
|
+
raise
|
198
205
|
|
199
206
|
raise CredentialUnavailableError(message=NO_TOKEN.format(account.get("username")))
|
200
207
|
|