diff --git a/src/client/Microsoft.Identity.Lab.Api/Helpers/AppAccessorWithPartitionAsserts.cs b/src/client/Microsoft.Identity.Lab.Api/Helpers/AppAccessorWithPartitionAsserts.cs new file mode 100644 index 0000000000..86b094f253 --- /dev/null +++ b/src/client/Microsoft.Identity.Lab.Api/Helpers/AppAccessorWithPartitionAsserts.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Microsoft.Identity.Client; +using Microsoft.Identity.Client.Cache.Items; +using Microsoft.Identity.Client.Core; +using Microsoft.Identity.Client.PlatformsCommon.Shared; +using Microsoft.Identity.Lab.Api.Helpers; + +namespace Microsoft.Identity.Lab.Api.Helpers +{ + internal class AppAccessorWithPartitionAsserts : InMemoryPartitionedAppTokenCacheAccessor + { + public AppAccessorWithPartitionAsserts( + ILoggerAdapter logger, + CacheOptions tokenCacheAccessorOptions) : base(logger, tokenCacheAccessorOptions) + { + + } + + public override List GetAllAccessTokens(string partitionKey = null, ILoggerAdapter requestlogger = null) + { + Assert.IsNotNull(partitionKey); + return base.GetAllAccessTokens(partitionKey, requestlogger); + } + + public override List GetAllAccounts(string partitionKey = null, ILoggerAdapter requestlogger = null) + { + Assert.IsNotNull(partitionKey); + Assert.Fail("App token cache - do not call GetAllAccounts"); + throw new InvalidOperationException(); + } + + public override List GetAllIdTokens(string partitionKey = null, ILoggerAdapter requestlogger = null) + { + Assert.IsNotNull(partitionKey); + + Assert.Fail("App token cache - do not call GetAllIdTokens"); + throw new InvalidOperationException(); + } + + public override List GetAllRefreshTokens(string partitionKey = null, ILoggerAdapter requestlogger = null) + { + Assert.IsNotNull(partitionKey); + + Assert.Fail("App token cache - do not call GetAllRefreshTokens"); + throw new InvalidOperationException(); + } + + public override bool HasAccessOrRefreshTokens() + { + Assert.Fail("HasAccessOrRefreshTokens was called. It should not be called unless the token cache serialization hooks"); + throw new InvalidOperationException(); + } + } +} diff --git a/src/client/Microsoft.Identity.Lab.Api/Helpers/Assert.cs b/src/client/Microsoft.Identity.Lab.Api/Helpers/Assert.cs new file mode 100644 index 0000000000..5fd0898eb6 --- /dev/null +++ b/src/client/Microsoft.Identity.Lab.Api/Helpers/Assert.cs @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Identity.Lab.Api.Helpers +{ + /// + /// Lightweight assertion helper that throws + /// instead of depending on MSTest. Intended for use in mock infrastructure only. + /// + internal static class Assert + { + public static void AreEqual(T expected, T actual, string message = null) + { + if (!EqualityComparer.Default.Equals(expected, actual)) + { + throw new InvalidOperationException( + message ?? $"Assert.AreEqual failed. Expected: <{expected}>. Actual: <{actual}>."); + } + } + + public static void IsTrue(bool condition, string message = null) + { + if (!condition) + { + throw new InvalidOperationException( + message ?? "Assert.IsTrue failed."); + } + } + + public static void IsFalse(bool condition, string message = null) + { + if (condition) + { + throw new InvalidOperationException( + message ?? "Assert.IsFalse failed."); + } + } + + public static void IsNotNull(object value, string message = null) + { + if (value == null) + { + throw new InvalidOperationException( + message ?? "Assert.IsNotNull failed."); + } + } + + public static void IsEmpty(ICollection collection, string message = null) + { + if (collection != null && collection.Count > 0) + { + throw new InvalidOperationException( + message ?? $"Assert.IsEmpty failed. Collection has {collection.Count} element(s)."); + } + } + + public static void IsEmpty(IEnumerable collection, string message = null) + { + if (collection != null && collection.Any()) + { + throw new InvalidOperationException( + message ?? "Assert.IsEmpty failed. Collection is not empty."); + } + } + + public static void HasCount(int expectedCount, ICollection collection, string message = null) + { + int actual = collection?.Count ?? 0; + if (actual != expectedCount) + { + throw new InvalidOperationException( + message ?? $"Assert.HasCount failed. Expected: {expectedCount}. Actual: {actual}."); + } + } + + public static void Contains(T item, ICollection collection, string message = null) + { + if (collection == null || !collection.Contains(item)) + { + throw new InvalidOperationException( + message ?? $"Assert.Contains failed. Item <{item}> not found in collection."); + } + } + + public static void Fail(string message) + { + throw new InvalidOperationException(message ?? "Assert.Fail was called."); + } + } +} diff --git a/src/client/Microsoft.Identity.Lab.Api/Helpers/CoreAssert.cs b/src/client/Microsoft.Identity.Lab.Api/Helpers/CoreAssert.cs new file mode 100644 index 0000000000..bc4e7d5cc9 --- /dev/null +++ b/src/client/Microsoft.Identity.Lab.Api/Helpers/CoreAssert.cs @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Identity.Client; +using Microsoft.Identity.Client.Utils; +using Microsoft.Identity.Lab.Api.Helpers; + +namespace Microsoft.Identity.Lab.Api.Helpers +{ + /// + /// Provides custom assertion helpers for MSAL.NET test scenarios. + /// + internal static class CoreAssert + { + /// + /// Asserts that two scope strings represent the same set of scopes. + /// + public static void AreScopesEqual(string scopesExpected, string scopesActual) + { + var expectedScopes = ScopeHelper.ConvertStringToScopeSet(scopesExpected); + var actualScopes = ScopeHelper.ConvertStringToScopeSet(scopesActual); + + Assert.HasCount(expectedScopes.Count, actualScopes); + foreach (string expectedScope in expectedScopes) + { + Assert.Contains(expectedScope, actualScopes); + } + } + + internal static void AreAccountsEqual( + string expectedUsername, + string expectedEnv, + string expectedId, + string expectedTid, + string expectedOid, + params IAccount[] accounts) + { + foreach (var account in accounts) + { + Assert.AreEqual(expectedUsername, account.Username); + Assert.AreEqual(expectedEnv, account.Environment); + Assert.AreEqual(expectedId, account.HomeAccountId.Identifier); + Assert.AreEqual(expectedTid, account.HomeAccountId.TenantId); + Assert.AreEqual(expectedOid, account.HomeAccountId.ObjectId); + } + } + + /// + /// Asserts that three values are all equal to each other. + /// + public static void AreEqual(T val1, T val2, T val3) + { + Assert.AreEqual(val1, val2, "First and second values differ"); + Assert.AreEqual(val1, val3, "First and third values differ"); + } + + /// + /// Asserts that two values are within one second of each other. + /// + public static void AreWithinOneSecond(DateTimeOffset expected, DateTimeOffset actual, string message = "") + { + IsWithinRange(expected, actual, TimeSpan.FromSeconds(1), message); + } + + /// + /// Asserts that two values are within a specified range of each other. + /// + public static void IsWithinRange(DateTimeOffset expected, DateTimeOffset actual, TimeSpan range, string message = "") + { + TimeSpan t = expected - actual; + Assert.IsTrue(t >= -range && t <= range, + $"{message} The dates are off by {t.TotalMilliseconds}ms, which is more than the expected {range.TotalMilliseconds}ms"); + } + + /// + /// Asserts that two dictionaries are equal. + /// + public static void AssertDictionariesAreEqual( + IDictionary dict1, + IDictionary dict2, + IEqualityComparer valueComparer) + { + Assert.IsTrue(DictionariesAreEqual(dict1, dict2, valueComparer)); + } + + /// + /// Asserts that the specified type is immutable. + /// + public static void IsImmutable() + { + Assert.IsTrue(IsImmutable(typeof(T))); + } + + private static bool IsImmutable(Type type) + { + if (type == typeof(string) || type.IsPrimitive || type.IsEnum) + { + return true; + } + + #pragma warning disable IL2070, IL2067 + var fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + #pragma warning restore IL2070, IL2067 + var isShallowImmutable = fieldInfos.All(f => f.IsInitOnly); + + if (!isShallowImmutable) + { + return false; + } + + return fieldInfos.All(f => IsImmutable(f.FieldType)); + } + + private static bool DictionariesAreEqual( + IDictionary dict1, + IDictionary dict2, + IEqualityComparer valueComparer) + { + if (dict1 == dict2) + return true; + if ((dict1 == null) || (dict2 == null)) + return false; + if (dict1.Count != dict2.Count) + return false; + + foreach (var kvp in dict1) + { + if (!dict2.TryGetValue(kvp.Key, out TValue value2)) + return false; + if (!valueComparer.Equals(kvp.Value, value2)) + return false; + } + return true; + } + } +} diff --git a/src/client/Microsoft.Identity.Lab.Api/Helpers/ManagedIdentityTestUtil.cs b/src/client/Microsoft.Identity.Lab.Api/Helpers/ManagedIdentityTestUtil.cs new file mode 100644 index 0000000000..5f151d294c --- /dev/null +++ b/src/client/Microsoft.Identity.Lab.Api/Helpers/ManagedIdentityTestUtil.cs @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Identity.Client; +using Microsoft.Identity.Client.AppConfig; +using Microsoft.Identity.Client.ManagedIdentity; + +namespace Microsoft.Identity.Test.Common.Core.Helpers +{ + /// + /// ManagedIdentityTestUtil provides utility methods for setting up and managing environment variables + /// related to managed identities in test scenarios. + /// + public static class ManagedIdentityTestUtil + { + /// + /// User assigned identity identifier types for testing. + /// + public enum UserAssignedIdentityId + { + /// No user-assigned identity. + None, + /// Identified by client ID. + ClientId, + /// Identified by resource ID. + ResourceId, + /// Identified by object ID. + ObjectId + } + + /// + /// MSI Azure resource types for testing. + /// + public enum MsiAzureResource + { + /// Azure Web App. + WebApp, + /// Azure Function. + Function, + /// Azure Virtual Machine. + VM, + /// Azure Arc. + AzureArc, + /// Azure Cloud Shell. + CloudShell, + /// Azure Service Fabric. + ServiceFabric + } + + /// + /// Sets environment variables for the specified managed identity source. + /// + public static void SetEnvironmentVariables(ManagedIdentitySource managedIdentitySource, string endpoint, string secret = "secret", string thumbprint = "thumbprint") + { + switch (managedIdentitySource) + { + case ManagedIdentitySource.AppService: + Environment.SetEnvironmentVariable("IDENTITY_ENDPOINT", endpoint); + Environment.SetEnvironmentVariable("IDENTITY_HEADER", secret); + break; + + case ManagedIdentitySource.Imds: + case ManagedIdentitySource.ImdsV2: + Environment.SetEnvironmentVariable("AZURE_POD_IDENTITY_AUTHORITY_HOST", endpoint); + break; + + case ManagedIdentitySource.AzureArc: + Environment.SetEnvironmentVariable("IDENTITY_ENDPOINT", endpoint); + Environment.SetEnvironmentVariable("IMDS_ENDPOINT", "http://localhost:40342"); + break; + + case ManagedIdentitySource.CloudShell: + Environment.SetEnvironmentVariable("MSI_ENDPOINT", endpoint); + break; + + case ManagedIdentitySource.ServiceFabric: + Environment.SetEnvironmentVariable("IDENTITY_ENDPOINT", endpoint); + Environment.SetEnvironmentVariable("IDENTITY_HEADER", secret); + Environment.SetEnvironmentVariable("IDENTITY_SERVER_THUMBPRINT", thumbprint); + break; + + case ManagedIdentitySource.MachineLearning: + Environment.SetEnvironmentVariable("MSI_ENDPOINT", endpoint); + Environment.SetEnvironmentVariable("MSI_SECRET", secret); + Environment.SetEnvironmentVariable("DEFAULT_IDENTITY_CLIENT_ID", "fake_DEFAULT_IDENTITY_CLIENT_ID"); + break; + + default: + throw new NotImplementedException($"Setting environment variables for {managedIdentitySource} is not implemented."); + } + } + + /// + /// Sets environment variables for testing upgrade scenarios. + /// + internal static void SetUpgradeScenarioEnvironmentVariables(ManagedIdentitySource managedIdentitySource, string endpoint, string secret = "secret", string thumbprint = "thumbprint") + { + SetEnvironmentVariables(managedIdentitySource, endpoint, secret, thumbprint); + + switch (managedIdentitySource) + { + case ManagedIdentitySource.AppService: + Environment.SetEnvironmentVariable("MSI_ENDPOINT", endpoint); + Environment.SetEnvironmentVariable("MSI_SECRET", secret); + break; + } + } + + /// + /// Create the MIA with the http proxy + /// + public static ManagedIdentityApplicationBuilder CreateMIABuilder(string userAssignedId = "", UserAssignedIdentityId userAssignedIdentityId = UserAssignedIdentityId.ClientId) + { + var builder = ManagedIdentityApplicationBuilder.Create(ManagedIdentityId.WithUserAssignedClientId(userAssignedId)); + + switch (userAssignedIdentityId) + { + case UserAssignedIdentityId.ResourceId: + builder = ManagedIdentityApplicationBuilder.Create(ManagedIdentityId.WithUserAssignedResourceId(userAssignedId)); + break; + + case UserAssignedIdentityId.ObjectId: + builder = ManagedIdentityApplicationBuilder.Create(ManagedIdentityId.WithUserAssignedObjectId(userAssignedId)); + break; + } + + builder.Config.AccessorOptions = null; + + return builder; + } + } +} diff --git a/src/client/Microsoft.Identity.Lab.Api/Helpers/TestCommon.cs b/src/client/Microsoft.Identity.Lab.Api/Helpers/TestCommon.cs new file mode 100644 index 0000000000..068a4fc182 --- /dev/null +++ b/src/client/Microsoft.Identity.Lab.Api/Helpers/TestCommon.cs @@ -0,0 +1,189 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using Microsoft.Identity.Client; +using Microsoft.Identity.Client.ApiConfig.Parameters; +using Microsoft.Identity.Client.AppConfig; +using Microsoft.Identity.Client.Cache; +using Microsoft.Identity.Client.Cache.Items; +using Microsoft.Identity.Client.Http; +using Microsoft.Identity.Client.Http.Retry; +using Microsoft.Identity.Client.Instance; +using Microsoft.Identity.Client.Internal; +using Microsoft.Identity.Client.Internal.Requests; +using Microsoft.Identity.Client.PlatformsCommon.Factories; +using Microsoft.Identity.Client.PlatformsCommon.Interfaces; +using Microsoft.Identity.Lab.Api.Helpers; +using static Microsoft.Identity.Client.TelemetryCore.Internal.Events.ApiEvent; + +namespace Microsoft.Identity.Lab.Api.Helpers +{ + internal static class TestCommon + { + internal const string OnPremiseAuthority = "https://fs.contoso.com/adfs/"; + internal const string B2CSignUpSignIn = "b2c_1_susi"; + internal const string B2CAuthority = "https://login.microsoftonline.in/tfp/tenant/" + B2CSignUpSignIn + "/"; + internal const string ClientId = "d3adb33f-c0de-ed0c-c0de-deadb33fc0d3"; + internal const string ProductionPrefNetworkEnvironment = "login.microsoftonline.com"; + internal const string Utid = "my-utid"; + internal const string AuthorityTestTenant = "https://" + ProductionPrefNetworkEnvironment + "/" + Utid + "/"; + + internal static HashSet s_scope + { + get + { + return new HashSet(new[] { "r1/scope1", "r1/scope2" }, StringComparer.OrdinalIgnoreCase); + } + } + + public static IServiceBundle CreateServiceBundleWithCustomHttpManager( + IHttpManager httpManager, + LogCallback logCallback = null, + string authority = ClientApplicationBase.DefaultAuthority, + bool isExtendedTokenLifetimeEnabled = false, + bool enablePiiLogging = false, + string clientId = ClientId, + bool clearCaches = true, + bool validateAuthority = true, + bool isLegacyCacheEnabled = true, + bool isMultiCloudSupportEnabled = false, + MsalClientType applicationType = MsalClientType.PublicClient, + bool isInstanceDiscoveryEnabled = true, + IPlatformProxy platformProxy = null) + { + var appConfig = new ApplicationConfiguration(applicationType) + { + ClientId = clientId, + HttpManager = httpManager, + RedirectUri = PlatformProxyFactory.CreatePlatformProxy(null).GetDefaultRedirectUri(clientId), + LoggingCallback = logCallback, + LogLevel = LogLevel.Verbose, + EnablePiiLogging = enablePiiLogging, + IsExtendedTokenLifetimeEnabled = isExtendedTokenLifetimeEnabled, + Authority = Authority.CreateAuthority(authority, validateAuthority), + LegacyCacheCompatibilityEnabled = isLegacyCacheEnabled, + MultiCloudSupportEnabled = isMultiCloudSupportEnabled, + IsInstanceDiscoveryEnabled = isInstanceDiscoveryEnabled, + PlatformProxy = platformProxy, + RetryPolicyFactory = new RetryPolicyFactory() + }; + + if (clearCaches) + ApplicationBase.ResetStateForTest(); + + return new ServiceBundle(appConfig); + } + + public static IServiceBundle CreateDefaultServiceBundle() + { + return CreateServiceBundleWithCustomHttpManager(null); + } + + public static IServiceBundle CreateDefaultAdfsServiceBundle() + { + return CreateServiceBundleWithCustomHttpManager(null, authority: OnPremiseAuthority); + } + + public static IServiceBundle CreateDefaultB2CServiceBundle() + { + return CreateServiceBundleWithCustomHttpManager(null, authority: B2CAuthority); + } + + public static AuthenticationRequestParameters CreateAuthenticationRequestParameters( + IServiceBundle serviceBundle, + Authority authority = null, + HashSet scopes = null, + RequestContext requestContext = null, + ApiIds apiID = ApiIds.None) + { + var commonParameters = new AcquireTokenCommonParameters + { + Scopes = scopes ?? s_scope, + ApiId = apiID + }; + + authority ??= Authority.CreateAuthority(TestCommon.AuthorityTestTenant); + requestContext ??= new RequestContext(serviceBundle, Guid.NewGuid(), commonParameters.MtlsCertificate) + { + ApiEvent = new Client.TelemetryCore.Internal.Events.ApiEvent(Guid.NewGuid()) + }; + + return new AuthenticationRequestParameters( + serviceBundle, + new TokenCache(serviceBundle, false), + commonParameters, + requestContext, + authority) + { + }; + } + + public static bool YieldTillSatisfied(Func func, int maxTimeInMilliSec = 30000) + { + int iCount = maxTimeInMilliSec / 100; + while (iCount > 0) + { + if (func()) + { + return true; + } + Thread.Yield(); + Thread.Sleep(100); + iCount--; + } + + return false; + } + + public static MsalAccessTokenCacheItem UpdateATWithRefreshOn( + ITokenCacheAccessor accessor, + DateTimeOffset? refreshOn = null, + bool expired = false) + { + MsalAccessTokenCacheItem atItem = accessor.GetAllAccessTokens().Single(); + + refreshOn ??= DateTimeOffset.UtcNow - TimeSpan.FromMinutes(30); + + atItem = atItem.WithRefreshOn(refreshOn); + + Assert.IsTrue(atItem.ExpiresOn > DateTime.UtcNow + TimeSpan.FromMinutes(10)); + + if (expired) + { + atItem = atItem.WithExpiresOn(DateTime.UtcNow - TimeSpan.FromMinutes(1)); + } + + accessor.SaveAccessToken(atItem); + + return atItem; + } + + internal static MsalAccessTokenCacheItem WithRefreshOn(this MsalAccessTokenCacheItem atItem, DateTimeOffset? refreshOn) + { + MsalAccessTokenCacheItem newAtItem = new MsalAccessTokenCacheItem( + atItem.Environment, + atItem.ClientId, + atItem.ScopeString, + atItem.TenantId, + atItem.Secret, + atItem.CachedAt, + atItem.ExpiresOn, + atItem.ExtendedExpiresOn, + atItem.RawClientInfo, + atItem.HomeAccountId, + atItem.KeyId, + refreshOn, + atItem.TokenType, + atItem.OboCacheKey); + + return newAtItem; + } + } +} diff --git a/src/client/Microsoft.Identity.Lab.Api/Helpers/UserAccessorWithPartitionAsserts.cs b/src/client/Microsoft.Identity.Lab.Api/Helpers/UserAccessorWithPartitionAsserts.cs new file mode 100644 index 0000000000..ac21ca8f68 --- /dev/null +++ b/src/client/Microsoft.Identity.Lab.Api/Helpers/UserAccessorWithPartitionAsserts.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Microsoft.Identity.Client; +using Microsoft.Identity.Client.Cache.Items; +using Microsoft.Identity.Client.Core; +using Microsoft.Identity.Client.PlatformsCommon.Shared; +using Microsoft.Identity.Lab.Api.Helpers; + +namespace Microsoft.Identity.Lab.Api.Helpers +{ + internal class UserAccessorWithPartitionAsserts : InMemoryPartitionedUserTokenCacheAccessor + { + public UserAccessorWithPartitionAsserts(ILoggerAdapter logger, CacheOptions tokenCacheAccessorOptions) : base(logger, tokenCacheAccessorOptions) + { + + } + + public override List GetAllAccessTokens(string partitionKey = null, ILoggerAdapter requestlogger = null) + { + Assert.IsNotNull(partitionKey); + return base.GetAllAccessTokens(partitionKey, requestlogger); + } + + public override List GetAllAccounts(string partitionKey = null, ILoggerAdapter requestlogger = null) + { + Assert.IsNotNull(partitionKey); + return base.GetAllAccounts(partitionKey, requestlogger); + } + + public override List GetAllIdTokens(string partitionKey = null, ILoggerAdapter requestlogger = null) + { + Assert.IsNotNull(partitionKey); + return base.GetAllIdTokens(partitionKey, requestlogger); + } + + public override List GetAllRefreshTokens(string partitionKey = null, ILoggerAdapter requestlogger = null) + { + Assert.IsNotNull(partitionKey); + return base.GetAllRefreshTokens(partitionKey, requestlogger); + } + + public override bool HasAccessOrRefreshTokens() + { + Assert.Fail("HasAccessOrRefreshTokens was called. It should not be called unless the token cache serialization hooks"); + throw new InvalidOperationException(); + } + } +} diff --git a/src/client/Microsoft.Identity.Lab.Api/Http/MockHelpers.cs b/src/client/Microsoft.Identity.Lab.Api/Http/MockHelpers.cs index 1365011376..07f28d12a3 100644 --- a/src/client/Microsoft.Identity.Lab.Api/Http/MockHelpers.cs +++ b/src/client/Microsoft.Identity.Lab.Api/Http/MockHelpers.cs @@ -19,7 +19,6 @@ using Microsoft.Identity.Client.OAuth2.Throttling; using Microsoft.Identity.Client.Utils; using Microsoft.Identity.Test.Unit; -using Microsoft.VisualStudio.TestTools.UnitTesting.Logging; using static Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil; namespace Microsoft.Identity.Test.Common.Core.Mocks diff --git a/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpAndServiceBundle.cs b/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpAndServiceBundle.cs index e3cb1fac57..88b05ba32f 100644 --- a/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpAndServiceBundle.cs +++ b/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpAndServiceBundle.cs @@ -10,8 +10,8 @@ using Microsoft.Identity.Client.Internal.Requests; using Microsoft.Identity.Client.PlatformsCommon.Interfaces; using Microsoft.Identity.Client.TelemetryCore.Internal.Events; +using Microsoft.Identity.Lab.Api.Helpers; using Microsoft.Identity.Test.Unit; -using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Microsoft.Identity.Test.Common.Core.Mocks { diff --git a/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpManager.cs b/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpManager.cs index 3b03f87545..1306dd202f 100644 --- a/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpManager.cs +++ b/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpManager.cs @@ -17,7 +17,7 @@ using Microsoft.Identity.Client.Core; using Microsoft.Identity.Client.Http; using Microsoft.Identity.Client.Http.Retry; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Identity.Lab.Api.Helpers; namespace Microsoft.Identity.Test.Common.Core.Mocks { diff --git a/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpMessageHandler.cs b/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpMessageHandler.cs index 95035c951b..7f2c2541eb 100644 --- a/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpMessageHandler.cs +++ b/src/client/Microsoft.Identity.Lab.Api/Http/MockHttpMessageHandler.cs @@ -11,8 +11,7 @@ using System.Threading.Tasks; using Microsoft.Identity.Client.OAuth2; using Microsoft.Identity.Client.Utils; -using Microsoft.Identity.Test.Common.Core.Helpers; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Identity.Lab.Api.Helpers; namespace Microsoft.Identity.Test.Common.Core.Mocks { @@ -117,7 +116,7 @@ protected override async Task SendAsync(HttpRequestMessage if (ExpectedMtlsBindingCertificate != null) { - Assert.HasCount(1, base.ClientCertificates); + Assert.AreEqual(1, base.ClientCertificates.Count); Assert.AreEqual(ExpectedMtlsBindingCertificate, base.ClientCertificates[0]); } diff --git a/src/client/Microsoft.Identity.Lab.Api/Http/TokenCacheHelper.cs b/src/client/Microsoft.Identity.Lab.Api/Http/TokenCacheHelper.cs index 928854749c..dd9d1c4882 100644 --- a/src/client/Microsoft.Identity.Lab.Api/Http/TokenCacheHelper.cs +++ b/src/client/Microsoft.Identity.Lab.Api/Http/TokenCacheHelper.cs @@ -12,7 +12,7 @@ using Microsoft.Identity.Client.PlatformsCommon.Factories; using Microsoft.Identity.Client.PlatformsCommon.Shared; using Microsoft.Identity.Client.Utils; -using Microsoft.Identity.Test.Common.Core.Helpers; +using Microsoft.Identity.Lab.Api.Helpers; using Microsoft.Identity.Test.Unit; namespace Microsoft.Identity.Test.Common.Core.Mocks @@ -361,12 +361,13 @@ public static void ExpireAllAccessTokens(ITokenCacheInternal tokenCache) { IReadOnlyList allAccessTokens; - // avoid calling GetAllAccessTokens() on the strict accessors, as they will throw - if (tokenCache.Accessor is AppAccessorWithPartitionAsserts appPartitionedAccessor) + // avoid calling GetAllAccessTokens() on strict partition-assert accessors, as they will throw when partitionKey is null. + // Check against the base classes so this works regardless of which concrete subclass is in use. + if (tokenCache.Accessor is InMemoryPartitionedAppTokenCacheAccessor appPartitionedAccessor) { allAccessTokens = appPartitionedAccessor.AccessTokenCacheDictionary.SelectMany(dict => dict.Value).Select(kv => kv.Value).ToList(); } - else if (tokenCache.Accessor is UserAccessorWithPartitionAsserts userPartitionedAccessor) + else if (tokenCache.Accessor is InMemoryPartitionedUserTokenCacheAccessor userPartitionedAccessor) { allAccessTokens = userPartitionedAccessor.AccessTokenCacheDictionary.SelectMany(dict => dict.Value).Select(kv => kv.Value).ToList(); } diff --git a/src/client/Microsoft.Identity.Lab.Api/Internal/TestConstants.cs b/src/client/Microsoft.Identity.Lab.Api/Internal/TestConstants.cs index 93f2f090a0..6fad65f995 100644 --- a/src/client/Microsoft.Identity.Lab.Api/Internal/TestConstants.cs +++ b/src/client/Microsoft.Identity.Lab.Api/Internal/TestConstants.cs @@ -10,7 +10,6 @@ using Microsoft.Identity.Client.Internal; using Microsoft.Identity.Client.OAuth2; using Microsoft.Identity.Client.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Microsoft.Identity.Test.Unit { diff --git a/src/client/Microsoft.Identity.Lab.Api/Microsoft.Identity.Lab.Api.csproj b/src/client/Microsoft.Identity.Lab.Api/Microsoft.Identity.Lab.Api.csproj index 1ebd89639f..5b690f648a 100644 --- a/src/client/Microsoft.Identity.Lab.Api/Microsoft.Identity.Lab.Api.csproj +++ b/src/client/Microsoft.Identity.Lab.Api/Microsoft.Identity.Lab.Api.csproj @@ -41,7 +41,6 @@ - diff --git a/src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt b/src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt index c135715c68..93c043600a 100644 --- a/src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt +++ b/src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt @@ -1,4 +1,4 @@ -const Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.TooManyRequestsContent = "Too many requests error" -> string +const Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.TooManyRequestsContent = "Too many requests error" -> string const Microsoft.Identity.Test.Common.TestCategories.ADFS = "ADFS" -> string const Microsoft.Identity.Test.Common.TestCategories.Arlington = "Arlington" -> string const Microsoft.Identity.Test.Common.TestCategories.B2C = "B2C" -> string @@ -443,9 +443,6 @@ static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.GetMsiImdsErrorResp static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.GetMsiSuccessfulResponse(int expiresInHours = 1, bool useIsoFormat = false, bool imdsV2 = false) -> string static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.GetPopTokenResponse() -> string static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.GetTokenResponseWithNoOidClaim() -> string -static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.MockCertificateRequestResponse(Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId userAssignedIdentityId = Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.None, string userAssignedId = null, string certificate = "MIIDATCCAemgAwIBAgIUSfjghyQB4FIS41rWfNcZHTLE/R4wDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEVGVzdDAgFw0yNTA4MjgyMDIxMDBaGA8yMTI1MDgwNDIwMjEwMFowDzENMAsGA1UEAwwEVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALlc0S6TdwgQKGRl3Y/9uWNRpWo1WHiZtd1YdgCBt0rjxTqsbQUurU0B9Kdk7QQ9srxmjimxGHaUFypbb39awqIdQQcuQvIUj5+sQh9zzCyR35bGQp8vwbna5GlhAIbzsUi/y5kEGUMbuQN05XfoJSQrU35XZ8duQSDH5h9aDr6kuLcpDHo9/9vZiosPfqGPxZGtVjMvrJdVQGLJF35xD3LlX8xG2iJfVK/xYQVi3MgbRNQaL2lHtZaGAc1CToMUPO60xXrZkQE08hC907YTBcavUVQg4vrOaPpsCs+Fj6EJcasADAJeh1mGBn3kHFPCxBa2MKFraFPp53zOagTvYV0CAwEAAaNTMFEwHQYDVR0OBBYEFA9irQR/O6/V2JVyDEHFOdUDjAsyMB8GA1UdIwQYMBaAFA9irQR/O6/V2JVyDEHFOdUDjAsyMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAOxtgYjtkUDVvWzq/lkjLTdcLjPvmH0hF34A3uvX4zcjmqF845lfvszTuhc1mx5J6YLEzKfr4TrO3D3g2BnDLvhupok0wEmJ9yVwbt1laim7zP09gZqnUqYM9hYKDhwgLZAaG3zGNocxDEAU7jazMGOGF7TweB7LdNuVI6CqgDOBQ8Cy2ObuZvzCI5Y7f+HucXpiJOu1xNa2ZZpMpQycYEvi5TD+CL5CBv2fcKQRn/+u5B3ZXCD2C9jT/RZ7rH46mIG7nC7dS4J2o4JjmlJIUAe2U6tRay5GvEmc/nZK8hd9y4BICzrykp9ENAoy9i+uaE1GGWeNgO+irrcrAcLwto=", string clientIdOverride = null, string tenantIdOverride = null, string mtlsEndpointOverride = null) -> Microsoft.Identity.Test.Common.Core.Mocks.MockHttpMessageHandler -static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.MockCsrResponse(System.Net.HttpStatusCode statusCode = System.Net.HttpStatusCode.OK, string responseServerHeader = "IMDS/150.870.65.1854", Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId userAssignedIdentityId = Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.None, string userAssignedId = null, string clientIdOverride = null, string tenantIdOverride = null, string attestationEndpointOverride = null) -> Microsoft.Identity.Test.Common.Core.Mocks.MockHttpMessageHandler -static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.MockCsrResponseFailure() -> Microsoft.Identity.Test.Common.Core.Mocks.MockHttpMessageHandler static Microsoft.Identity.Test.Common.TestData.GetAuthorityWithExpectedTenantId() -> System.Collections.Generic.IEnumerable static Microsoft.Identity.Test.Common.TestData.GetClaimsAndCapabilities() -> System.Collections.Generic.IEnumerable static Microsoft.Identity.Test.LabInfrastructure.CertificateHelper.FindCertificateByName(string subjectName) -> System.Security.Cryptography.X509Certificates.X509Certificate2 @@ -480,3 +477,21 @@ static readonly Microsoft.Identity.Test.Unit.TestConstants.s_extraHttpHeader -> static readonly Microsoft.Identity.Test.Unit.TestConstants.s_graphScopes -> string[] static readonly Microsoft.Identity.Test.Unit.TestConstants.s_scopeForAnotherResource -> System.Collections.Generic.SortedSet static readonly Microsoft.Identity.Test.Unit.TestConstants.s_userIdentifier -> string +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource.AzureArc = 3 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource.CloudShell = 4 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource.Function = 1 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource.ServiceFabric = 5 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource.VM = 2 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource.WebApp = 0 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.MsiAzureResource +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.ClientId = 1 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.None = 0 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.ObjectId = 3 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId +Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.ResourceId = 2 -> Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId +static Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.CreateMIABuilder(string userAssignedId = "", Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId userAssignedIdentityId = Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.ClientId) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder +static Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.SetEnvironmentVariables(Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource managedIdentitySource, string endpoint, string secret = "secret", string thumbprint = "thumbprint") -> void +static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.MockCsrResponse(System.Net.HttpStatusCode statusCode = System.Net.HttpStatusCode.OK, string responseServerHeader = "IMDS/150.870.65.1854", Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId userAssignedIdentityId = Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.None, string userAssignedId = null, string clientIdOverride = null, string tenantIdOverride = null, string attestationEndpointOverride = null) -> Microsoft.Identity.Test.Common.Core.Mocks.MockHttpMessageHandler +static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.MockCsrResponseFailure() -> Microsoft.Identity.Test.Common.Core.Mocks.MockHttpMessageHandler +static Microsoft.Identity.Test.Common.Core.Mocks.MockHelpers.MockCertificateRequestResponse(Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId userAssignedIdentityId = Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil.UserAssignedIdentityId.None, string userAssignedId = null, string certificate = "MIIDATCCAemgAwIBAgIUSfjghyQB4FIS41rWfNcZHTLE/R4wDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEVGVzdDAgFw0yNTA4MjgyMDIxMDBaGA8yMTI1MDgwNDIwMjEwMFowDzENMAsGA1UEAwwEVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALlc0S6TdwgQKGRl3Y/9uWNRpWo1WHiZtd1YdgCBt0rjxTqsbQUurU0B9Kdk7QQ9srxmjimxGHaUFypbb39awqIdQQcuQvIUj5+sQh9zzCyR35bGQp8vwbna5GlhAIbzsUi/y5kEGUMbuQN05XfoJSQrU35XZ8duQSDH5h9aDr6kuLcpDHo9/9vZiosPfqGPxZGtVjMvrJdVQGLJF35xD3LlX8xG2iJfVK/xYQVi3MgbRNQaL2lHtZaGAc1CToMUPO60xXrZkQE08hC907YTBcavUVQg4vrOaPpsCs+Fj6EJcasADAJeh1mGBn3kHFPCxBa2MKFraFPp53zOagTvYV0CAwEAAaNTMFEwHQYDVR0OBBYEFA9irQR/O6/V2JVyDEHFOdUDjAsyMB8GA1UdIwQYMBaAFA9irQR/O6/V2JVyDEHFOdUDjAsyMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAOxtgYjtkUDVvWzq/lkjLTdcLjPvmH0hF34A3uvX4zcjmqF845lfvszTuhc1mx5J6YLEzKfr4TrO3D3g2BnDLvhupok0wEmJ9yVwbt1laim7zP09gZqnUqYM9hYKDhwgLZAaG3zGNocxDEAU7jazMGOGF7TweB7LdNuVI6CqgDOBQ8Cy2ObuZvzCI5Y7f+HucXpiJOu1xNa2ZZpMpQycYEvi5TD+CL5CBv2fcKQRn/+u5B3ZXCD2C9jT/RZ7rH46mIG7nC7dS4J2o4JjmlJIUAe2U6tRay5GvEmc/nZK8hd9y4BICzrykp9ENAoy9i+uaE1GGWeNgO+irrcrAcLwto=", string clientIdOverride = null, string tenantIdOverride = null, string mtlsEndpointOverride = null) -> Microsoft.Identity.Test.Common.Core.Mocks.MockHttpMessageHandler diff --git a/src/client/Microsoft.Identity.Lab.Api/UI/MockWebUI.cs b/src/client/Microsoft.Identity.Lab.Api/UI/MockWebUI.cs index d8f421af9f..59677b29e6 100644 --- a/src/client/Microsoft.Identity.Lab.Api/UI/MockWebUI.cs +++ b/src/client/Microsoft.Identity.Lab.Api/UI/MockWebUI.cs @@ -10,7 +10,7 @@ using Microsoft.Identity.Client.OAuth2; using Microsoft.Identity.Client.UI; using Microsoft.Identity.Client.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Identity.Lab.Api.Helpers; namespace Microsoft.Identity.Test.Common.Mocks { diff --git a/tests/Microsoft.Identity.Test.Common/ManagedIdentityTestUtil.cs b/tests/Microsoft.Identity.Test.Common/ManagedIdentityTestUtil.cs deleted file mode 100644 index ec3517179f..0000000000 --- a/tests/Microsoft.Identity.Test.Common/ManagedIdentityTestUtil.cs +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.Identity.Client; -using Microsoft.Identity.Client.AppConfig; -using Microsoft.Identity.Client.ManagedIdentity; - -namespace Microsoft.Identity.Test.Common.Core.Helpers -{ - /// - /// ManagedIdentityTestUtil provides utility methods for setting up and managing environment variables - /// related to managed identities in test scenarios. These utilities help simulate different managed - /// identity sources and configurations, facilitating comprehensive testing of MSAL's managed identity - /// integration. - /// - public static class ManagedIdentityTestUtil - { - /// - /// user assigned identity identifier types for testing. This enum is used to specify the type of identifier (ClientId, ResourceId, ObjectId) when creating a user-assigned managed identity in tests. - /// - public enum UserAssignedIdentityId - { - /// - /// represents the absence of a user-assigned identity identifier. This value is used when creating a managed identity without specifying any identifier, allowing tests to verify behavior when no user-assigned identity is configured. - /// - None, - /// - /// represents a user-assigned identity identified by its client ID. This value is used when creating a managed identity with a specific client ID, allowing tests to verify behavior when a client ID is provided. - /// - ClientId, - /// - /// represents a user-assigned identity identified by its resource ID. This value is used when creating a managed identity with a specific resource ID, allowing tests to verify behavior when a resource ID is provided. - /// - ResourceId, - /// - /// represents a user-assigned identity identified by its object ID. This value is used when creating a managed identity with a specific object ID, allowing tests to verify behavior when an object ID is provided. - /// - ObjectId - } - - //MSI Azure resources - /// - /// MSI Azure resource types for testing. This enum is used to specify the type of Azure resource (WebApp, Function, VM, AzureArc, CloudShell, ServiceFabric) when creating a managed identity in tests. - /// - public enum MsiAzureResource - { - /// - /// Web App resource type for managed identity testing. This value is used when simulating a managed identity associated with an Azure Web App, allowing tests to verify behavior specific to this resource type. - /// - WebApp, - /// - /// Function resource type for managed identity testing. This value is used when simulating a managed identity associated with an Azure Function, allowing tests to verify behavior specific to this resource type. - /// - Function, - /// - /// VM resource type for managed identity testing. This value is used when simulating a managed identity associated with an Azure Virtual Machine, allowing tests to verify behavior specific to this resource type. - /// - VM, - /// - /// Azure Arc resource type for managed identity testing. This value is used when simulating a managed identity associated with Azure Arc, allowing tests to verify behavior specific to this resource type. - /// - AzureArc, - /// - /// Cloud Shell resource type for managed identity testing. This value is used when simulating a managed identity associated with Azure Cloud Shell, allowing tests to verify behavior specific to this resource type. - /// - CloudShell, - /// - /// Service Fabric resource type for managed identity testing. This value is used when simulating a managed identity associated with Azure Service Fabric, allowing tests to verify behavior specific to this resource type. - /// - ServiceFabric - } - - /// - /// Sets environment variables for the specified managed identity source. - /// - /// The managed identity source. - /// The endpoint URL. - /// The secret value (default is "secret"). - /// The certificate thumbprint (default is "thumbprint"). - public static void SetEnvironmentVariables(ManagedIdentitySource managedIdentitySource, string endpoint, string secret = "secret", string thumbprint = "thumbprint") - { - switch (managedIdentitySource) - { - case ManagedIdentitySource.AppService: - Environment.SetEnvironmentVariable("IDENTITY_ENDPOINT", endpoint); - Environment.SetEnvironmentVariable("IDENTITY_HEADER", secret); - break; - - case ManagedIdentitySource.Imds: - case ManagedIdentitySource.ImdsV2: - Environment.SetEnvironmentVariable("AZURE_POD_IDENTITY_AUTHORITY_HOST", endpoint); - break; - - case ManagedIdentitySource.AzureArc: - Environment.SetEnvironmentVariable("IDENTITY_ENDPOINT", endpoint); - Environment.SetEnvironmentVariable("IMDS_ENDPOINT", "http://localhost:40342"); - break; - - case ManagedIdentitySource.CloudShell: - Environment.SetEnvironmentVariable("MSI_ENDPOINT", endpoint); - break; - - case ManagedIdentitySource.ServiceFabric: - Environment.SetEnvironmentVariable("IDENTITY_ENDPOINT", endpoint); - Environment.SetEnvironmentVariable("IDENTITY_HEADER", secret); - Environment.SetEnvironmentVariable("IDENTITY_SERVER_THUMBPRINT", thumbprint); - break; - - case ManagedIdentitySource.MachineLearning: - Environment.SetEnvironmentVariable("MSI_ENDPOINT", endpoint); - Environment.SetEnvironmentVariable("MSI_SECRET", secret); - Environment.SetEnvironmentVariable("DEFAULT_IDENTITY_CLIENT_ID", "fake_DEFAULT_IDENTITY_CLIENT_ID"); - break; - - default: - throw new NotImplementedException($"Setting environment variables for {managedIdentitySource} is not implemented."); - } - } - - /// - /// Sets environment variables for testing upgrade scenarios. - /// This method mimics a scenario where older environment variables - /// (e.g., MSI_ENDPOINT and MSI_SECRET) from previous versions of - /// App Service (2017) still exist after an upgrade to newer versions (2019). - /// It ensures that MSAL's Managed Identity source detection can correctly - /// handle both legacy and new variables. - /// - /// - /// The type of managed identity source being tested (e.g., AppService, MachineLearning). - /// - /// - /// The endpoint URL to be set as part of the environment variables. - /// - /// - /// Optional: The secret value to be set (default is "secret"). - /// - /// - /// Optional: The certificate thumbprint to be set (default is "thumbprint"). - /// - internal static void SetUpgradeScenarioEnvironmentVariables(ManagedIdentitySource managedIdentitySource, string endpoint, string secret = "secret", string thumbprint = "thumbprint") - { - // Use the common method to set base environment variables - SetEnvironmentVariables(managedIdentitySource, endpoint, secret, thumbprint); - - // Add upgrade-specific variables where needed - switch (managedIdentitySource) - { - case ManagedIdentitySource.AppService: - Environment.SetEnvironmentVariable("MSI_ENDPOINT", endpoint); - Environment.SetEnvironmentVariable("MSI_SECRET", secret); - break; - } - } - - /// - /// Create the MIA with the http proxy - /// - /// - /// - /// - public static ManagedIdentityApplicationBuilder CreateMIABuilder(string userAssignedId = "", UserAssignedIdentityId userAssignedIdentityId = UserAssignedIdentityId.ClientId) - { - var builder = ManagedIdentityApplicationBuilder.Create(ManagedIdentityId.WithUserAssignedClientId(userAssignedId)); - - switch (userAssignedIdentityId) - { - case UserAssignedIdentityId.ResourceId: - builder = ManagedIdentityApplicationBuilder.Create(ManagedIdentityId.WithUserAssignedResourceId(userAssignedId)); - break; - - case UserAssignedIdentityId.ObjectId: - builder = ManagedIdentityApplicationBuilder.Create(ManagedIdentityId.WithUserAssignedObjectId(userAssignedId)); - break; - } - - - builder.Config.AccessorOptions = null; - - return builder; - } - } -} diff --git a/tests/Microsoft.Identity.Test.Common/Microsoft.Identity.Test.Common.csproj b/tests/Microsoft.Identity.Test.Common/Microsoft.Identity.Test.Common.csproj index 3178aed835..73627f8998 100644 --- a/tests/Microsoft.Identity.Test.Common/Microsoft.Identity.Test.Common.csproj +++ b/tests/Microsoft.Identity.Test.Common/Microsoft.Identity.Test.Common.csproj @@ -25,6 +25,7 @@ +