diff --git a/src/service/API/Microsoft.FeatureFlighting.API.csproj b/src/service/API/Microsoft.FeatureFlighting.API.csproj
index b92b30f..3d5b7a9 100644
--- a/src/service/API/Microsoft.FeatureFlighting.API.csproj
+++ b/src/service/API/Microsoft.FeatureFlighting.API.csproj
@@ -30,9 +30,11 @@
-
-
-
+
+
+
+
+
diff --git a/src/service/API/Program.cs b/src/service/API/Program.cs
index 84cded3..bab153a 100644
--- a/src/service/API/Program.cs
+++ b/src/service/API/Program.cs
@@ -9,6 +9,7 @@
using Autofac.Extensions.DependencyInjection;
using Azure.Extensions.AspNetCore.Configuration.Secrets;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
+using Azure.Core;
namespace Microsoft.PS.Services.FlightingService.Api
{
@@ -16,7 +17,7 @@ namespace Microsoft.PS.Services.FlightingService.Api
public static class Program
{
public static void Main(string[] args)
- {
+ {
CreateHostBuilder(args).Build().Run();
}
@@ -37,12 +38,19 @@ public static IHostBuilder CreateHostBuilder(string[] args)
private static void AddKeyVault(IConfigurationBuilder config)
{
- var builtConfig = config.Build();
+ var builtConfig = config.Build();
+ TokenCredential credential;
+ #if DEBUG
+ credential = new VisualStudioCredential();
+ #else
+ credential = new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(builtConfig["UserAssignedClientId"]));
+ #endif
config.AddAzureKeyVault(
new SecretClient(
new Uri(builtConfig["KeyVault:EndpointUrl"]),
- credential: new DefaultAzureCredential()
+ credential
),
new AzureKeyVaultConfigurationOptions()
{
@@ -58,12 +66,19 @@ private static void AddAzureAppConfiguration(IConfigurationBuilder config)
string appConfigurationUri = builtConfig["AzureAppConfigurationUri"];
string flightingAppConfigLabel = builtConfig["AppConfiguration:FeatureFlightsLabel"];
string configurationCommonLabel = builtConfig["AppConfiguration:ConfigurationCommonLabel"];
- string configurationEnvLabel = builtConfig["AppConfiguration:ConfigurationEnvLabel"];
+ string configurationEnvLabel = builtConfig["AppConfiguration:ConfigurationEnvLabel"];
+ TokenCredential credential;
+ #if DEBUG
+ credential = new VisualStudioCredential();
+ #else
+ credential = new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(builtConfig["UserAssignedClientId"]));
+ #endif
config.AddAzureAppConfiguration(options =>
{
options
- .Connect(new Uri(appConfigurationUri),new DefaultAzureCredential())
+ .Connect(new Uri(appConfigurationUri), credential)
.UseFeatureFlags(configure =>
{
configure.Label = flightingAppConfigLabel;
diff --git a/src/service/API/appsettings.fxp-preprod.json b/src/service/API/appsettings.fxp-preprod.json
index 4fbc948..1c54228 100644
--- a/src/service/API/appsettings.fxp-preprod.json
+++ b/src/service/API/appsettings.fxp-preprod.json
@@ -12,5 +12,6 @@
"Name": "kv-exp-ppe-eus",
"EndpointUrl": "https://kv-exp-ppe-eus.vault.azure.net/",
"PollingIntervalInHours": 1
- }
+ },
+ "UserAssignedClientId": "493d2364-979a-49e8-a67a-6db0446d079b"
}
diff --git a/src/service/API/appsettings.fxp-prod.json b/src/service/API/appsettings.fxp-prod.json
index 52501c7..acd0283 100644
--- a/src/service/API/appsettings.fxp-prod.json
+++ b/src/service/API/appsettings.fxp-prod.json
@@ -12,5 +12,6 @@
"Name": "kv-exp-ppe-eus",
"EndpointUrl": "https://kv-exp-prod-eus.vault.azure.net/",
"PollingIntervalInHours": 1
- }
+ },
+ "UserAssignedClientId": "78d78b7f-4c24-44d7-96f2-b1b73852068f"
}
diff --git a/src/service/Common/Authentication/ITokenGenerator.cs b/src/service/Common/Authentication/ITokenGenerator.cs
index c262690..4e47a89 100644
--- a/src/service/Common/Authentication/ITokenGenerator.cs
+++ b/src/service/Common/Authentication/ITokenGenerator.cs
@@ -13,7 +13,8 @@ public interface ITokenGenerator
/// Authority to generate the token
/// ID of the application for generating the token
/// Resource ID for which the token is generated
+ /// user Assigned Client Id
/// Bearer token
- Task GenerateToken(string authority, string clientId, string resourceId);
+ Task GenerateToken(string authority, string clientId, string resourceId, string userAssignedClientId);
}
}
diff --git a/src/service/Common/Authorization/IAuthorizationService.cs b/src/service/Common/Authorization/IAuthorizationService.cs
index 89921f0..30995ba 100644
--- a/src/service/Common/Authorization/IAuthorizationService.cs
+++ b/src/service/Common/Authorization/IAuthorizationService.cs
@@ -23,15 +23,16 @@ public interface IAuthorizationService
/// Tenant name
/// True if the required claims are present
bool IsAuthorized(string appName);
-
+
///
/// Creates the bearer token
///
/// IDP authority
/// AAD Client ID
/// AAD Client ID against which the token is acquired
+ /// user Assigned Client Id
/// Bearer token
- Task GetAuthenticationToken(string authority, string clientId, string resourceId);
+ Task GetAuthenticationToken(string authority, string clientId, string resourceId,string userAssignedClientId);
///
/// Augments the user identity with the required claims
diff --git a/src/service/Domain/Microsoft.FeatureFlighting.Core.csproj b/src/service/Domain/Microsoft.FeatureFlighting.Core.csproj
index b45eba5..428de78 100644
--- a/src/service/Domain/Microsoft.FeatureFlighting.Core.csproj
+++ b/src/service/Domain/Microsoft.FeatureFlighting.Core.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/src/service/Infrastructure/AppConfig/AzureConfigurationClientProvider.cs b/src/service/Infrastructure/AppConfig/AzureConfigurationClientProvider.cs
index 538e4e9..25f2726 100644
--- a/src/service/Infrastructure/AppConfig/AzureConfigurationClientProvider.cs
+++ b/src/service/Infrastructure/AppConfig/AzureConfigurationClientProvider.cs
@@ -3,9 +3,10 @@
using Azure.Data.AppConfiguration;
using Azure.Identity;
using Microsoft.Extensions.Configuration;
+using static Microsoft.AspNetCore.Hosting.Internal.HostingApplication;
namespace Microsoft.FeatureFlighting.Infrastructure.AppConfig
-{
+{
//
internal class AzureConfigurationClientProvider : IAzureConfigurationClientProvider
{
@@ -31,9 +32,15 @@ public ConfigurationClient GetConfigurationClient()
options.Retry.Mode = RetryMode.Exponential;
options.Retry.MaxRetries = 10;
options.Retry.Delay = TimeSpan.FromSeconds(1);
-
+ TokenCredential credential;
+ #if DEBUG
+ credential = new VisualStudioCredential();
+ #else
+ credential = new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(_configuration["UserAssignedClientId"]));
+ #endif
string appConfigUri = _configuration["AzureAppConfigurationUri"];
- _configurationClient = new ConfigurationClient(new Uri(appConfigUri), new DefaultAzureCredential(), options);
+ _configurationClient = new ConfigurationClient(new Uri(appConfigUri), credential, options);
return _configurationClient;
}
diff --git a/src/service/Infrastructure/Authentication/AadTokenGenerator.cs b/src/service/Infrastructure/Authentication/AadTokenGenerator.cs
index c5b4320..4af72e3 100644
--- a/src/service/Infrastructure/Authentication/AadTokenGenerator.cs
+++ b/src/service/Infrastructure/Authentication/AadTokenGenerator.cs
@@ -26,9 +26,9 @@ public AadTokenGenerator()
}
//
- public async Task GenerateToken(string authority, string clientId, string resourceId)
+ public async Task GenerateToken(string authority, string clientId, string resourceId, string userAssignedClientId)
{
- IConfidentialClientApplication client = GetOrCreateConfidentialApp(authority, clientId);
+ IConfidentialClientApplication client = GetOrCreateConfidentialApp(authority, clientId, userAssignedClientId);
var scopes = new string[] { resourceId };
AuthenticationResult authenticationResult = await client
.AcquireTokenForClient(scopes)
@@ -36,7 +36,7 @@ public async Task GenerateToken(string authority, string clientId, strin
return authenticationResult.AccessToken;
}
- private IConfidentialClientApplication GetOrCreateConfidentialApp(string authority, string clientId)
+ private IConfidentialClientApplication GetOrCreateConfidentialApp(string authority, string clientId, string userAssignedClientId)
{
string confidentialAppCacheKey = CreateConfidentialAppCacheKey(authority, clientId);
if (_cache.ContainsKey(confidentialAppCacheKey))
@@ -58,13 +58,15 @@ private IConfidentialClientApplication GetOrCreateConfidentialApp(string authori
return client;
#else
+ var credential = new ManagedIdentityCredential(userAssignedClientId);
+
IConfidentialClientApplication client =
ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority(new Uri(authority))
.WithClientAssertion((AssertionRequestOptions options) =>
{
- var accessToken = new DefaultAzureCredential().GetToken(new TokenRequestContext(new string[] { $"api://AzureADTokenExchange/.default" }), CancellationToken.None);
+ var accessToken = credential.GetToken(new TokenRequestContext(new string[] { $"api://AzureADTokenExchange/.default" }), CancellationToken.None);
return Task.FromResult(accessToken.Token);
})
.Build();
diff --git a/src/service/Infrastructure/Authorization/AuthorizationService.cs b/src/service/Infrastructure/Authorization/AuthorizationService.cs
index 64dfb69..2b88426 100644
--- a/src/service/Infrastructure/Authorization/AuthorizationService.cs
+++ b/src/service/Infrastructure/Authorization/AuthorizationService.cs
@@ -75,14 +75,14 @@ public bool IsAuthorized(string appName)
return false;
}
- public async Task GetAuthenticationToken(string authority, string clientId, string resourceId)
+ public async Task GetAuthenticationToken(string authority, string clientId, string resourceId,string userAssignedClientId)
{
AuthenticationResult authenticationResult;
const string MsalScopeSuffix = "/.default";
string bearerToken = null;
try
{
- IConfidentialClientApplication app = GetOrCreateConfidentialApp(authority, clientId);
+ IConfidentialClientApplication app = GetOrCreateConfidentialApp(authority, clientId, userAssignedClientId);
if (app != null)
{
var scopes = new[] { resourceId + MsalScopeSuffix };
@@ -97,7 +97,7 @@ public async Task GetAuthenticationToken(string authority, string client
return bearerToken;
}
- private IConfidentialClientApplication GetOrCreateConfidentialApp(string authority, string clientId)
+ private IConfidentialClientApplication GetOrCreateConfidentialApp(string authority, string clientId,string userAssignedClientId)
{
string confidentialAppCacheKey = $"{authority}-{clientId}";
if (_confidentialApps.ContainsKey(confidentialAppCacheKey))
@@ -115,13 +115,14 @@ private IConfidentialClientApplication GetOrCreateConfidentialApp(string authori
_confidentialApps.TryAdd(confidentialAppCacheKey, app);
return app;
#else
+ var credential = new ManagedIdentityCredential(userAssignedClientId);
IConfidentialClientApplication app =
ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority(new Uri(authority))
.WithClientAssertion((AssertionRequestOptions options) =>
{
- var accessToken = new DefaultAzureCredential().GetToken(new TokenRequestContext(new string[] { $"api://AzureADTokenExchange/.default" }), CancellationToken.None);
+ var accessToken = credential.GetToken(new TokenRequestContext(new string[] { $"api://AzureADTokenExchange/.default" }), CancellationToken.None);
return Task.FromResult(accessToken.Token);
})
.Build();
diff --git a/src/service/Infrastructure/Graph/GraphGroupVerificationService.cs b/src/service/Infrastructure/Graph/GraphGroupVerificationService.cs
index c1f9737..e13e9e2 100644
--- a/src/service/Infrastructure/Graph/GraphGroupVerificationService.cs
+++ b/src/service/Infrastructure/Graph/GraphGroupVerificationService.cs
@@ -147,13 +147,14 @@ private IGraphServiceClient CreateGraphClient(IConfiguration configuration)
_cache.Add(confidentialAppCacheKey, client);
#else
- IConfidentialClientApplication client =
+ var credential = new ManagedIdentityCredential(configuration["UserAssignedClientId"]);
+ IConfidentialClientApplication client =
ConfidentialClientApplicationBuilder
.Create(configuration["Graph:ClientId"])
.WithAuthority(new Uri(authority))
.WithClientAssertion((AssertionRequestOptions options) =>
{
- var accessToken = new DefaultAzureCredential().GetToken(new TokenRequestContext(new string[] { $"api://AzureADTokenExchange/.default" }), CancellationToken.None);
+ var accessToken = credential.GetToken(new TokenRequestContext(new string[] { $"api://AzureADTokenExchange/.default" }), CancellationToken.None);
return Task.FromResult(accessToken.Token);
})
.Build();
diff --git a/src/service/Infrastructure/Microsoft.FeatureFlighting.Infrastructure.csproj b/src/service/Infrastructure/Microsoft.FeatureFlighting.Infrastructure.csproj
index 9c7f96e..8d63f16 100644
--- a/src/service/Infrastructure/Microsoft.FeatureFlighting.Infrastructure.csproj
+++ b/src/service/Infrastructure/Microsoft.FeatureFlighting.Infrastructure.csproj
@@ -13,7 +13,7 @@
-
+
diff --git a/src/service/Infrastructure/Storage/BlobProviderFactory.cs b/src/service/Infrastructure/Storage/BlobProviderFactory.cs
index 1b7dc34..6ec0d1b 100644
--- a/src/service/Infrastructure/Storage/BlobProviderFactory.cs
+++ b/src/service/Infrastructure/Storage/BlobProviderFactory.cs
@@ -8,6 +8,9 @@
using Microsoft.FeatureFlighting.Common.Storage;
using Azure.Identity;
using Microsoft.FeatureFlighting.Common;
+using Azure.Core;
+using Microsoft.Extensions.Configuration;
+using System.Reflection.PortableExecutable;
namespace Microsoft.FeatureFlighting.Infrastructure.Storage
{
@@ -17,16 +20,23 @@ internal class BlobProviderFactory : IBlobProviderFactory
private readonly ITenantConfigurationProvider _tenantConfigurationProvider;
private readonly ILogger _logger;
private readonly IDictionary _blobProviderCache;
- private readonly DefaultAzureCredential _defaultAzureCredential;
-
- public BlobProviderFactory(ITenantConfigurationProvider tenantConfigurationProvider, ILogger logger)
+ private readonly TokenCredential _defaultAzureCredential;
+ private readonly IConfiguration _configuration;
+ public BlobProviderFactory(ITenantConfigurationProvider tenantConfigurationProvider, ILogger logger, IConfiguration configuration)
{
_tenantConfigurationProvider = tenantConfigurationProvider ?? throw new ArgumentNullException(nameof(tenantConfigurationProvider));
_blobProviderCache = new ConcurrentDictionary(StringComparer.InvariantCultureIgnoreCase);
_logger = logger;
+ _configuration = configuration;
if (_defaultAzureCredential == null)
- _defaultAzureCredential = new DefaultAzureCredential();
-
+ {
+ #if DEBUG
+ _defaultAzureCredential = new VisualStudioCredential();
+ #else
+ _defaultAzureCredential = new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(_configuration["UserAssignedClientId"]));
+ #endif
+ }
}
///
diff --git a/src/service/Infrastructure/Storage/CosmosDbRepository.cs b/src/service/Infrastructure/Storage/CosmosDbRepository.cs
index 001e2f6..9b6c1d8 100644
--- a/src/service/Infrastructure/Storage/CosmosDbRepository.cs
+++ b/src/service/Infrastructure/Storage/CosmosDbRepository.cs
@@ -13,13 +13,14 @@
using Microsoft.FeatureFlighting.Common.AppExceptions;
using Microsoft.FeatureFlighting.Common.Config;
using Azure.Identity;
+using Azure.Core;
namespace Microsoft.FeatureFlighting.Infrastructure.Storage
{
///
/// Azure Cosmos DB Document repository
///
- internal class CosmosDbRepository: IDocumentRepository where TDoc : class, new()
+ internal class CosmosDbRepository : IDocumentRepository where TDoc : class, new()
{
private readonly IConfiguration _configuration;
private readonly ILogger _logger;
@@ -40,7 +41,15 @@ public CosmosDbRepository(CosmosDbConfiguration cosmosConfiguration, IConfigurat
MaxRetryWaitTimeOnRateLimitedRequests = TimeSpan.FromSeconds(int.Parse(_configuration["CosmosDb:MaxRetryWaitTimeOnRateLimitedRequests"])),
MaxRetryAttemptsOnRateLimitedRequests = int.Parse(_configuration["CosmosDb:MaxRetryAttemptsOnRateLimitedRequests"])
};
- CosmosClient client = new(cosmosConfiguration.Endpoint, new DefaultAzureCredential(), options);
+ TokenCredential credential;
+ #if DEBUG
+ credential = new VisualStudioCredential();
+ #else
+ credential = new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(_configuration["UserAssignedClientId"]));
+ #endif
+
+ CosmosClient client = new(cosmosConfiguration.Endpoint, credential, options);
Database database = client.GetDatabase(cosmosConfiguration.DatabaseId);
_container = database.GetContainer(cosmosConfiguration.ContainerId);
_logger = logger;
diff --git a/src/service/Infrastructure/Webhook/WebhookTriggerManager.cs b/src/service/Infrastructure/Webhook/WebhookTriggerManager.cs
index 030333d..85d5aec 100644
--- a/src/service/Infrastructure/Webhook/WebhookTriggerManager.cs
+++ b/src/service/Infrastructure/Webhook/WebhookTriggerManager.cs
@@ -13,6 +13,7 @@
using System.Collections.Generic;
using Microsoft.Graph;
using System.Linq;
+using Microsoft.Extensions.Configuration;
namespace Microsoft.FeatureFlighting.Infrastructure.Webhook
{
@@ -22,13 +23,14 @@ internal class WebhookTriggerManager: IWebhookTriggerManager
private readonly IHttpClientFactory _httpClientFactory;
private readonly ITokenGenerator _tokenGenerator;
private readonly ILogger _logger;
+ public IConfiguration _configuration { get; }
- public WebhookTriggerManager(IHttpClientFactory httpClientFactory, ITokenGenerator tokenGenerator, ILogger logger)
- {
-
+ public WebhookTriggerManager(IHttpClientFactory httpClientFactory, ITokenGenerator tokenGenerator, ILogger logger, IConfiguration configuration)
+ {
_httpClientFactory = httpClientFactory;
_tokenGenerator = tokenGenerator;
_logger= logger;
+ _configuration = configuration;
}
//
@@ -47,7 +49,7 @@ public async Task Trigger(WebhookConfiguration webhook, string payload,
DependencyContext dependency = CreateDependencyContext(webhook, trackingIds);
HttpRequestMessage request = new(new HttpMethod(webhook.HttpMethod), webhook.Uri ?? "");
- string bearerToken = await _tokenGenerator.GenerateToken(webhook.AuthenticationAuthority, webhook.ClientId, webhook.ResourceId);
+ string bearerToken = await _tokenGenerator.GenerateToken(webhook.AuthenticationAuthority, webhook.ClientId, webhook.ResourceId, _configuration["UserAssignedClientId"]);
request.Headers.Add("Authorization", $"Bearer {bearerToken}");
request.Headers.Add("x-correlationId", trackingIds.CorrelationId);
request.Headers.Add("x-messageId", trackingIds.TransactionId);
diff --git a/src/service/Tests/Api.Tests/Microsoft.FeatureFlighting.API.Tests.csproj b/src/service/Tests/Api.Tests/Microsoft.FeatureFlighting.API.Tests.csproj
index 61ddf58..85b819e 100644
--- a/src/service/Tests/Api.Tests/Microsoft.FeatureFlighting.API.Tests.csproj
+++ b/src/service/Tests/Api.Tests/Microsoft.FeatureFlighting.API.Tests.csproj
@@ -7,8 +7,11 @@
-
-
+
+
+
+
+
diff --git a/src/service/Tests/Domain.Tests/Microsoft.PS.FlightingService.Core.Tests.csproj b/src/service/Tests/Domain.Tests/Microsoft.PS.FlightingService.Core.Tests.csproj
index bf19a76..cda8a01 100644
--- a/src/service/Tests/Domain.Tests/Microsoft.PS.FlightingService.Core.Tests.csproj
+++ b/src/service/Tests/Domain.Tests/Microsoft.PS.FlightingService.Core.Tests.csproj
@@ -13,6 +13,7 @@
+
diff --git a/src/service/Tests/Services.Tests/Microsoft.FeatureFlighting.Infrastructure.Tests.csproj b/src/service/Tests/Services.Tests/Microsoft.FeatureFlighting.Infrastructure.Tests.csproj
index 562a3e7..dc7782a 100644
--- a/src/service/Tests/Services.Tests/Microsoft.FeatureFlighting.Infrastructure.Tests.csproj
+++ b/src/service/Tests/Services.Tests/Microsoft.FeatureFlighting.Infrastructure.Tests.csproj
@@ -21,6 +21,7 @@
+
diff --git a/tests/functional/Tests/FeatureFlagClient.cs b/tests/functional/Tests/FeatureFlagClient.cs
index 55e99d2..7a11869 100644
--- a/tests/functional/Tests/FeatureFlagClient.cs
+++ b/tests/functional/Tests/FeatureFlagClient.cs
@@ -9,6 +9,7 @@
using Microsoft.FeatureFlighting.Tests.Functional.Utilities;
using Azure.Core;
using Azure.Identity;
+using System.Threading;
namespace Microsoft.FeatureFlighting.Tests.Functional
{
@@ -217,7 +218,7 @@ private static async Task GetClientSecretForAuthentication()
{
return _testContext.Properties["FunctionalTest:AAD:ClientSecret"].ToString();
}
- return await KeyVaultHelper.Instance.GetSecret(_testContext.Properties["FunctionalTest:KeyVault:Endpoint"].ToString(), _testContext.Properties["FunctionalTest:AAD:ClientSecret"].ToString());
+ return await KeyVaultHelper.Instance.GetSecret(_testContext.Properties["FunctionalTest:KeyVault:Endpoint"].ToString(), _testContext.Properties["FunctionalTest:AAD:ClientSecret"].ToString(), _testContext.Properties["FunctionalTest:UserAssignedClientId"].ToString());
}
private static async Task GetAlternateClientSecretForAuthentication()
@@ -226,7 +227,7 @@ private static async Task GetAlternateClientSecretForAuthentication()
{
return _testContext.Properties["FunctionalTest:InvalidAAD:ClientSecret"].ToString();
}
- return await KeyVaultHelper.Instance.GetSecret(_testContext.Properties["FunctionalTest:KeyVault:Endpoint"].ToString(), _testContext.Properties["FunctionalTest:InvalidAAD:ClientSecret"].ToString());
+ return await KeyVaultHelper.Instance.GetSecret(_testContext.Properties["FunctionalTest:KeyVault:Endpoint"].ToString(), _testContext.Properties["FunctionalTest:InvalidAAD:ClientSecret"].ToString(), _testContext.Properties["FunctionalTest:UserAssignedClientId"].ToString());
}
private static async Task GetAccessTokenAsync()
@@ -239,10 +240,17 @@ private static async Task GetAccessTokenAsync()
string cachedToken = _tokenCache.GetValueOrDefault(clientId, null);
if (!string.IsNullOrWhiteSpace(cachedToken))
return cachedToken;
-
- var tokenCredential = new DefaultAzureCredential();
- var accessToken = await tokenCredential.GetTokenAsync(
- new TokenRequestContext(scopes: new string[] { flightingResource + "/.default" }) { });
+ string userAssignedClientId = _testContext.Properties["FunctionalTest:UserAssignedClientId"].ToString();
+ TokenCredential credential;
+ #if DEBUG
+ credential = new VisualStudioCredential();
+ #else
+ credential = new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(userAssignedClientId));
+ #endif
+
+ var accessToken = await credential.GetTokenAsync(
+ new TokenRequestContext(scopes: new string[] { flightingResource + "/.default" }), CancellationToken.None);
return accessToken.Token;
}
@@ -252,10 +260,17 @@ private static async Task GetAccessTokenAsyncFromAlternateAccount()
string flightingKey = await GetAlternateClientSecretForAuthentication();
string flightingResource = _testContext.Properties["FunctionalTest:FxpFlighting:AAD:ResourceId"].ToString();
string authority = _testContext.Properties["FunctionalTest:AAD:Authority"].ToString();
-
- var tokenCredential = new DefaultAzureCredential();
- var accessToken = await tokenCredential.GetTokenAsync(
- new TokenRequestContext(scopes: new string[] { flightingResource + "/.default" }) { });
+ string userAssignedClientId = _testContext.Properties["FunctionalTest:UserAssignedClientId"].ToString();
+ TokenCredential credential;
+ #if DEBUG
+ credential = new VisualStudioCredential();
+ #else
+ credential = new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(userAssignedClientId));
+ #endif
+
+ var accessToken = await credential.GetTokenAsync(
+ new TokenRequestContext(scopes: new string[] { flightingResource + "/.default" }), CancellationToken.None );
return accessToken.Token;
}
}
diff --git a/tests/functional/Tests/Helper/KeyVaultHelper.cs b/tests/functional/Tests/Helper/KeyVaultHelper.cs
index 263db5f..657c6b1 100644
--- a/tests/functional/Tests/Helper/KeyVaultHelper.cs
+++ b/tests/functional/Tests/Helper/KeyVaultHelper.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Collections.Concurrent;
using Azure.Security.KeyVault.Secrets;
+using Azure.Core;
namespace Microsoft.FeatureFlighting.Tests.Functional.Helper
{
@@ -28,12 +29,20 @@ public static KeyVaultHelper Instance
}
}
- public async Task GetSecret(string keyVaultEndpoint, string secretName)
+ public async Task GetSecret(string keyVaultEndpoint, string secretName,string userAssignedClientId)
{
if (SecretsCache.ContainsKey(secretName))
return SecretsCache[secretName];
+ TokenCredential credential;
- SecretClient client = new(new System.Uri(keyVaultEndpoint), new DefaultAzureCredential());
+ #if DEBUG
+ credential = new VisualStudioCredential();
+ #else
+ credential = new ManagedIdentityCredential(
+ ManagedIdentityId.FromUserAssignedClientId(userAssignedClientId));
+ #endif
+
+ SecretClient client = new(new System.Uri(keyVaultEndpoint), credential);
KeyVaultSecret secret = await client.GetSecretAsync(secretName);
return secret.Value;
}
diff --git a/tests/functional/Tests/Local.runsettings b/tests/functional/Tests/Local.runsettings
index 3612968..9c83e2c 100644
--- a/tests/functional/Tests/Local.runsettings
+++ b/tests/functional/Tests/Local.runsettings
@@ -32,6 +32,7 @@
+
diff --git a/tests/functional/Tests/PreProduction.runsettings b/tests/functional/Tests/PreProduction.runsettings
index 9482dad..9bb2830 100644
--- a/tests/functional/Tests/PreProduction.runsettings
+++ b/tests/functional/Tests/PreProduction.runsettings
@@ -32,6 +32,7 @@
+
diff --git a/tests/functional/Tests/Production.runsettings b/tests/functional/Tests/Production.runsettings
index 3d798f7..29131ad 100644
--- a/tests/functional/Tests/Production.runsettings
+++ b/tests/functional/Tests/Production.runsettings
@@ -32,6 +32,7 @@
+