Skip to content

Commit 981ba66

Browse files
committed
[Identity] Expand DAC constructor signature
Make all the keyword arguments first-class for easier discoverability and more predictable behavior. Signed-off-by: Paul Van Eck <paulvaneck@microsoft.com>
1 parent 8c03c97 commit 981ba66

3 files changed

Lines changed: 139 additions & 120 deletions

File tree

sdk/identity/azure-identity/azure/identity/_credentials/default.py

Lines changed: 76 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# ------------------------------------
55
import logging
66
import os
7-
from typing import List, Any, Optional, cast
7+
from typing import Dict, List, Any, Optional, cast
88

99
from azure.core.credentials import (
1010
AccessToken,
@@ -144,38 +144,51 @@ class DefaultAzureCredential(ChainedTokenCredential):
144144
:caption: Create a DefaultAzureCredential.
145145
"""
146146

147-
def __init__(self, **kwargs: Any) -> None: # pylint: disable=too-many-statements, too-many-locals
147+
def __init__( # pylint: disable=too-many-statements, too-many-locals
148+
self,
149+
*,
150+
authority: Optional[str] = None,
151+
exclude_environment_credential: Optional[bool] = None,
152+
exclude_workload_identity_credential: Optional[bool] = None,
153+
exclude_managed_identity_credential: Optional[bool] = None,
154+
exclude_shared_token_cache_credential: Optional[bool] = None,
155+
exclude_visual_studio_code_credential: Optional[bool] = None,
156+
exclude_cli_credential: Optional[bool] = None,
157+
exclude_developer_cli_credential: Optional[bool] = None,
158+
exclude_powershell_credential: Optional[bool] = None,
159+
exclude_interactive_browser_credential: Optional[bool] = None,
160+
exclude_broker_credential: Optional[bool] = None,
161+
managed_identity_client_id: Optional[str] = None,
162+
workload_identity_client_id: Optional[str] = None,
163+
workload_identity_tenant_id: Optional[str] = None,
164+
interactive_browser_tenant_id: Optional[str] = None,
165+
interactive_browser_client_id: Optional[str] = None,
166+
broker_tenant_id: Optional[str] = None,
167+
broker_client_id: Optional[str] = None,
168+
shared_cache_username: Optional[str] = None,
169+
shared_cache_tenant_id: Optional[str] = None,
170+
visual_studio_code_tenant_id: Optional[str] = None,
171+
process_timeout: int = 10,
172+
require_envvar: bool = False,
173+
**kwargs: Any,
174+
) -> None:
148175
if "tenant_id" in kwargs:
149176
raise TypeError("'tenant_id' is not supported in DefaultAzureCredential.")
150177

151-
authority = kwargs.pop("authority", None)
152178
authority = normalize_authority(authority) if authority else get_default_authority()
153179

154-
vscode_tenant_id = kwargs.pop("visual_studio_code_tenant_id", None)
155-
156-
interactive_browser_tenant_id = kwargs.pop(
157-
"interactive_browser_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
158-
)
159-
160-
managed_identity_client_id = kwargs.pop(
161-
"managed_identity_client_id", os.environ.get(EnvironmentVariables.AZURE_CLIENT_ID)
180+
interactive_browser_tenant_id = interactive_browser_tenant_id or os.environ.get(
181+
EnvironmentVariables.AZURE_TENANT_ID
162182
)
163-
workload_identity_client_id = kwargs.pop("workload_identity_client_id", managed_identity_client_id)
164-
workload_identity_tenant_id = kwargs.pop(
165-
"workload_identity_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
183+
managed_identity_client_id = managed_identity_client_id or os.environ.get(EnvironmentVariables.AZURE_CLIENT_ID)
184+
workload_identity_client_id = workload_identity_client_id or managed_identity_client_id
185+
workload_identity_tenant_id = workload_identity_tenant_id or os.environ.get(
186+
EnvironmentVariables.AZURE_TENANT_ID
166187
)
167-
interactive_browser_client_id = kwargs.pop("interactive_browser_client_id", None)
168-
169-
broker_tenant_id = kwargs.pop("broker_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID))
170-
broker_client_id = kwargs.pop("broker_client_id", None)
188+
broker_tenant_id = broker_tenant_id or os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
189+
shared_cache_username = shared_cache_username or os.environ.get(EnvironmentVariables.AZURE_USERNAME)
190+
shared_cache_tenant_id = shared_cache_tenant_id or os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
171191

172-
shared_cache_username = kwargs.pop("shared_cache_username", os.environ.get(EnvironmentVariables.AZURE_USERNAME))
173-
shared_cache_tenant_id = kwargs.pop(
174-
"shared_cache_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
175-
)
176-
177-
process_timeout = kwargs.pop("process_timeout", 10)
178-
require_envvar = kwargs.pop("require_envvar", False)
179192
token_credentials_env = os.environ.get(EnvironmentVariables.AZURE_TOKEN_CREDENTIALS, "").strip().lower()
180193
if require_envvar and not token_credentials_env:
181194
raise ValueError(
@@ -184,85 +197,82 @@ def __init__(self, **kwargs: Any) -> None: # pylint: disable=too-many-statement
184197
)
185198

186199
# Define credential configuration mapping
187-
credential_config = {
200+
credential_config: Dict[str, Any] = {
188201
"environment": {
189-
"exclude_param": "exclude_environment_credential",
190202
"env_name": "environmentcredential",
191203
"default_exclude": False,
192204
},
193205
"workload_identity": {
194-
"exclude_param": "exclude_workload_identity_credential",
195206
"env_name": "workloadidentitycredential",
196207
"default_exclude": False,
197208
},
198209
"managed_identity": {
199-
"exclude_param": "exclude_managed_identity_credential",
200210
"env_name": "managedidentitycredential",
201211
"default_exclude": False,
202212
},
203213
"shared_token_cache": {
204-
"exclude_param": "exclude_shared_token_cache_credential",
205214
"default_exclude": False,
206215
},
207216
"visual_studio_code": {
208-
"exclude_param": "exclude_visual_studio_code_credential",
209217
"env_name": "visualstudiocodecredential",
210218
"default_exclude": False,
211219
},
212220
"cli": {
213-
"exclude_param": "exclude_cli_credential",
214221
"env_name": "azureclicredential",
215222
"default_exclude": False,
216223
},
217224
"developer_cli": {
218-
"exclude_param": "exclude_developer_cli_credential",
219225
"env_name": "azuredeveloperclicredential",
220226
"default_exclude": False,
221227
},
222228
"powershell": {
223-
"exclude_param": "exclude_powershell_credential",
224229
"env_name": "azurepowershellcredential",
225230
"default_exclude": False,
226231
},
227232
"interactive_browser": {
228-
"exclude_param": "exclude_interactive_browser_credential",
229233
"env_name": "interactivebrowsercredential",
230234
"default_exclude": True,
231235
},
232236
"broker": {
233-
"exclude_param": "exclude_broker_credential",
234237
"default_exclude": False,
235238
},
236239
}
237240

238-
# Extract user-provided exclude flags and set defaults
239-
exclude_flags = {}
240-
user_excludes = {}
241-
for cred_key, config in credential_config.items():
242-
param_name = cast(str, config["exclude_param"])
243-
user_excludes[cred_key] = kwargs.pop(param_name, None)
244-
exclude_flags[cred_key] = config["default_exclude"]
241+
# Build user-provided exclude flags and defaults
242+
user_excludes = {
243+
"environment": exclude_environment_credential,
244+
"workload_identity": exclude_workload_identity_credential,
245+
"managed_identity": exclude_managed_identity_credential,
246+
"shared_token_cache": exclude_shared_token_cache_credential,
247+
"visual_studio_code": exclude_visual_studio_code_credential,
248+
"cli": exclude_cli_credential,
249+
"developer_cli": exclude_developer_cli_credential,
250+
"powershell": exclude_powershell_credential,
251+
"interactive_browser": exclude_interactive_browser_credential,
252+
"broker": exclude_broker_credential,
253+
}
254+
exclude_flags = {cred_key: config["default_exclude"] for cred_key, config in credential_config.items()}
245255

246256
# Process AZURE_TOKEN_CREDENTIALS environment variable and apply user overrides
247257
exclude_flags = process_credential_exclusions(credential_config, exclude_flags, user_excludes)
248258

249-
# Extract individual exclude flags for backward compatibility
250-
exclude_environment_credential = exclude_flags["environment"]
251-
exclude_workload_identity_credential = exclude_flags["workload_identity"]
252-
exclude_managed_identity_credential = exclude_flags["managed_identity"]
253-
exclude_shared_token_cache_credential = exclude_flags["shared_token_cache"]
254-
exclude_visual_studio_code_credential = exclude_flags["visual_studio_code"]
255-
exclude_cli_credential = exclude_flags["cli"]
256-
exclude_developer_cli_credential = exclude_flags["developer_cli"]
257-
exclude_powershell_credential = exclude_flags["powershell"]
258-
exclude_interactive_browser_credential = exclude_flags["interactive_browser"]
259-
exclude_broker_credential = exclude_flags["broker"]
259+
# Extract individual exclude flags for readability
260+
_exclude_environment = exclude_flags["environment"]
261+
_exclude_workload_identity = exclude_flags["workload_identity"]
262+
_exclude_managed_identity = exclude_flags["managed_identity"]
263+
_exclude_shared_token_cache = exclude_flags["shared_token_cache"]
264+
_exclude_visual_studio_code = exclude_flags["visual_studio_code"]
265+
_exclude_cli = exclude_flags["cli"]
266+
_exclude_developer_cli = exclude_flags["developer_cli"]
267+
_exclude_powershell = exclude_flags["powershell"]
268+
_exclude_interactive_browser = exclude_flags["interactive_browser"]
269+
_exclude_broker = exclude_flags["broker"]
260270

261271
credentials: List[SupportsTokenInfo] = []
262272
within_dac.set(True)
263-
if not exclude_environment_credential:
273+
if not _exclude_environment:
264274
credentials.append(EnvironmentCredential(authority=authority, _within_dac=True, **kwargs))
265-
if not exclude_workload_identity_credential:
275+
if not _exclude_workload_identity:
266276
try:
267277
credentials.append(
268278
WorkloadIdentityCredential(
@@ -274,30 +284,30 @@ def __init__(self, **kwargs: Any) -> None: # pylint: disable=too-many-statement
274284
)
275285
except ValueError as ex:
276286
credentials.append(FailedDACCredential("WorkloadIdentityCredential", error=str(ex)))
277-
if not exclude_managed_identity_credential:
287+
if not _exclude_managed_identity:
278288
credentials.append(
279289
ManagedIdentityCredential(
280290
client_id=managed_identity_client_id,
281-
_exclude_workload_identity_credential=exclude_workload_identity_credential,
291+
_exclude_workload_identity_credential=_exclude_workload_identity,
282292
_enable_imds_probe=token_credentials_env != "managedidentitycredential",
283293
**kwargs,
284294
)
285295
)
286-
if not exclude_shared_token_cache_credential and SharedTokenCacheCredential.supported():
296+
if not _exclude_shared_token_cache and SharedTokenCacheCredential.supported():
287297
# username and/or tenant_id are only required when the cache contains tokens for multiple identities
288298
shared_cache = SharedTokenCacheCredential(
289299
username=shared_cache_username, tenant_id=shared_cache_tenant_id, authority=authority, **kwargs
290300
)
291301
credentials.append(shared_cache)
292-
if not exclude_visual_studio_code_credential:
293-
credentials.append(VisualStudioCodeCredential(tenant_id=vscode_tenant_id))
294-
if not exclude_cli_credential:
302+
if not _exclude_visual_studio_code:
303+
credentials.append(VisualStudioCodeCredential(tenant_id=visual_studio_code_tenant_id))
304+
if not _exclude_cli:
295305
credentials.append(AzureCliCredential(process_timeout=process_timeout))
296-
if not exclude_powershell_credential:
306+
if not _exclude_powershell:
297307
credentials.append(AzurePowerShellCredential(process_timeout=process_timeout))
298-
if not exclude_developer_cli_credential:
308+
if not _exclude_developer_cli:
299309
credentials.append(AzureDeveloperCliCredential(process_timeout=process_timeout))
300-
if not exclude_interactive_browser_credential:
310+
if not _exclude_interactive_browser:
301311
if interactive_browser_client_id:
302312
credentials.append(
303313
InteractiveBrowserCredential(
@@ -306,7 +316,7 @@ def __init__(self, **kwargs: Any) -> None: # pylint: disable=too-many-statement
306316
)
307317
else:
308318
credentials.append(InteractiveBrowserCredential(tenant_id=interactive_browser_tenant_id, **kwargs))
309-
if not exclude_broker_credential:
319+
if not _exclude_broker:
310320
broker_credential_args = {"tenant_id": broker_tenant_id, **kwargs}
311321
if broker_client_id:
312322
broker_credential_args["client_id"] = broker_client_id

sdk/identity/azure-identity/azure/identity/_internal/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,11 @@ def process_credential_exclusions(credential_config: dict, exclude_flags: dict,
191191
any user-provided exclude overrides which take precedence over environment settings.
192192
193193
:param credential_config: Configuration mapping for all available credentials, containing
194-
exclude parameter names, environment names, and default exclude settings
194+
environment names and default exclude settings
195195
:type credential_config: dict
196196
:param exclude_flags: Dictionary of exclude flags for each credential (will be modified)
197197
:type exclude_flags: dict
198-
:param user_excludes: User-provided exclude overrides from constructor kwargs
198+
:param user_excludes: User-provided exclude overrides (None means not specified)
199199
:type user_excludes: dict
200200
201201
:return: Dictionary of final exclude flags for each credential

0 commit comments

Comments
 (0)