Skip to content

Commit 1500012

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 80159d1 commit 1500012

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,
@@ -141,38 +141,51 @@ class DefaultAzureCredential(ChainedTokenCredential):
141141
:caption: Create a DefaultAzureCredential.
142142
"""
143143

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

148-
authority = kwargs.pop("authority", None)
149175
authority = normalize_authority(authority) if authority else get_default_authority()
150176

151-
vscode_tenant_id = kwargs.pop("visual_studio_code_tenant_id", None)
152-
153-
interactive_browser_tenant_id = kwargs.pop(
154-
"interactive_browser_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
155-
)
156-
157-
managed_identity_client_id = kwargs.pop(
158-
"managed_identity_client_id", os.environ.get(EnvironmentVariables.AZURE_CLIENT_ID)
177+
interactive_browser_tenant_id = interactive_browser_tenant_id or os.environ.get(
178+
EnvironmentVariables.AZURE_TENANT_ID
159179
)
160-
workload_identity_client_id = kwargs.pop("workload_identity_client_id", managed_identity_client_id)
161-
workload_identity_tenant_id = kwargs.pop(
162-
"workload_identity_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
180+
managed_identity_client_id = managed_identity_client_id or os.environ.get(EnvironmentVariables.AZURE_CLIENT_ID)
181+
workload_identity_client_id = workload_identity_client_id or managed_identity_client_id
182+
workload_identity_tenant_id = workload_identity_tenant_id or os.environ.get(
183+
EnvironmentVariables.AZURE_TENANT_ID
163184
)
164-
interactive_browser_client_id = kwargs.pop("interactive_browser_client_id", None)
165-
166-
broker_tenant_id = kwargs.pop("broker_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID))
167-
broker_client_id = kwargs.pop("broker_client_id", None)
185+
broker_tenant_id = broker_tenant_id or os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
186+
shared_cache_username = shared_cache_username or os.environ.get(EnvironmentVariables.AZURE_USERNAME)
187+
shared_cache_tenant_id = shared_cache_tenant_id or os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
168188

169-
shared_cache_username = kwargs.pop("shared_cache_username", os.environ.get(EnvironmentVariables.AZURE_USERNAME))
170-
shared_cache_tenant_id = kwargs.pop(
171-
"shared_cache_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
172-
)
173-
174-
process_timeout = kwargs.pop("process_timeout", 10)
175-
require_envvar = kwargs.pop("require_envvar", False)
176189
token_credentials_env = os.environ.get(EnvironmentVariables.AZURE_TOKEN_CREDENTIALS, "").strip().lower()
177190
if require_envvar and not token_credentials_env:
178191
raise ValueError(
@@ -181,85 +194,82 @@ def __init__(self, **kwargs: Any) -> None: # pylint: disable=too-many-statement
181194
)
182195

183196
# Define credential configuration mapping
184-
credential_config = {
197+
credential_config: Dict[str, Any] = {
185198
"environment": {
186-
"exclude_param": "exclude_environment_credential",
187199
"env_name": "environmentcredential",
188200
"default_exclude": False,
189201
},
190202
"workload_identity": {
191-
"exclude_param": "exclude_workload_identity_credential",
192203
"env_name": "workloadidentitycredential",
193204
"default_exclude": False,
194205
},
195206
"managed_identity": {
196-
"exclude_param": "exclude_managed_identity_credential",
197207
"env_name": "managedidentitycredential",
198208
"default_exclude": False,
199209
},
200210
"shared_token_cache": {
201-
"exclude_param": "exclude_shared_token_cache_credential",
202211
"default_exclude": False,
203212
},
204213
"visual_studio_code": {
205-
"exclude_param": "exclude_visual_studio_code_credential",
206214
"env_name": "visualstudiocodecredential",
207215
"default_exclude": False,
208216
},
209217
"cli": {
210-
"exclude_param": "exclude_cli_credential",
211218
"env_name": "azureclicredential",
212219
"default_exclude": False,
213220
},
214221
"developer_cli": {
215-
"exclude_param": "exclude_developer_cli_credential",
216222
"env_name": "azuredeveloperclicredential",
217223
"default_exclude": False,
218224
},
219225
"powershell": {
220-
"exclude_param": "exclude_powershell_credential",
221226
"env_name": "azurepowershellcredential",
222227
"default_exclude": False,
223228
},
224229
"interactive_browser": {
225-
"exclude_param": "exclude_interactive_browser_credential",
226230
"env_name": "interactivebrowsercredential",
227231
"default_exclude": True,
228232
},
229233
"broker": {
230-
"exclude_param": "exclude_broker_credential",
231234
"default_exclude": False,
232235
},
233236
}
234237

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

243253
# Process AZURE_TOKEN_CREDENTIALS environment variable and apply user overrides
244254
exclude_flags = process_credential_exclusions(credential_config, exclude_flags, user_excludes)
245255

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

258268
credentials: List[SupportsTokenInfo] = []
259269
within_dac.set(True)
260-
if not exclude_environment_credential:
270+
if not _exclude_environment:
261271
credentials.append(EnvironmentCredential(authority=authority, _within_dac=True, **kwargs))
262-
if not exclude_workload_identity_credential:
272+
if not _exclude_workload_identity:
263273
try:
264274
credentials.append(
265275
WorkloadIdentityCredential(
@@ -271,30 +281,30 @@ def __init__(self, **kwargs: Any) -> None: # pylint: disable=too-many-statement
271281
)
272282
except ValueError as ex:
273283
credentials.append(FailedDACCredential("WorkloadIdentityCredential", error=str(ex)))
274-
if not exclude_managed_identity_credential:
284+
if not _exclude_managed_identity:
275285
credentials.append(
276286
ManagedIdentityCredential(
277287
client_id=managed_identity_client_id,
278-
_exclude_workload_identity_credential=exclude_workload_identity_credential,
288+
_exclude_workload_identity_credential=_exclude_workload_identity,
279289
_enable_imds_probe=token_credentials_env != "managedidentitycredential",
280290
**kwargs,
281291
)
282292
)
283-
if not exclude_shared_token_cache_credential and SharedTokenCacheCredential.supported():
293+
if not _exclude_shared_token_cache and SharedTokenCacheCredential.supported():
284294
# username and/or tenant_id are only required when the cache contains tokens for multiple identities
285295
shared_cache = SharedTokenCacheCredential(
286296
username=shared_cache_username, tenant_id=shared_cache_tenant_id, authority=authority, **kwargs
287297
)
288298
credentials.append(shared_cache)
289-
if not exclude_visual_studio_code_credential:
290-
credentials.append(VisualStudioCodeCredential(tenant_id=vscode_tenant_id))
291-
if not exclude_cli_credential:
299+
if not _exclude_visual_studio_code:
300+
credentials.append(VisualStudioCodeCredential(tenant_id=visual_studio_code_tenant_id))
301+
if not _exclude_cli:
292302
credentials.append(AzureCliCredential(process_timeout=process_timeout))
293-
if not exclude_powershell_credential:
303+
if not _exclude_powershell:
294304
credentials.append(AzurePowerShellCredential(process_timeout=process_timeout))
295-
if not exclude_developer_cli_credential:
305+
if not _exclude_developer_cli:
296306
credentials.append(AzureDeveloperCliCredential(process_timeout=process_timeout))
297-
if not exclude_interactive_browser_credential:
307+
if not _exclude_interactive_browser:
298308
if interactive_browser_client_id:
299309
credentials.append(
300310
InteractiveBrowserCredential(
@@ -303,7 +313,7 @@ def __init__(self, **kwargs: Any) -> None: # pylint: disable=too-many-statement
303313
)
304314
else:
305315
credentials.append(InteractiveBrowserCredential(tenant_id=interactive_browser_tenant_id, **kwargs))
306-
if not exclude_broker_credential:
316+
if not _exclude_broker:
307317
broker_credential_args = {"tenant_id": broker_tenant_id, **kwargs}
308318
if broker_client_id:
309319
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)