Skip to content

Commit 8262041

Browse files
authored
Support user-based authentication in live tests (#33994)
1 parent 4872214 commit 8262041

File tree

2 files changed

+74
-24
lines changed

2 files changed

+74
-24
lines changed

doc/dev/tests.md

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ Live Azure resources will be necessary in order to run live tests and produce re
181181
resource management commands, documented in [/eng/common/TestResources][test_resources], that streamline this process.
182182
Both pure ARM templates (`test-resources.json`) and BICEP files (`test-resources.bicep`) are supported.
183183

184+
User-based authentication is preferred when using test resources. To enable this:
185+
- Use the [`-UserAuth` command flag][user_auth_flag] when running the `New-TestResources` script.
186+
- Set the environment variable `AZURE_TEST_USE_PWSH_AUTH` to "true" to authenticate with Azure PowerShell, or
187+
`AZURE_TEST_USE_CLI_AUTH` to "true" to authenticate with Azure CLI.
188+
- Ensure you're logged into the tool you choose -- if
189+
you used `New-TestResources.ps1` to deploy resources, you'll already have logged in with Azure PowerShell.
190+
184191
If you haven't yet set up a `test-resources` file for test resource deployment and/or want to use test resources of
185192
your own, you can just configure credentials to target these resources instead.
186193

@@ -209,14 +216,20 @@ environment variables necessary to run live tests for the service. After storing
209216
-- formatted as `VARIABLE=value` on separate lines -- your credentials and test configuration variables will be set in
210217
our environment when running tests.
211218

219+
If you used the [`-UserAuth` command flag][user_auth_flag] to deploy test resources, set either
220+
`AZURE_TEST_USE_PWSH_AUTH` or `AZURE_TEST_USE_CLI_AUTH` to "true" to authenticate with Azure PowerShell or Azure CLI,
221+
respectively. If both are set to true, Azure PowerShell will be used.
222+
212223
If your service doesn't have a `test-resources` file for test deployment, you'll need to set environment variables
213-
for `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, and `AZURE_CLIENT_SECRET` at minimum.
224+
for authentication at minimum. For user-based authentication, use `AZURE_TEST_USE_PWSH_AUTH` or
225+
`AZURE_TEST_USE_CLI_AUTH` as described above.
214226

227+
For service principal authentication:
215228
1. Set the `AZURE_SUBSCRIPTION_ID` variable to your organization's subscription ID. You can find it in the "Overview"
216229
section of the "Subscriptions" blade in the [Azure Portal][azure_portal].
217230
2. Define the `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, and `AZURE_CLIENT_SECRET` of a test service principal. If you do not
218-
have a service principal, use the Azure CLI's [az ad sp create-for-rbac][azure_cli_service_principal] command (ideally,
219-
using your alias as the service principal's name prefix):
231+
have a service principal, use the Azure CLI's [az ad sp create-for-rbac][azure_cli_service_principal] command
232+
(ideally, using your alias as the service principal's name prefix):
220233

221234
```
222235
az login
@@ -326,7 +339,9 @@ well. To run tests in playback, either set `AZURE_TEST_RUN_LIVE` to "false" or l
326339

327340
### Run and record tests
328341

329-
With the `AZURE_TEST_RUN_LIVE` environment variable set to "true", use `pytest` to run your test(s) in live mode.
342+
First, refer to the [Configure test variables](#configure-test-variables) section to ensure environment variables are
343+
set for test resources and authentication. With the `AZURE_TEST_RUN_LIVE` environment variable set to "true", use
344+
`pytest` to run your test(s) in live mode.
330345

331346
```
332347
(env) azure-sdk-for-python\sdk\my-service\my-package> pytest tests
@@ -339,18 +354,18 @@ Playback test errors most frequently indicate a need for additional sanitizers a
339354
[Sanitize secrets](#sanitize-secrets)). If you encounter any unexpected errors, refer to the
340355
[test proxy troubleshooting guide][troubleshooting_guide].
341356

342-
At this point there should folder called `recordings` inside your package's `tests` directory. Each recording in this
343-
folder will be a `.json` file that captures the HTTP traffic that was generated while running the test matching the
344-
file's name.
357+
If tests were recorded for a new library, there should now be a folder called `recordings` inside your package's
358+
`tests` directory. Each recording in this folder will be a `.json` file that captures the HTTP traffic that was
359+
generated while running the test matching the file's name.
345360

346361
The final step in setting up recordings is to move these files out of the `azure-sdk-for-python` and into the
347362
`azure-sdk-assets` repository. The [recording migration guide][recording_move] describes how to do so. This step only
348-
needs to be completed once. Your library will have an `assets.json` file at its root, which stores the `azure-sdk-assets`
349-
tag that contains the current set of recordings.
363+
needs to be completed once. Your library will have an `assets.json` file at its root, which stores the
364+
`azure-sdk-assets` tag that contains the current set of recordings.
350365

351-
From this point on, recordings will automatically be fetched when tests are run in playback mode -- either from
352-
a local cache (described in [Update test recordings](#update-test-recordings)), or from `azure-sdk-assets` if they're
353-
not locally available.
366+
From this point on, recordings will automatically be fetched when tests are run in playback mode -- either from a local
367+
cache (described in [Update test recordings](#update-test-recordings)), or from `azure-sdk-assets` if they're not
368+
locally available.
354369

355370
#### Update test recordings
356371

@@ -725,3 +740,4 @@ Tests that use the Shared Access Signature (SAS) to authenticate a client should
725740
[test_proxy_startup]: https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/test_proxy_migration_guide.md#start-the-proxy-server
726741
[test_resources]: https://github.com/Azure/azure-sdk-for-python/tree/main/eng/common/TestResources#readme
727742
[troubleshooting_guide]: https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/test_proxy_troubleshooting.md
743+
[user_auth_flag]: https://github.com/Azure/azure-sdk-for-python/blob/main/eng/common/TestResources/New-TestResources.ps1.md#-userauth

tools/azure-sdk-tools/devtools_testutils/azure_recorded_testcase.py

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# license information.
55
# --------------------------------------------------------------------------
66
import functools
7+
import logging
78
import os
89
import os.path
910
import six
@@ -24,6 +25,8 @@
2425
from .sanitizers import add_general_string_sanitizer
2526

2627

28+
_LOGGER = logging.getLogger()
29+
2730
load_dotenv(find_dotenv())
2831

2932

@@ -87,23 +90,54 @@ def get_credential(self, client_class, **kwargs):
8790
tenant_id = os.environ.get("AZURE_TENANT_ID", getattr(os.environ, "TENANT_ID", None))
8891
client_id = os.environ.get("AZURE_CLIENT_ID", getattr(os.environ, "CLIENT_ID", None))
8992
secret = os.environ.get("AZURE_CLIENT_SECRET", getattr(os.environ, "CLIENT_SECRET", None))
93+
94+
use_pwsh = os.environ.get("AZURE_TEST_USE_PWSH_AUTH", "false")
95+
use_cli = os.environ.get("AZURE_TEST_USE_CLI_AUTH", "false")
9096
is_async = kwargs.pop("is_async", False)
9197

92-
if tenant_id and client_id and secret and self.is_live:
93-
if _is_autorest_v3(client_class):
94-
# Create azure-identity class
95-
from azure.identity import ClientSecretCredential
98+
# Return live credentials only in live mode
99+
if self.is_live:
100+
# User-based authentication through Azure PowerShell, if requested
101+
if use_pwsh.lower() == "true":
102+
_LOGGER.info(
103+
"Environment variable AZURE_TEST_USE_PWSH_AUTH set to 'true'. Using AzurePowerShellCredential."
104+
)
105+
from azure.identity import AzurePowerShellCredential
96106

97107
if is_async:
98-
from azure.identity.aio import ClientSecretCredential
99-
return ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=secret)
100-
else:
101-
# Create msrestazure class
102-
from msrestazure.azure_active_directory import (
103-
ServicePrincipalCredentials,
104-
)
108+
from azure.identity.aio import AzurePowerShellCredential
109+
return AzurePowerShellCredential()
110+
# User-based authentication through Azure CLI, if requested
111+
if use_cli.lower() == "true":
112+
_LOGGER.info("Environment variable AZURE_TEST_USE_CLI_AUTH set to 'true'. Using AzureCliCredential.")
113+
from azure.identity import AzureCliCredential
114+
115+
if is_async:
116+
from azure.identity.aio import AzureCliCredential
117+
return AzureCliCredential()
118+
119+
# Service principal authentication
120+
if tenant_id and client_id and secret:
121+
# Check for track 2 client
122+
if _is_autorest_v3(client_class):
123+
_LOGGER.info(
124+
"Service principal client ID, secret, and tenant ID detected. Using ClientSecretCredential.\n"
125+
"For user-based auth, set AZURE_TEST_USE_PWSH_AUTH or AZURE_TEST_USE_CLI_AUTH to 'true'."
126+
)
127+
from azure.identity import ClientSecretCredential
128+
129+
if is_async:
130+
from azure.identity.aio import ClientSecretCredential
131+
return ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=secret)
132+
else:
133+
# Create msrestazure class
134+
from msrestazure.azure_active_directory import (
135+
ServicePrincipalCredentials,
136+
)
137+
138+
return ServicePrincipalCredentials(tenant=tenant_id, client_id=client_id, secret=secret)
105139

106-
return ServicePrincipalCredentials(tenant=tenant_id, client_id=client_id, secret=secret)
140+
# For playback tests, return credentials that will accept playback `get_token` calls
107141
else:
108142
if _is_autorest_v3(client_class):
109143
if is_async:

0 commit comments

Comments
 (0)