Skip to content

Commit 58d9dc1

Browse files
authoredFeb 10, 2025··
Fix access token cache issue (#27050)
* Fix access token cache issue * Update doc and script
1 parent fc20411 commit 58d9dc1

File tree

14 files changed

+113
-355
lines changed

14 files changed

+113
-355
lines changed
 

‎documentation/testing-docs/using-azure-test-framework.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ This cmdlet enables you to generate a credentials file (located in `C:/Users/<cu
5656

5757
#### Use user account to record test cases (Recommended)
5858

59-
Using a user account is the preferred method for recording test cases as it avoids storing secret in the local file with plain text. You can obtain the object ID of the user account either from the Azure portal or through Azure PowerShell.
59+
Using a user account is the preferred method for recording test cases as it avoids storing secret in the local file with plain text. The value of the UserId is your **email account** in the tenant where you plan to record the test.
6060

6161
```powershell
62-
Set-TestFxEnvironment -UserId <UserId> -SubscriptionId <SubscriptionId> -TenantId <TenantId> -RecorderMode "Record"
62+
Set-TestFxEnvironment -UserId <EmailAccount> -SubscriptionId <SubscriptionId> -TenantId <TenantId> -RecorderMode "Record"
6363
```
6464

6565
#### Create New Service Principal (Not Recommended)
@@ -108,7 +108,7 @@ You can use either a user account (Recommended) or a Service Principal to record
108108
With user account, you may set the following environment variables:
109109

110110
```
111-
TEST_CSM_ORGID_AUTHENTICATION=Environment=Prod;SubscriptionId=<SubscriptionId>;TenantId=<TenantId>;UserId=<UserId>;
111+
TEST_CSM_ORGID_AUTHENTICATION=Environment=Prod;SubscriptionId=<SubscriptionId>;TenantId=<TenantId>;UserId=<EmailAccount>;
112112
AZURE_TEST_MODE=Record
113113
```
114114

‎src/Attestation/Attestation.Test/ScenarioTests/AttestationTestRunner.cs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// ----------------------------------------------------------------------------------
1414

1515
using Microsoft.Azure.Attestation;
16+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
1617
using Microsoft.Azure.Commands.TestFx;
1718
using Microsoft.Azure.Management.Attestation;
1819
using Microsoft.Azure.Management.Internal.Resources;
@@ -74,15 +75,8 @@ private static AttestationManagementClient GetAttestationManagementClient(MockCo
7475

7576
private static AttestationClient GetAttestationClient(MockContext context)
7677
{
77-
string accessToken = "fakefakefake";
78-
79-
// When recording, we should have a connection string passed into the code from the environment
80-
if (HttpMockServer.Mode == HttpRecorderMode.Record)
81-
{
82-
accessToken = TestEnvironmentFactory.GetTestEnvironment().GetAccessToken(new[] { "https://attest.azure.net/.default" });
83-
}
84-
85-
return new AttestationClient(new AttestationCredentials(accessToken), HttpMockServer.CreateInstance());
78+
var creds = TestEnvironmentFactory.GetTestEnvironment().GetAccessToken(AzureEnvironmentConstants.AzureAttestationServiceEndpointResourceId);
79+
return new AttestationClient(creds, HttpMockServer.CreateInstance());
8680
}
8781
}
8882
}

‎src/DataLakeStore/DataLakeStore.Test/ScenarioTests/DataLakeStoreTestRunner.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
1516
using Microsoft.Azure.Commands.DataLakeStore.Models;
1617
using Microsoft.Azure.Commands.TestFx;
1718
using System.Collections.Generic;
@@ -57,12 +58,11 @@ protected DataLakeStoreTestRunner(ITestOutputHelper output)
5758
)
5859
.WithManagementClients(mockContext =>
5960
{
60-
var currentEnvironment = TestEnvironmentFactory.GetTestEnvironment();
6161
AdlsClientFactory.IsTest = true;
62-
AdlsClientFactory.CustomDelegatingHAndler = mockContext.AddHandlers(currentEnvironment, new AdlMockDelegatingHandler());
63-
AdlsClientFactory.MockCredentials = currentEnvironment.TokenInfo[TokenAudience.Management];
64-
var dummyObj = new object();
65-
return dummyObj;
62+
var creds = TestEnvironmentFactory.GetTestEnvironment().GetAccessToken(AzureEnvironmentConstants.AzureDataLakeStoreFileSystemEndpointSuffix);
63+
AdlsClientFactory.CustomDelegatingHAndler = mockContext.AddHandlers(creds, new AdlMockDelegatingHandler());
64+
AdlsClientFactory.MockCredentials = creds;
65+
return new object();
6666
}
6767
)
6868
.WithCleanupAction(

‎src/Network/Network.Test/ScenarioTests/NetworkTestRunner.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
1516
using Microsoft.Azure.Commands.TestFx;
1617
using Microsoft.Azure.KeyVault;
1718
using Microsoft.Azure.Test.HttpRecorder;
18-
using Microsoft.Rest;
1919
using Microsoft.Rest.ClientRuntime.Azure.TestFramework;
20-
using System;
2120
using System.Collections.Generic;
2221
using Xunit.Abstractions;
2322

@@ -76,15 +75,8 @@ protected NetworkTestRunner(ITestOutputHelper output)
7675

7776
private static KeyVaultClient GetKeyVaultClient(MockContext context)
7877
{
79-
string accessToken = "fakefakefake";
80-
81-
// When recording, we should have a connection string passed into the code from the environment
82-
if (HttpMockServer.Mode == HttpRecorderMode.Record)
83-
{
84-
accessToken = TestEnvironmentFactory.GetTestEnvironment().GetAccessToken(new[] { "https://vault.azure.net/.default" });
85-
}
86-
87-
return new KeyVaultClient(new TokenCredentials(accessToken), HttpMockServer.CreateInstance());
78+
var creds = TestEnvironmentFactory.GetTestEnvironment().GetAccessToken(AzureEnvironmentConstants.AzureKeyVaultServiceEndpointResourceId);
79+
return new KeyVaultClient(creds, HttpMockServer.CreateInstance());
8880
}
8981
}
9082
}

‎src/Synapse/Synapse.Test/ScenarioTests/SynapseTestRunner.cs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
1516
using Microsoft.Azure.Commands.TestFx;
1617
using Microsoft.Azure.Synapse;
1718
using Microsoft.Azure.Test.HttpRecorder;
@@ -78,15 +79,8 @@ protected SynapseTestRunner(ITestOutputHelper output)
7879

7980
protected static SynapseClient GetSynapseClient(MockContext context)
8081
{
81-
string accessToken = "fakefakefake";
82-
83-
// When recording, we should have a connection string passed into the code from the environment
84-
if (HttpMockServer.Mode == HttpRecorderMode.Record)
85-
{
86-
accessToken = TestEnvironmentFactory.GetTestEnvironment().GetAccessToken(new[] { "https://dev.azuresynapse.net/.default" });
87-
}
88-
89-
return new SynapseClient(new TokenCredentials(accessToken), HttpMockServer.CreateInstance());
82+
var creds = TestEnvironmentFactory.GetTestEnvironment().GetAccessToken(AzureEnvironmentConstants.AzureSynapseAnalyticsEndpointResourceId);
83+
return new SynapseClient(creds, HttpMockServer.CreateInstance());
9084
}
9185
}
9286
}

‎tools/Modules/TestFx-Tasks.psm1

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function Set-TestFxEnvironment {
2929

3030
[Parameter(Mandatory, ParameterSetName = "UserAccount")]
3131
[ValidateNotNullOrEmpty()]
32-
[guid] $UserId,
32+
[string] $UserId,
3333

3434
[Parameter(Mandatory, ParameterSetName = "NewServicePrincipal")]
3535
[ValidateNotNullOrEmpty()]
@@ -113,10 +113,10 @@ function Set-TestFxEnvironment {
113113
}
114114

115115
$testFxEnvProps = [PSCustomObject]@{
116-
Environment = $TargetEnvironment
117-
SubscriptionId = $SubscriptionId
118-
TenantId = $TenantId
119-
HttpRecorderMode = $RecorderMode
116+
Environment = $TargetEnvironment
117+
SubscriptionId = $SubscriptionId
118+
TenantId = $TenantId
119+
HttpRecorderMode = $RecorderMode
120120
}
121121

122122
switch ($PSCmdlet.ParameterSetName) {

‎tools/TestFx/DelegatingHandlers/HttpMockServer.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15+
using Microsoft.Azure.Commands.Common.Authentication;
16+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
17+
using Microsoft.Azure.Commands.ResourceManager.Common;
1518
using Microsoft.Azure.Commands.TestFx;
1619
using Microsoft.Azure.Commands.TestFx.Recorder;
1720
using System;
@@ -65,8 +68,16 @@ public static void Initialize(string callerIdentity, string testIdentity)
6568
Mode = HttpRecorderMode.Playback;
6669
}
6770

68-
if (Mode == HttpRecorderMode.Playback)
71+
if (Mode == HttpRecorderMode.Record)
6972
{
73+
AzureSession.Instance.ARMContextSaveMode = ContextSaveMode.CurrentUser;
74+
ProtectedProfileProvider.InitializeResourceManagerProfile();
75+
}
76+
else if (Mode == HttpRecorderMode.Playback)
77+
{
78+
AzureSession.Instance.ARMContextSaveMode = ContextSaveMode.Process;
79+
ResourceManagerProfileProvider.InitializeResourceManagerProfile();
80+
7081
var recordDir = Path.Combine(RecordsDirectory, CallerIdentity);
7182
var fileName = Path.GetFullPath(Path.Combine(recordDir, testIdentity.Replace(".json", "") + ".json"));
7283
if (!FileSystemUtilsObject.DirectoryExists(recordDir) || !FileSystemUtilsObject.FileExists(fileName))

‎tools/TestFx/DelegatingHandlers/ResourceCleanerDelegatingHandler.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ public class ResourceCleanerDelegatingHandler : DelegatingHandler
2727
{
2828
private readonly Regex _resourceGroupPattern = new Regex(@"/subscriptions/[^/]+/resourcegroups/([^?]+)\?api-version");
2929
private readonly HashSet<string> _resourceGroupsCreated = new HashSet<string>();
30-
private readonly TokenCredentials _tokenCredentials;
30+
private readonly ServiceClientCredentials _credentials;
3131

32-
public ResourceCleanerDelegatingHandler(TokenCredentials tokenCredentials)
32+
public ResourceCleanerDelegatingHandler(ServiceClientCredentials credentials)
3333
{
34-
_tokenCredentials = tokenCredentials;
34+
_credentials = credentials;
3535
}
3636

3737
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
@@ -55,7 +55,7 @@ public async Task DeleteResourceGroups()
5555
RequestUri = new Uri(resourceGroupUri)
5656
};
5757

58-
_tokenCredentials.ProcessHttpRequestAsync(httpRequest, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult();
58+
_credentials.ProcessHttpRequestAsync(httpRequest, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult();
5959

6060
HttpResponseMessage httpResponse = await httpClient.SendAsync(httpRequest).ConfigureAwait(false);
6161
string groupName = _resourceGroupPattern.Match(resourceGroupUri).Groups[1].Value;

‎tools/TestFx/EnvironmentSetupHelper.cs

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
1717
using Microsoft.Azure.Commands.Common.Authentication.Models;
1818
using Microsoft.Azure.Commands.Common.Authentication.Properties;
19-
using Microsoft.Azure.Commands.ScenarioTest;
2019
using Microsoft.Azure.Commands.TestFx.Mocks;
2120
using Microsoft.Azure.ServiceManagement.Common.Models;
2221
using Microsoft.Rest.ClientRuntime.Azure.TestFramework;
@@ -39,9 +38,9 @@ namespace Microsoft.Azure.Commands.TestFx
3938
{
4039
public class EnvironmentSetupHelper
4140
{
42-
private const string TestFxEnvironmentName = "__testfx-environment";
41+
private const string TestFxEnvironmentName = "testfx-environment";
4342

44-
private const string TestFxSubscriptionName = "__testfx-subscription";
43+
private const string TestFxSubscriptionName = "testfx-subscription";
4544

4645
private static string PackageDirectoryFromCommon { get; } = GetConfigDirectory();
4746

@@ -78,17 +77,17 @@ public EnvironmentSetupHelper()
7877
LogIfNotNull($"Insights Module path: {module}");
7978
RMInsightsModule = module;
8079
module = GetModuleManifest(RmDirectory, "Az.Storage");
81-
LogIfNotNull($"Storage Management Module path: {module}");
80+
LogIfNotNull($"Storage Module path: {module}");
8281
RMStorageModule = module;
83-
module = GetModuleManifest(StorageDirectory, "Azure.Storage");
84-
LogIfNotNull($"Storage Data Plane Module path: {module}");
85-
RMStorageDataPlaneModule = module;
8682
module = GetModuleManifest(RmDirectory, "Az.OperationalInsights");
87-
LogIfNotNull($"Storage Data Plane Module path: {module}");
83+
LogIfNotNull($"OperationalInsights Module path: {module}");
8884
RMOperationalInsightsModule = module;
8985
module = GetModuleManifest(RmDirectory, "Az.Network");
9086
LogIfNotNull($"Network Module path: {module}");
9187
RMNetworkModule = module;
88+
module = GetModuleManifest(RmDirectory, "Az.KeyVault");
89+
LogIfNotNull($"KeyVault Module path: {module}");
90+
RMKeyVaultModule = module;
9291
module = GetModuleManifest(RmDirectory, "Az.EventHub");
9392
LogIfNotNull($"EventHub Module path: {module}");
9493
RMEventHubModule = module;
@@ -102,33 +101,8 @@ public EnvironmentSetupHelper()
102101
LogIfNotNull($"Stack Resources Module path: {module}");
103102
StackRMResourceModule = module;
104103
module = GetModuleManifest(StackRmDirectory, "Az.Storage");
105-
LogIfNotNull($"Stack Storage Management Plane Module path: {module}");
104+
LogIfNotNull($"Stack Storage Module path: {module}");
106105
StackRMStorageModule = module;
107-
module = GetModuleManifest(StackStorageDirectory, "Azure.Storage");
108-
LogIfNotNull($"Stack Storage Data Plane Module path: {module}");
109-
StackRMStorageDataPlaneModule = module;
110-
module = GetModuleManifest(RmDirectory, "Az.KeyVault");
111-
LogIfNotNull($"KeyVault Module path: {module}");
112-
RMKeyVaultModule = module;
113-
114-
TestExecutionHelpers.SetUpSessionAndProfile();
115-
IDataStore datastore = new MemoryDataStore();
116-
if (AzureSession.Instance.DataStore != null && (AzureSession.Instance.DataStore is MemoryDataStore))
117-
{
118-
datastore = AzureSession.Instance.DataStore;
119-
}
120-
121-
AzureSession.Instance.DataStore = datastore;
122-
var rmprofile = new AzureRmProfile(Path.Combine(AzureSession.Instance.ProfileDirectory, AzureSession.Instance.ProfileFile));
123-
rmprofile.EnvironmentTable.Add("foo", new AzureEnvironment(AzureEnvironment.PublicEnvironments.Values.FirstOrDefault()));
124-
rmprofile.DefaultContext = new AzureContext(new AzureSubscription(), new AzureAccount(), rmprofile.EnvironmentTable["foo"], new AzureTenant());
125-
rmprofile.DefaultContext.Subscription.SetEnvironment("foo");
126-
if (AzureRmProfileProvider.Instance.Profile == null)
127-
{
128-
AzureRmProfileProvider.Instance.Profile = rmprofile;
129-
}
130-
131-
AzureSession.Instance.DataStore = datastore;
132106

133107
if (File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), Resources.AzureDirectoryName, "testcredentials.json")))
134108
{
@@ -150,8 +124,6 @@ public EnvironmentSetupHelper()
150124

151125
public string RMMonitorModule { get; private set; }
152126

153-
public string RMStorageDataPlaneModule { get; private set; }
154-
155127
public string RMNetworkModule { get; private set; }
156128

157129
public string StackRMProfileModule { get; private set; }
@@ -160,8 +132,6 @@ public EnvironmentSetupHelper()
160132

161133
public string StackRMStorageModule { get; private set; }
162134

163-
public string StackRMStorageDataPlaneModule { get; private set; }
164-
165135
public string RMKeyVaultModule { get; private set; }
166136

167137
private void LogIfNotNull(string message)
@@ -393,15 +363,19 @@ public void SetupAzureEnvironmentFromEnvironmentVariables(AzureModule mode)
393363
ResourceManagerUrl = currentEnvironment.Endpoints.ResourceManagementUri.AbsoluteUri,
394364
ServiceManagementUrl = currentEnvironment.Endpoints.ServiceManagementUri.AbsoluteUri,
395365
GalleryUrl = currentEnvironment.Endpoints.GalleryUri?.AbsoluteUri,
396-
AzureDataLakeAnalyticsCatalogAndJobEndpointSuffix = currentEnvironment.Endpoints.DataLakeAnalyticsJobAndCatalogServiceUri.OriginalString.Replace("https://", ""), // because it is just a sufix
397-
AzureDataLakeStoreFileSystemEndpointSuffix = currentEnvironment.Endpoints.DataLakeStoreServiceUri.OriginalString.Replace("https://", ""), // because it is just a sufix
366+
AzureDataLakeAnalyticsCatalogAndJobEndpointSuffix = currentEnvironment.Endpoints.DataLakeAnalyticsJobAndCatalogServiceUri.OriginalString.Replace("https://", ""),
367+
AzureDataLakeStoreFileSystemEndpointSuffix = currentEnvironment.Endpoints.DataLakeStoreServiceUri.OriginalString.Replace("https://", ""),
398368
StorageEndpointSuffix = AzureEnvironmentConstants.AzureStorageEndpointSuffix,
399369
AzureKeyVaultDnsSuffix = AzureEnvironmentConstants.AzureKeyVaultDnsSuffix,
400370
AzureKeyVaultServiceEndpointResourceId = AzureEnvironmentConstants.AzureKeyVaultServiceEndpointResourceId
401371
};
402372
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.MicrosoftGraphUrl, currentEnvironment.Endpoints.GraphUri.AbsoluteUri);
403-
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.OperationalInsightsEndpoint, "https://api.loganalytics.io/v1");
404-
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.OperationalInsightsEndpointResourceId, "https://api.loganalytics.io");
373+
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.AzureAttestationServiceEndpointSuffix, AzureEnvironmentConstants.AzureAttestationServiceEndpointSuffix);
374+
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.AzureAttestationServiceEndpointResourceId, AzureEnvironmentConstants.AzureAttestationServiceEndpointResourceId);
375+
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.AzureSynapseAnalyticsEndpointSuffix, AzureEnvironmentConstants.AzureSynapseAnalyticsEndpointSuffix);
376+
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.AzureSynapseAnalyticsEndpointResourceId, AzureEnvironmentConstants.AzureSynapseAnalyticsEndpointResourceId);
377+
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.OperationalInsightsEndpoint, AzureEnvironmentConstants.AzureOperationalInsightsEndpoint);
378+
testEnvironment.ExtendedProperties.SetProperty(AzureEnvironment.ExtendedEndpoint.OperationalInsightsEndpointResourceId, AzureEnvironmentConstants.AzureOperationalInsightsEndpointResourceId);
405379
if (!AzureRmProfileProvider.Instance.GetProfile<AzureRmProfile>().EnvironmentTable.ContainsKey(TestFxEnvironmentName))
406380
{
407381
AzureRmProfileProvider.Instance.GetProfile<AzureRmProfile>().EnvironmentTable[TestFxEnvironmentName] = testEnvironment;
@@ -441,12 +415,13 @@ public void SetupAzureEnvironmentFromEnvironmentVariables(AzureModule mode)
441415
testAccount.SetSubscriptions(currentEnvironment.SubscriptionId);
442416
testAccount.SetTenants(currentEnvironment.TenantId);
443417

418+
AzureRmProfileProvider.Instance.Profile = new AzureRmProfile(Path.Combine(AzureSession.Instance.ProfileDirectory, AzureSession.Instance.ProfileFile));
444419
AzureRmProfileProvider.Instance.Profile.DefaultContext = new AzureContext(testSubscription, testAccount, testEnvironment, testTenant);
445420
}
446421

447422
private void SetAuthenticationFactory(TestEnvironment environment)
448423
{
449-
if (environment.TokenInfo.ContainsKey(TokenAudience.Management))
424+
if (environment.IsRunningMocked)
450425
{
451426
var httpMessage = new HttpRequestMessage();
452427
environment.TokenInfo[TokenAudience.Management]

0 commit comments

Comments
 (0)
Please sign in to comment.