From 9e5f908a9998350b764ad271e890ee97ba561e56 Mon Sep 17 00:00:00 2001 From: Christopher Scott Date: Tue, 2 Feb 2021 15:02:36 -0600 Subject: [PATCH 1/2] Refactor TestEnvVar --- .../tests/DefaultAzureCredentialTests.cs | 52 ++++++------ .../tests/DeviceCodeCredentialTests.cs | 2 +- .../EnvironmentCredentialProviderTests.cs | 79 ++++++------------- .../ManagedIdentityCredentialLiveTestBase.cs | 26 +++--- .../tests/ManagedIdentityCredentialTests.cs | 30 +++---- .../Azure.Identity/tests/TestEnvVar.cs | 67 ++++++++++++++-- 6 files changed, 133 insertions(+), 123 deletions(-) diff --git a/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs b/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs index 1b2584d78c29..f0e892eef1a3 100644 --- a/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs @@ -38,7 +38,7 @@ public void ValidateCtorNoOptions() } [Test] - public void ValidateCtorIncludedInteractiveParam([Values(true, false)]bool includeInteractive) + public void ValidateCtorIncludedInteractiveParam([Values(true, false)] bool includeInteractive) { var cred = new DefaultAzureCredential(includeInteractive); @@ -110,7 +110,7 @@ public void ValidateCtorOptionsPassedToCredentials() [Test] [NonParallelizable] - public void ValidateEnvironmentBasedOptionsPassedToCredentials([Values]bool clientIdSpecified, [Values]bool usernameSpecified, [Values]bool tenantIdSpecified) + public void ValidateEnvironmentBasedOptionsPassedToCredentials([Values] bool clientIdSpecified, [Values] bool usernameSpecified, [Values] bool tenantIdSpecified) { var expClientId = clientIdSpecified ? Guid.NewGuid().ToString() : null; var expUsername = usernameSpecified ? Guid.NewGuid().ToString() : null; @@ -121,9 +121,11 @@ public void ValidateEnvironmentBasedOptionsPassedToCredentials([Values]bool clie bool onCreateVsCalled = false; bool onCreateVsCodeCalled = false; - using (new TestEnvVar("AZURE_CLIENT_ID", expClientId)) - using (new TestEnvVar("AZURE_USERNAME", expUsername)) - using (new TestEnvVar("AZURE_TENANT_ID", expTenantId)) + using (new TestEnvVar(new Dictionary + { + { "AZURE_CLIENT_ID", expClientId }, + { "AZURE_USERNAME", expUsername }, + { "AZURE_TENANT_ID", expTenantId } })) { var credFactory = new MockDefaultAzureCredentialFactory(CredentialPipeline.GetInstance(null)); @@ -191,9 +193,11 @@ public void ValidateEmptyEnvironmentBasedOptionsNotPassedToCredentials([Values] bool onCreateVsCalled = false; bool onCreateVsCodeCalled = false; - using (new TestEnvVar("AZURE_CLIENT_ID", expClientId)) - using (new TestEnvVar("AZURE_USERNAME", expUsername)) - using (new TestEnvVar("AZURE_TENANT_ID", expTenantId)) + using (new TestEnvVar(new Dictionary + { + { "AZURE_CLIENT_ID", expClientId }, + { "AZURE_USERNAME", expUsername }, + { "AZURE_TENANT_ID", expTenantId } })) { var credFactory = new MockDefaultAzureCredentialFactory(CredentialPipeline.GetInstance(null)); @@ -249,13 +253,13 @@ public void ValidateEmptyEnvironmentBasedOptionsNotPassedToCredentials([Values] } [Test] - public void ValidateCtorWithExcludeOptions([Values(true, false)]bool excludeEnvironmentCredential, - [Values(true, false)]bool excludeManagedIdentityCredential, - [Values(true, false)]bool excludeSharedTokenCacheCredential, - [Values(true, false)]bool excludeVisualStudioCredential, - [Values(true, false)]bool excludeVisualStudioCodeCredential, - [Values(true, false)]bool excludeCliCredential, - [Values(true, false)]bool excludeInteractiveBrowserCredential) + public void ValidateCtorWithExcludeOptions([Values(true, false)] bool excludeEnvironmentCredential, + [Values(true, false)] bool excludeManagedIdentityCredential, + [Values(true, false)] bool excludeSharedTokenCacheCredential, + [Values(true, false)] bool excludeVisualStudioCredential, + [Values(true, false)] bool excludeVisualStudioCodeCredential, + [Values(true, false)] bool excludeCliCredential, + [Values(true, false)] bool excludeInteractiveBrowserCredential) { var credFactory = new MockDefaultAzureCredentialFactory(CredentialPipeline.GetInstance(null)); @@ -311,13 +315,13 @@ public void ValidateCtorWithExcludeOptions([Values(true, false)]bool excludeEnvi } [Test] - public void ValidateAllUnavailable([Values(true, false)]bool excludeEnvironmentCredential, - [Values(true, false)]bool excludeManagedIdentityCredential, - [Values(true, false)]bool excludeSharedTokenCacheCredential, - [Values(true, false)]bool excludeVisualStudioCredential, - [Values(true, false)]bool excludeVisualStudioCodeCredential, - [Values(true, false)]bool excludeCliCredential, - [Values(true, false)]bool excludeInteractiveBrowserCredential) + public void ValidateAllUnavailable([Values(true, false)] bool excludeEnvironmentCredential, + [Values(true, false)] bool excludeManagedIdentityCredential, + [Values(true, false)] bool excludeSharedTokenCacheCredential, + [Values(true, false)] bool excludeVisualStudioCredential, + [Values(true, false)] bool excludeVisualStudioCodeCredential, + [Values(true, false)] bool excludeCliCredential, + [Values(true, false)] bool excludeInteractiveBrowserCredential) { if (excludeEnvironmentCredential && excludeManagedIdentityCredential && excludeSharedTokenCacheCredential && excludeVisualStudioCredential && excludeVisualStudioCodeCredential && excludeCliCredential && excludeInteractiveBrowserCredential) { @@ -401,7 +405,7 @@ public void ValidateAllUnavailable([Values(true, false)]bool excludeEnvironmentC } [Test] - public void ValidateUnhandledException([Values(0, 1, 2, 3, 4, 5, 6)]int exPossition) + public void ValidateUnhandledException([Values(0, 1, 2, 3, 4, 5, 6)] int exPossition) { var credFactory = new MockDefaultAzureCredentialFactory(CredentialPipeline.GetInstance(null)); @@ -541,7 +545,7 @@ public void ValidateUnhandledException([Values(0, 1, 2, 3, 4, 5, 6)]int exPossit } [Test] - public async Task ValidateSelectedCredentialCaching([Values(typeof(EnvironmentCredential), typeof(ManagedIdentityCredential), typeof(SharedTokenCacheCredential), typeof(VisualStudioCredential), typeof(VisualStudioCodeCredential), typeof(AzureCliCredential), typeof(InteractiveBrowserCredential))]Type availableCredential) + public async Task ValidateSelectedCredentialCaching([Values(typeof(EnvironmentCredential), typeof(ManagedIdentityCredential), typeof(SharedTokenCacheCredential), typeof(VisualStudioCredential), typeof(VisualStudioCodeCredential), typeof(AzureCliCredential), typeof(InteractiveBrowserCredential))] Type availableCredential) { var expToken = new AccessToken(Guid.NewGuid().ToString(), DateTimeOffset.MaxValue); diff --git a/sdk/identity/Azure.Identity/tests/DeviceCodeCredentialTests.cs b/sdk/identity/Azure.Identity/tests/DeviceCodeCredentialTests.cs index 3a85d9b1707d..fe4f4c4ce4c1 100644 --- a/sdk/identity/Azure.Identity/tests/DeviceCodeCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/DeviceCodeCredentialTests.cs @@ -162,7 +162,7 @@ public async Task AuthenticateWithDeviceCodeMockVerifyCallbackCancellationAsync( var options = new TokenCredentialOptions() { Transport = mockTransport }; - var cancelSource = new CancellationTokenSource(1000); + var cancelSource = new CancellationTokenSource(100); var cred = InstrumentClient(new DeviceCodeCredential(VerifyDeviceCodeCallbackCancellationToken, ClientId, options: options)); diff --git a/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs b/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs index d331cc74d998..070abbc5fe84 100644 --- a/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs +++ b/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs @@ -8,6 +8,7 @@ using Azure.Core.TestFramework; using Azure.Identity.Tests.Mock; using System.Threading.Tasks; +using System.Collections.Generic; namespace Azure.Identity.Tests { @@ -57,16 +58,12 @@ public void CredentialConstructionClientSecret() [Test] public void CredentialConstructionClientCertificate() { - string clientIdBackup = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); - string tenantIdBackup = Environment.GetEnvironmentVariable("AZURE_TENANT_ID"); - string clientCertificateLocationBackup = Environment.GetEnvironmentVariable("AZURE_CLIENT_CERTIFICATE_PATH"); - - try + using (new TestEnvVar(new Dictionary + { + {"AZURE_CLIENT_ID", "mockclientid"}, + {"AZURE_TENANT_ID", "mocktenantid"}, + {"AZURE_CLIENT_CERTIFICATE_PATH", "mockcertificatepath"}})) { - Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", "mockclientid"); - Environment.SetEnvironmentVariable("AZURE_TENANT_ID", "mocktenantid"); - Environment.SetEnvironmentVariable("AZURE_CLIENT_CERTIFICATE_PATH", "mockcertificatepath"); - var provider = new EnvironmentCredential(); var cred = provider.Credential as ClientCertificateCredential; Assert.NotNull(cred); @@ -78,12 +75,6 @@ public void CredentialConstructionClientCertificate() Assert.NotNull(certProvider); Assert.AreEqual("mockcertificatepath", certProvider.CertificatePath); } - finally - { - Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", clientIdBackup); - Environment.SetEnvironmentVariable("AZURE_TENANT_ID", tenantIdBackup); - Environment.SetEnvironmentVariable("AZURE_CLIENT_CERTIFICATE_PATH", clientCertificateLocationBackup); - } } [Test] @@ -113,52 +104,26 @@ public async Task EnvironmentCredentialAuthenticationFailedException() await Task.CompletedTask; } - [NonParallelizable] - [Test] - public void AssertCredentialUnavailableWhenEmptyString() + public static IEnumerable EnvironmentSettings() { - // ensure no env vars are set before starting the test - using (new TestEnvVar("AZURE_CLIENT_ID", null)) - using (new TestEnvVar("AZURE_TENANT_ID", null)) - using (new TestEnvVar("AZURE_CLIENT_SECRET", null)) - using (new TestEnvVar("AZURE_CLIENT_CERTIFICATE_PATH", null)) - using (new TestEnvVar("AZURE_USERNAME", null)) - using (new TestEnvVar("AZURE_PASSWORD", null)) - { - using (new TestEnvVar("AZURE_CLIENT_ID", "mockclientid")) - using (new TestEnvVar("AZURE_CLIENT_SECRET", "mockclientsecret")) - using (new TestEnvVar("AZURE_TENANT_ID", "mocktenantid")) - { - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_ID"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_SECRET"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_TENANT_ID"); - } - - using (new TestEnvVar("AZURE_CLIENT_ID", "mockclientid")) - using (new TestEnvVar("AZURE_CLIENT_CERTIFICATE_PATH", "mockcertpath")) - using (new TestEnvVar("AZURE_TENANT_ID", "mocktenantid")) - { - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_ID"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_CERTIFICATE_PATH"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_TENANT_ID"); - } - - using (new TestEnvVar("AZURE_USERNAME", "mockusername")) - using (new TestEnvVar("AZURE_PASSWORD", "mockpassword")) - using (new TestEnvVar("AZURE_TENANT_ID", "mocktenantid")) - using (new TestEnvVar("AZURE_CLIENT_ID", "mockclientid")) - { - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_ID"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_TENANT_ID"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_USERNAME"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_PASSWORD"); - } - } + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", string.Empty }, { "AZURE_CLIENT_SECRET", "mockclientsecret" }, { "AZURE_TENANT_ID", "mocktenantid" } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_SECRET", string.Empty }, { "AZURE_TENANT_ID", "mocktenantid" } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_SECRET", "mockclientsecret" }, { "AZURE_TENANT_ID", string.Empty } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", string.Empty }, { "AZURE_CLIENT_CERTIFICATE_PATH", "mockcertpath" }, { "AZURE_TENANT_ID", "mocktenantid" } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_CERTIFICATE_PATH", string.Empty }, { "AZURE_TENANT_ID", "mocktenantid" } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_CERTIFICATE_PATH", "mockcertpath" }, { "AZURE_TENANT_ID", string.Empty } } }; + yield return new object[] { new Dictionary { { "AZURE_USERNAME", string.Empty }, { "AZURE_PASSWORD", "mockpassword" }, { "AZURE_TENANT_ID", "mocktenantid" }, { "AZURE_CLIENT_ID", "mockclientid" } } }; + yield return new object[] { new Dictionary { { "AZURE_USERNAME", "mockusername" }, { "AZURE_PASSWORD", string.Empty }, { "AZURE_TENANT_ID", "mocktenantid" }, { "AZURE_CLIENT_ID", "mockclientid" } } }; + yield return new object[] { new Dictionary { { "AZURE_USERNAME", "mockusername" }, { "AZURE_PASSWORD", "mockpassword" }, { "AZURE_TENANT_ID", string.Empty }, { "AZURE_CLIENT_ID", "mockclientid" } } }; + yield return new object[] { new Dictionary { { "AZURE_USERNAME", "mockusername" }, { "AZURE_PASSWORD", "mockpassword" }, { "AZURE_TENANT_ID", "mocktenantid" }, { "AZURE_CLIENT_ID", string.Empty } } }; } - private void SetEnvVarToEmptyStringAndAssertCredentialUnavailable(string envVar) + [NonParallelizable] + [Test] + [TestCaseSource(nameof(EnvironmentSettings))] + public void AssertCredentialUnavailableWhenEmptyString(Dictionary environmentVars) { - using (new TestEnvVar(envVar, string.Empty)) + using (new TestEnvVar(environmentVars)) { var credential = InstrumentClient(new EnvironmentCredential()); diff --git a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialLiveTestBase.cs b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialLiveTestBase.cs index a181ca02065f..a8febc374389 100644 --- a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialLiveTestBase.cs +++ b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialLiveTestBase.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.Reflection; using Azure.Core.TestFramework; using Azure.Security.KeyVault.Secrets; @@ -38,27 +39,24 @@ public void ClearChallengeCacheforRecord() private class ManagedIdenityEnvironment : IDisposable { - private readonly TestEnvVar[] _envVars; + private readonly TestEnvVar _envVar; public ManagedIdenityEnvironment(IdentityTestEnvironment env) { - _envVars = new TestEnvVar[] - { - new TestEnvVar("IDENTITY_ENDPOINT", env.IdentityEndpoint), - new TestEnvVar("IMDS_ENDPOINT", env.ImdsEndpoint), - new TestEnvVar("MSI_ENDPOINT", env.MsiEndpoint), - new TestEnvVar("MSI_SECRET", env.MsiSecret), - new TestEnvVar("IDENTITY_HEADER", env.IdentityHeader), - new TestEnvVar("IDENTITY_SERVER_THUMBPRINT", env.IdentityServerThumbprint) - }; + _envVar = + new TestEnvVar( + new Dictionary + { + { "IDENTITY_ENDPOINT", env.IdentityEndpoint }, + { "IMDS_ENDPOINT", env.ImdsEndpoint }, + { "MSI_ENDPOINT", env.MsiEndpoint }, + { "MSI_SECRET", env.MsiSecret },{ "IDENTITY_HEADER", env.IdentityHeader }, + { "IDENTITY_SERVER_THUMBPRINT", env.IdentityServerThumbprint } }); } public void Dispose() { - foreach (TestEnvVar envVar in _envVars) - { - envVar.Dispose(); - } + _envVar.Dispose(); } } } diff --git a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs index 7c7ea52232fd..de5dab17c24f 100644 --- a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; @@ -24,8 +25,7 @@ public ManagedIdentityCredentialTests(bool isAsync) : base(isAsync) [Test] public async Task VerifyImdsRequestMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", null)) - using (new TestEnvVar("MSI_SECRET", null)) + using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -65,8 +65,7 @@ public async Task VerifyImdsRequestMockAsync() [Test] public async Task VerifyImdsRequestWithClientIdMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", null)) - using (new TestEnvVar("MSI_SECRET", null)) + using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -108,8 +107,7 @@ public async Task VerifyImdsRequestWithClientIdMockAsync() [Test] public async Task VerifyAppService2017RequestMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", "mock-msi-secret")) + using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -147,8 +145,7 @@ public async Task VerifyAppService2017RequestMockAsync() [Test] public async Task VerifyAppService2017RequestWithClientIdMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", "mock-msi-secret")) + using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -189,8 +186,7 @@ public async Task VerifyAppService2017RequestWithClientIdMockAsync() [Test] public async Task VerifyAppService2019RequestMockAsync() { - using (new TestEnvVar("IDENTITY_ENDPOINT", "https://identity.endpoint/")) - using (new TestEnvVar("IDENTITY_HEADER", "mock-identity-header")) + using (new TestEnvVar(new Dictionary { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" } })) { var expectedToken = "mock-access-token"; var response = new MockResponse(200); @@ -222,10 +218,7 @@ public async Task VerifyAppService2019RequestMockAsync() // The test should be removed if and when support for this api version is added back public async Task VerifyAppService2017RequestWith2019EnvVarsMockAsync() { - using (new TestEnvVar("IDENTITY_ENDPOINT", "https://identity.endpoint/")) - using (new TestEnvVar("IDENTITY_HEADER", "mock-identity-header")) - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", "mock-msi-secret")) + using (new TestEnvVar(new Dictionary { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" }, { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -264,8 +257,7 @@ public async Task VerifyAppService2017RequestWith2019EnvVarsMockAsync() [Test] public async Task VerifyAppService2019RequestWithClientIdMockAsync() { - using (new TestEnvVar("IDENTITY_ENDPOINT", "https://identity.endpoint/")) - using (new TestEnvVar("IDENTITY_HEADER", "mock-identity-header")) + using (new TestEnvVar(new Dictionary { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" } })) { var expectedToken = "mock-access-token"; var response = new MockResponse(200); @@ -296,8 +288,7 @@ public async Task VerifyAppService2019RequestWithClientIdMockAsync() [Test] public async Task VerifyCloudShellMsiRequestMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", null)) + using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -341,8 +332,7 @@ public async Task VerifyCloudShellMsiRequestMockAsync() [Test] public async Task VerifyCloudShellMsiRequestWithClientIdMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", null)) + using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); diff --git a/sdk/identity/Azure.Identity/tests/TestEnvVar.cs b/sdk/identity/Azure.Identity/tests/TestEnvVar.cs index fdf94b32ac2a..3144ab8c12a8 100644 --- a/sdk/identity/Azure.Identity/tests/TestEnvVar.cs +++ b/sdk/identity/Azure.Identity/tests/TestEnvVar.cs @@ -2,29 +2,82 @@ // Licensed under the MIT License. using System; -using System.Collections; using System.Collections.Generic; -using System.Text; +using System.Threading; namespace Azure.Identity.Tests { internal class TestEnvVar : IDisposable { - private readonly string _origValue = null; - private readonly string _name; + private static SemaphoreSlim _lock = new SemaphoreSlim(1, 1); + private readonly Dictionary _originalValues = new Dictionary() + { + { "AZURE_USERNAME", EnvironmentVariables.Username}, + { "AZURE_PASSWORD", EnvironmentVariables.Password}, + { "AZURE_TENANT_ID", EnvironmentVariables.TenantId}, + { "AZURE_CLIENT_ID", EnvironmentVariables.ClientId}, + { "AZURE_CLIENT_SECRET", EnvironmentVariables.ClientSecret}, + { "AZURE_CLIENT_CERTIFICATE_PATH", EnvironmentVariables.ClientCertificatePath}, + { "IDENTITY_ENDPOINT", EnvironmentVariables.IdentityEndpoint}, + { "IDENTITY_HEADER", EnvironmentVariables.IdentityHeader}, + { "MSI_ENDPOINT", EnvironmentVariables.MsiEndpoint}, + { "MSI_SECRET", EnvironmentVariables.MsiSecret}, + { "IMDS_ENDPOINT", EnvironmentVariables.ImdsEndpoint}, + { "IDENTITY_SERVER_THUMBPRINT", EnvironmentVariables.IdentityServerThumbprint}, + }; public TestEnvVar(string name, string value) { - _name = name; + var acquired = _lock.Wait(TimeSpan.Zero); + if (!acquired) + { + throw new Exception($"Concurrent use of {nameof(TestEnvVar)}. Consider marking these tests as NonParallelizable."); + } + + _originalValues[name] = Environment.GetEnvironmentVariable(name); - _origValue = Environment.GetEnvironmentVariable(name); + CleanExistingEnvironmentVariables(); Environment.SetEnvironmentVariable(name, value); } + // clear the existing values so that the test needs only set up the values relevant to it. + private void CleanExistingEnvironmentVariables() + { + foreach (var kvp in _originalValues) + { + Environment.SetEnvironmentVariable(kvp.Key, null); + } + } + + public TestEnvVar(Dictionary environmentVariables) + { + var acquired = _lock.Wait(TimeSpan.Zero); + if (!acquired) + { + throw new Exception($"Concurrent use of {nameof(TestEnvVar)}. Consider marking these tests as NonParallelizable."); + } + + foreach (var kvp in environmentVariables) + { + _originalValues[kvp.Key] = kvp.Value; + } + + CleanExistingEnvironmentVariables(); + + foreach (var kvp in environmentVariables) + { + Environment.SetEnvironmentVariable(kvp.Key, kvp.Value); + } + } + public void Dispose() { - Environment.SetEnvironmentVariable(_name, _origValue); + foreach (var kvp in _originalValues) + { + Environment.SetEnvironmentVariable(kvp.Key, kvp.Value); + } + _lock.Release(); } } } From a94d2c8ac707e5d19a18014b18560f1742210465 Mon Sep 17 00:00:00 2001 From: Christopher Scott Date: Tue, 2 Feb 2021 16:06:32 -0600 Subject: [PATCH 2/2] pr comments --- .../tests/DefaultAzureCredentialTests.cs | 4 ++-- .../EnvironmentCredentialProviderTests.cs | 13 +++++++------ .../tests/ManagedIdentityCredentialTests.cs | 18 +++++++++--------- .../Azure.Identity/tests/TestEnvVar.cs | 18 +++++++++--------- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs b/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs index f0e892eef1a3..7e437c68ea56 100644 --- a/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs @@ -121,7 +121,7 @@ public void ValidateEnvironmentBasedOptionsPassedToCredentials([Values] bool cli bool onCreateVsCalled = false; bool onCreateVsCodeCalled = false; - using (new TestEnvVar(new Dictionary + using (new TestEnvVar(new () { { "AZURE_CLIENT_ID", expClientId }, { "AZURE_USERNAME", expUsername }, @@ -193,7 +193,7 @@ public void ValidateEmptyEnvironmentBasedOptionsNotPassedToCredentials([Values] bool onCreateVsCalled = false; bool onCreateVsCodeCalled = false; - using (new TestEnvVar(new Dictionary + using (new TestEnvVar(new () { { "AZURE_CLIENT_ID", expClientId }, { "AZURE_USERNAME", expUsername }, diff --git a/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs b/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs index 070abbc5fe84..d156426acf82 100644 --- a/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs +++ b/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs @@ -58,11 +58,12 @@ public void CredentialConstructionClientSecret() [Test] public void CredentialConstructionClientCertificate() { - using (new TestEnvVar(new Dictionary + using (new TestEnvVar(new () { - {"AZURE_CLIENT_ID", "mockclientid"}, - {"AZURE_TENANT_ID", "mocktenantid"}, - {"AZURE_CLIENT_CERTIFICATE_PATH", "mockcertificatepath"}})) + { "AZURE_CLIENT_ID", "mockclientid" }, + { "AZURE_TENANT_ID", "mocktenantid" }, + { "AZURE_CLIENT_CERTIFICATE_PATH", "mockcertificatepath" } + })) { var provider = new EnvironmentCredential(); var cred = provider.Credential as ClientCertificateCredential; @@ -104,7 +105,7 @@ public async Task EnvironmentCredentialAuthenticationFailedException() await Task.CompletedTask; } - public static IEnumerable EnvironmentSettings() + public static IEnumerable AssertCredentialUnavailableWhenEmptyStringEnvironmentSettings() { yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", string.Empty }, { "AZURE_CLIENT_SECRET", "mockclientsecret" }, { "AZURE_TENANT_ID", "mocktenantid" } } }; yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_SECRET", string.Empty }, { "AZURE_TENANT_ID", "mocktenantid" } } }; @@ -120,7 +121,7 @@ public static IEnumerable EnvironmentSettings() [NonParallelizable] [Test] - [TestCaseSource(nameof(EnvironmentSettings))] + [TestCaseSource(nameof(AssertCredentialUnavailableWhenEmptyStringEnvironmentSettings))] public void AssertCredentialUnavailableWhenEmptyString(Dictionary environmentVars) { using (new TestEnvVar(environmentVars)) diff --git a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs index de5dab17c24f..c7301c5840ba 100644 --- a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs @@ -25,7 +25,7 @@ public ManagedIdentityCredentialTests(bool isAsync) : base(isAsync) [Test] public async Task VerifyImdsRequestMockAsync() { - using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null } })) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -65,7 +65,7 @@ public async Task VerifyImdsRequestMockAsync() [Test] public async Task VerifyImdsRequestWithClientIdMockAsync() { - using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null } })) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -107,7 +107,7 @@ public async Task VerifyImdsRequestWithClientIdMockAsync() [Test] public async Task VerifyAppService2017RequestMockAsync() { - using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -145,7 +145,7 @@ public async Task VerifyAppService2017RequestMockAsync() [Test] public async Task VerifyAppService2017RequestWithClientIdMockAsync() { - using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -186,7 +186,7 @@ public async Task VerifyAppService2017RequestWithClientIdMockAsync() [Test] public async Task VerifyAppService2019RequestMockAsync() { - using (new TestEnvVar(new Dictionary { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" } })) + using (new TestEnvVar(new () { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" } })) { var expectedToken = "mock-access-token"; var response = new MockResponse(200); @@ -218,7 +218,7 @@ public async Task VerifyAppService2019RequestMockAsync() // The test should be removed if and when support for this api version is added back public async Task VerifyAppService2017RequestWith2019EnvVarsMockAsync() { - using (new TestEnvVar(new Dictionary { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" }, { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) + using (new TestEnvVar(new () { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" }, { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -257,7 +257,7 @@ public async Task VerifyAppService2017RequestWith2019EnvVarsMockAsync() [Test] public async Task VerifyAppService2019RequestWithClientIdMockAsync() { - using (new TestEnvVar(new Dictionary { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" } })) + using (new TestEnvVar(new () { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" } })) { var expectedToken = "mock-access-token"; var response = new MockResponse(200); @@ -288,7 +288,7 @@ public async Task VerifyAppService2019RequestWithClientIdMockAsync() [Test] public async Task VerifyCloudShellMsiRequestMockAsync() { - using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", null } })) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -332,7 +332,7 @@ public async Task VerifyCloudShellMsiRequestMockAsync() [Test] public async Task VerifyCloudShellMsiRequestWithClientIdMockAsync() { - using (new TestEnvVar(new Dictionary { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", null } })) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); diff --git a/sdk/identity/Azure.Identity/tests/TestEnvVar.cs b/sdk/identity/Azure.Identity/tests/TestEnvVar.cs index 3144ab8c12a8..4a60f49c315b 100644 --- a/sdk/identity/Azure.Identity/tests/TestEnvVar.cs +++ b/sdk/identity/Azure.Identity/tests/TestEnvVar.cs @@ -41,15 +41,6 @@ public TestEnvVar(string name, string value) Environment.SetEnvironmentVariable(name, value); } - // clear the existing values so that the test needs only set up the values relevant to it. - private void CleanExistingEnvironmentVariables() - { - foreach (var kvp in _originalValues) - { - Environment.SetEnvironmentVariable(kvp.Key, null); - } - } - public TestEnvVar(Dictionary environmentVariables) { var acquired = _lock.Wait(TimeSpan.Zero); @@ -79,5 +70,14 @@ public void Dispose() } _lock.Release(); } + + // clear the existing values so that the test needs only set up the values relevant to it. + private void CleanExistingEnvironmentVariables() + { + foreach (var kvp in _originalValues) + { + Environment.SetEnvironmentVariable(kvp.Key, null); + } + } } }