Skip to content

Commit 8e9c61d

Browse files
committed
Test and doc updates
Signed-off-by: Paul Van Eck <[email protected]>
1 parent f2cfc61 commit 8e9c61d

File tree

4 files changed

+35
-104
lines changed

4 files changed

+35
-104
lines changed

sdk/identity/azure-identity/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
### Features Added
66

77
- Expanded the set of acceptable values for environment variable `AZURE_TOKEN_CREDENTIALS` to allow for selection of a specific credential in the `DefaultAzureCredential` chain. At runtime, only the specified credential will be used when acquiring tokens with `DefaultAzureCredential`. For example, setting `AZURE_TOKEN_CREDENTIALS=WorkloadIdentityCredential` will make `DefaultAzureCredential` use only `WorkloadIdentityCredential`.
8-
- Valid values are `EnvironmentCredential`, `WorkloadIdentityCredential`, `ManagedIdentityCredential`, `AzureCliCredential`, `AzurePowershellCredential`, `AzureDeveloperCliCredential`, and `InteractiveBrowserCredential`. ([#41709](https://github.com/Azure/azure-sdk-for-python/pull/41709))
8+
- Valid values are `EnvironmentCredential`, `WorkloadIdentityCredential`, `ManagedIdentityCredential`, `AzureCliCredential`, `AzurePowershellCredential`, `AzureDeveloperCliCredential`, and `InteractiveBrowserCredential`. ([#41709](https://github.com/Azure/azure-sdk-for-python/pull/41709))
99

1010
### Breaking Changes
1111

sdk/identity/azure-identity/README.md

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -297,31 +297,6 @@ variables:
297297

298298
Configuration is attempted in the preceding order. For example, if values for a client secret and certificate are both present, the client secret is used.
299299

300-
### Configuring DefaultAzureCredential
301-
302-
`DefaultAzureCredential` supports an additional environment variable to customize its behavior:
303-
304-
|Variable name|Value
305-
|-|-
306-
|`AZURE_TOKEN_CREDENTIALS`|Credential name or group
307-
308-
#### AZURE_TOKEN_CREDENTIALS values
309-
310-
You can set `AZURE_TOKEN_CREDENTIALS` to one of the following values to control which credentials `DefaultAzureCredential` attempts to use:
311-
312-
**Individual Credentials:**
313-
- `EnvironmentCredential` - Only use environment variables for service principal authentication
314-
- `WorkloadIdentityCredential` - Only use workload identity for Kubernetes authentication
315-
- `ManagedIdentityCredential` - Only use managed identity authentication
316-
- `AzureCliCredential` - Only use Azure CLI authentication
317-
- `AzurePowerShellCredential` - Only use Azure PowerShell authentication
318-
- `AzureDeveloperCliCredential` - Only use Azure Developer CLI authentication
319-
- `InteractiveBrowserCredential` - Only use interactive browser authentication
320-
321-
**Credential Groups:**
322-
- `prod` - Use deployed service credentials: `EnvironmentCredential`, `WorkloadIdentityCredential`, and `ManagedIdentityCredential`
323-
- `dev` - Use developer credentials: `SharedTokenCacheCredential`, `AzureCliCredential`, `AzurePowerShellCredential`, and `AzureDeveloperCliCredential`
324-
325300
## Continuous Access Evaluation
326301

327302
As of version 1.14.0, accessing resources protected by [Continuous Access Evaluation (CAE)][cae] is possible on a per-request basis. This behavior can be enabled by setting the `enable_cae` keyword argument to `True` in the credential's `get_token` method. CAE isn't supported for developer and managed identity credentials.

sdk/identity/azure-identity/tests/test_token_credentials_env.py

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_token_credentials_env_dev():
2929
credential = DefaultAzureCredential()
3030

3131
# Get the actual credential classes in the chain
32-
actual_classes = {c.__class__ for c in credential.credentials}
32+
actual_classes = [c.__class__ for c in credential.credentials]
3333

3434
# All dev credentials should be present (if supported)
3535
if SharedTokenCacheCredential.supported():
@@ -40,6 +40,9 @@ def test_token_credentials_env_dev():
4040
assert AzureDeveloperCliCredential in actual_classes
4141
assert AzurePowerShellCredential in actual_classes
4242

43+
# Assert no duplicates
44+
assert len(actual_classes) == len(set(actual_classes))
45+
4346
# Production credentials should NOT be present
4447
for cred_class in prod_credentials:
4548
if cred_class == WorkloadIdentityCredential:
@@ -60,18 +63,10 @@ def test_token_credentials_env_prod():
6063
}
6164

6265
with patch.dict("os.environ", {EnvironmentVariables.AZURE_TOKEN_CREDENTIALS: "prod"}, clear=False):
63-
# Print to verify the environment variable is set in the test
64-
print(f"AZURE_TOKEN_CREDENTIALS={os.environ.get(EnvironmentVariables.AZURE_TOKEN_CREDENTIALS)}")
65-
6666
credential = DefaultAzureCredential()
6767

6868
# Get the actual credential classes in the chain
69-
actual_classes = {c.__class__ for c in credential.credentials}
70-
71-
# Print which credentials are actually in the chain
72-
print("Credentials in chain:")
73-
for cls in actual_classes:
74-
print(f" - {cls.__name__}")
69+
actual_classes = [c.__class__ for c in credential.credentials]
7570

7671
# Production credentials should be present
7772
assert EnvironmentCredential in actual_classes
@@ -81,6 +76,9 @@ def test_token_credentials_env_prod():
8176
if all(os.environ.get(var) for var in EnvironmentVariables.WORKLOAD_IDENTITY_VARS):
8277
assert WorkloadIdentityCredential in actual_classes
8378

79+
# Assert no duplicates
80+
assert len(actual_classes) == len(set(actual_classes))
81+
8482
# Developer credentials should NOT be present
8583
for cred_class in dev_credentials:
8684
assert cred_class not in actual_classes
@@ -93,7 +91,7 @@ def test_token_credentials_env_case_insensitive():
9391
credential = DefaultAzureCredential()
9492

9593
# Get the actual credential classes in the chain
96-
actual_classes = {c.__class__ for c in credential.credentials}
94+
actual_classes = [c.__class__ for c in credential.credentials]
9795

9896
# EnvironmentCredential (prod) should not be present
9997
assert EnvironmentCredential not in actual_classes
@@ -113,7 +111,7 @@ def test_token_credentials_env_invalid():
113111
def test_token_credentials_env_with_exclude():
114112
with patch.dict("os.environ", {EnvironmentVariables.AZURE_TOKEN_CREDENTIALS: "prod"}, clear=False):
115113
credential = DefaultAzureCredential(exclude_environment_credential=True)
116-
actual_classes = {c.__class__ for c in credential.credentials}
114+
actual_classes = [c.__class__ for c in credential.credentials]
117115

118116
assert EnvironmentCredential not in actual_classes
119117

@@ -135,17 +133,12 @@ def test_token_credentials_env_workload_identity_credential():
135133
credential = DefaultAzureCredential()
136134

137135
# Get the actual credential classes in the chain
138-
actual_classes = {c.__class__ for c in credential.credentials}
136+
actual_classes = [c.__class__ for c in credential.credentials]
139137

140138
# Only WorkloadIdentityCredential should be present
141139
assert WorkloadIdentityCredential in actual_classes
142140
assert len(actual_classes) == 1
143141

144-
# Verify other credentials are not present
145-
assert EnvironmentCredential not in actual_classes
146-
assert ManagedIdentityCredential not in actual_classes
147-
assert AzureCliCredential not in actual_classes
148-
149142

150143
def test_token_credentials_env_environment_credential():
151144
"""With AZURE_TOKEN_CREDENTIALS=EnvironmentCredential, only EnvironmentCredential should be used"""
@@ -154,17 +147,12 @@ def test_token_credentials_env_environment_credential():
154147
credential = DefaultAzureCredential()
155148

156149
# Get the actual credential classes in the chain
157-
actual_classes = {c.__class__ for c in credential.credentials}
150+
actual_classes = [c.__class__ for c in credential.credentials]
158151

159152
# Only EnvironmentCredential should be present
160153
assert EnvironmentCredential in actual_classes
161154
assert len(actual_classes) == 1
162155

163-
# Verify other credentials are not present
164-
assert WorkloadIdentityCredential not in actual_classes
165-
assert ManagedIdentityCredential not in actual_classes
166-
assert AzureCliCredential not in actual_classes
167-
168156

169157
def test_token_credentials_env_managed_identity_credential():
170158
"""With AZURE_TOKEN_CREDENTIALS=ManagedIdentityCredential, only ManagedIdentityCredential should be used"""
@@ -175,17 +163,12 @@ def test_token_credentials_env_managed_identity_credential():
175163
credential = DefaultAzureCredential()
176164

177165
# Get the actual credential classes in the chain
178-
actual_classes = {c.__class__ for c in credential.credentials}
166+
actual_classes = [c.__class__ for c in credential.credentials]
179167

180168
# Only ManagedIdentityCredential should be present
181169
assert ManagedIdentityCredential in actual_classes
182170
assert len(actual_classes) == 1
183171

184-
# Verify other credentials are not present
185-
assert EnvironmentCredential not in actual_classes
186-
assert WorkloadIdentityCredential not in actual_classes
187-
assert AzureCliCredential not in actual_classes
188-
189172

190173
def test_token_credentials_env_azure_cli_credential():
191174
"""With AZURE_TOKEN_CREDENTIALS=AzureCliCredential, only AzureCliCredential should be used"""
@@ -194,17 +177,12 @@ def test_token_credentials_env_azure_cli_credential():
194177
credential = DefaultAzureCredential()
195178

196179
# Get the actual credential classes in the chain
197-
actual_classes = {c.__class__ for c in credential.credentials}
180+
actual_classes = [c.__class__ for c in credential.credentials]
198181

199182
# Only AzureCliCredential should be present
200183
assert AzureCliCredential in actual_classes
201184
assert len(actual_classes) == 1
202185

203-
# Verify other credentials are not present
204-
assert EnvironmentCredential not in actual_classes
205-
assert ManagedIdentityCredential not in actual_classes
206-
assert WorkloadIdentityCredential not in actual_classes
207-
208186

209187
def test_token_credentials_env_specific_credential_case_insensitive():
210188
"""Specific credential names should be case insensitive"""
@@ -213,7 +191,7 @@ def test_token_credentials_env_specific_credential_case_insensitive():
213191
credential = DefaultAzureCredential()
214192

215193
# Get the actual credential classes in the chain
216-
actual_classes = {c.__class__ for c in credential.credentials}
194+
actual_classes = [c.__class__ for c in credential.credentials]
217195

218196
# Only EnvironmentCredential should be present
219197
assert EnvironmentCredential in actual_classes
@@ -255,7 +233,7 @@ def test_user_exclude_flags_override_env_var():
255233
# Test case 2: env var says use specific credential, user includes additional credential
256234
with patch.dict("os.environ", {EnvironmentVariables.AZURE_TOKEN_CREDENTIALS: "environmentcredential"}, clear=False):
257235
credential = DefaultAzureCredential(exclude_powershell_credential=False)
258-
actual_classes = {c.__class__ for c in credential.credentials}
236+
actual_classes = [c.__class__ for c in credential.credentials]
259237

260238
# Both EnvironmentCredential and AzurePowerShellCredential should be present
261239
assert EnvironmentCredential in actual_classes
@@ -264,7 +242,7 @@ def test_user_exclude_flags_override_env_var():
264242
# Test case 3: env var says "dev" mode, user excludes a dev credential
265243
with patch.dict("os.environ", {EnvironmentVariables.AZURE_TOKEN_CREDENTIALS: "dev"}, clear=False):
266244
credential = DefaultAzureCredential(exclude_cli_credential=True)
267-
actual_classes = {c.__class__ for c in credential.credentials}
245+
actual_classes = [c.__class__ for c in credential.credentials]
268246

269247
# AzureCliCredential should NOT be present despite "dev" mode
270248
assert AzureCliCredential not in actual_classes

sdk/identity/azure-identity/tests/test_token_credentials_env_async.py

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_token_credentials_env_dev():
2929
credential = DefaultAzureCredential()
3030

3131
# Get the actual credential classes in the chain
32-
actual_classes = {c.__class__ for c in credential.credentials}
32+
actual_classes = [c.__class__ for c in credential.credentials]
3333

3434
# All dev credentials should be present (if supported)
3535
if SharedTokenCacheCredential.supported():
@@ -40,6 +40,9 @@ def test_token_credentials_env_dev():
4040
assert AzureDeveloperCliCredential in actual_classes
4141
assert AzurePowerShellCredential in actual_classes
4242

43+
# Assert no duplicates
44+
assert len(actual_classes) == len(set(actual_classes))
45+
4346
# Production credentials should NOT be present
4447
for cred_class in prod_credentials:
4548
if cred_class == WorkloadIdentityCredential:
@@ -60,18 +63,10 @@ def test_token_credentials_env_prod():
6063
}
6164

6265
with patch.dict("os.environ", {EnvironmentVariables.AZURE_TOKEN_CREDENTIALS: "prod"}, clear=False):
63-
# Print to verify the environment variable is set in the test
64-
print(f"AZURE_TOKEN_CREDENTIALS={os.environ.get(EnvironmentVariables.AZURE_TOKEN_CREDENTIALS)}")
65-
6666
credential = DefaultAzureCredential()
6767

6868
# Get the actual credential classes in the chain
69-
actual_classes = {c.__class__ for c in credential.credentials}
70-
71-
# Print which credentials are actually in the chain
72-
print("Credentials in chain:")
73-
for cls in actual_classes:
74-
print(f" - {cls.__name__}")
69+
actual_classes = [c.__class__ for c in credential.credentials]
7570

7671
# Production credentials should be present
7772
assert EnvironmentCredential in actual_classes
@@ -81,6 +76,9 @@ def test_token_credentials_env_prod():
8176
if all(os.environ.get(var) for var in EnvironmentVariables.WORKLOAD_IDENTITY_VARS):
8277
assert WorkloadIdentityCredential in actual_classes
8378

79+
# Assert no duplicates
80+
assert len(actual_classes) == len(set(actual_classes))
81+
8482
# Developer credentials should NOT be present
8583
for cred_class in dev_credentials:
8684
assert cred_class not in actual_classes
@@ -93,7 +91,7 @@ def test_token_credentials_env_case_insensitive():
9391
credential = DefaultAzureCredential()
9492

9593
# Get the actual credential classes in the chain
96-
actual_classes = {c.__class__ for c in credential.credentials}
94+
actual_classes = [c.__class__ for c in credential.credentials]
9795

9896
# EnvironmentCredential (prod) should not be present
9997
assert EnvironmentCredential not in actual_classes
@@ -113,7 +111,7 @@ def test_token_credentials_env_invalid():
113111
def test_token_credentials_env_with_exclude():
114112
with patch.dict("os.environ", {EnvironmentVariables.AZURE_TOKEN_CREDENTIALS: "prod"}, clear=False):
115113
credential = DefaultAzureCredential(exclude_environment_credential=True)
116-
actual_classes = {c.__class__ for c in credential.credentials}
114+
actual_classes = [c.__class__ for c in credential.credentials]
117115

118116
assert EnvironmentCredential not in actual_classes
119117

@@ -135,17 +133,12 @@ def test_token_credentials_env_workload_identity_credential():
135133
credential = DefaultAzureCredential()
136134

137135
# Get the actual credential classes in the chain
138-
actual_classes = {c.__class__ for c in credential.credentials}
136+
actual_classes = [c.__class__ for c in credential.credentials]
139137

140138
# Only WorkloadIdentityCredential should be present
141139
assert WorkloadIdentityCredential in actual_classes
142140
assert len(actual_classes) == 1
143141

144-
# Verify other credentials are not present
145-
assert EnvironmentCredential not in actual_classes
146-
assert ManagedIdentityCredential not in actual_classes
147-
assert AzureCliCredential not in actual_classes
148-
149142

150143
def test_token_credentials_env_environment_credential():
151144
"""With AZURE_TOKEN_CREDENTIALS=EnvironmentCredential, only EnvironmentCredential should be used"""
@@ -154,17 +147,12 @@ def test_token_credentials_env_environment_credential():
154147
credential = DefaultAzureCredential()
155148

156149
# Get the actual credential classes in the chain
157-
actual_classes = {c.__class__ for c in credential.credentials}
150+
actual_classes = [c.__class__ for c in credential.credentials]
158151

159152
# Only EnvironmentCredential should be present
160153
assert EnvironmentCredential in actual_classes
161154
assert len(actual_classes) == 1
162155

163-
# Verify other credentials are not present
164-
assert WorkloadIdentityCredential not in actual_classes
165-
assert ManagedIdentityCredential not in actual_classes
166-
assert AzureCliCredential not in actual_classes
167-
168156

169157
def test_token_credentials_env_managed_identity_credential():
170158
"""With AZURE_TOKEN_CREDENTIALS=ManagedIdentityCredential, only ManagedIdentityCredential should be used"""
@@ -175,17 +163,12 @@ def test_token_credentials_env_managed_identity_credential():
175163
credential = DefaultAzureCredential()
176164

177165
# Get the actual credential classes in the chain
178-
actual_classes = {c.__class__ for c in credential.credentials}
166+
actual_classes = [c.__class__ for c in credential.credentials]
179167

180168
# Only ManagedIdentityCredential should be present
181169
assert ManagedIdentityCredential in actual_classes
182170
assert len(actual_classes) == 1
183171

184-
# Verify other credentials are not present
185-
assert EnvironmentCredential not in actual_classes
186-
assert WorkloadIdentityCredential not in actual_classes
187-
assert AzureCliCredential not in actual_classes
188-
189172

190173
def test_token_credentials_env_azure_cli_credential():
191174
"""With AZURE_TOKEN_CREDENTIALS=AzureCliCredential, only AzureCliCredential should be used"""
@@ -194,17 +177,12 @@ def test_token_credentials_env_azure_cli_credential():
194177
credential = DefaultAzureCredential()
195178

196179
# Get the actual credential classes in the chain
197-
actual_classes = {c.__class__ for c in credential.credentials}
180+
actual_classes = [c.__class__ for c in credential.credentials]
198181

199182
# Only AzureCliCredential should be present
200183
assert AzureCliCredential in actual_classes
201184
assert len(actual_classes) == 1
202185

203-
# Verify other credentials are not present
204-
assert EnvironmentCredential not in actual_classes
205-
assert ManagedIdentityCredential not in actual_classes
206-
assert WorkloadIdentityCredential not in actual_classes
207-
208186

209187
def test_token_credentials_env_specific_credential_case_insensitive():
210188
"""Specific credential names should be case insensitive"""
@@ -213,7 +191,7 @@ def test_token_credentials_env_specific_credential_case_insensitive():
213191
credential = DefaultAzureCredential()
214192

215193
# Get the actual credential classes in the chain
216-
actual_classes = {c.__class__ for c in credential.credentials}
194+
actual_classes = [c.__class__ for c in credential.credentials]
217195

218196
# Only EnvironmentCredential should be present
219197
assert EnvironmentCredential in actual_classes
@@ -255,7 +233,7 @@ def test_user_exclude_flags_override_env_var():
255233
# Test case 2: env var says use specific credential, user includes additional credential
256234
with patch.dict("os.environ", {EnvironmentVariables.AZURE_TOKEN_CREDENTIALS: "environmentcredential"}, clear=False):
257235
credential = DefaultAzureCredential(exclude_powershell_credential=False)
258-
actual_classes = {c.__class__ for c in credential.credentials}
236+
actual_classes = [c.__class__ for c in credential.credentials]
259237

260238
# Both EnvironmentCredential and AzurePowerShellCredential should be present
261239
assert EnvironmentCredential in actual_classes
@@ -264,7 +242,7 @@ def test_user_exclude_flags_override_env_var():
264242
# Test case 3: env var says "dev" mode, user excludes a dev credential
265243
with patch.dict("os.environ", {EnvironmentVariables.AZURE_TOKEN_CREDENTIALS: "dev"}, clear=False):
266244
credential = DefaultAzureCredential(exclude_cli_credential=True)
267-
actual_classes = {c.__class__ for c in credential.credentials}
245+
actual_classes = [c.__class__ for c in credential.credentials]
268246

269247
# AzureCliCredential should NOT be present despite "dev" mode
270248
assert AzureCliCredential not in actual_classes

0 commit comments

Comments
 (0)