I have a .NET Core 3.1 Web API project in which I'm trying to wire up Azure App Config. I have it working in a couple other .NET Framework projects just fine, but when I try to implement it in a Core 3.1 project, I am able to read unencrypted values from the App Config if the App Cong only contains unencrypted values, but get an exception whenever my App Config contains any reference to any Azure Key Vault secrets.
So far, I am just proving this out with a unit test project within the API solution. Here's the code:
namespace WebApi.Test.Integration.Settings
{
public abstract class SettingsTestBase
{
protected SettingsTestBase()
{
Environment.SetEnvironmentVariable("Azure_Tenant_Id", "my-tenant-id");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
}
}
public class SettingsTests : SettingsTestBase
{
[Fact]
public void SettingsRequest_ReturnsValidSettings()
{
var config = GetConfiguration("https://my.keyvault.url.net");
var setting = config["my-keyvaultvalue-v1"] ?? "Hello world!";
Assert.NotNull(setting);
Assert.NotEqual(string.Empty, setting);
Assert.NotEqual("Hello world!", setting);
}
private IConfigurationRoot GetConfiguration(string uri)
{
var azureCred = new DefaultAzureCredential();
var chainedCred = new ChainedTokenCredential(azureCred);
var builder = new ConfigurationBuilder();
//The optional:true parameter for AddAzureAppConfiguration does not work, as of AzureAppConfiguration 3.0.1,
//specifically for the KeyVaultReferenceException we're experiencing. However, this would only gracefully not
//load our key vault secrets, not solve the problem we're having with retrieving secrets.
//https://github.com/Azure/AppConfiguration-DotnetProvider/issues/136
builder.AddAzureAppConfiguration(options =>
options.Connect(new Uri(uri), chainedCred), optional: true);
var config = builder.Build();
return config;
}
}
}
Packages I have included so far:
Azure.Identity -v 1.1.1
Microsoft.Azure.KeyVault -v 3.0.5
Microsoft.Azure.Services.AppAuthentication -v 1.5.0
Microsoft.Extensions.Configuration.AzureAppConfiguration -v 3.0.1
Microsoft.Extensions.Configuration.AzureKeyVault -v 3.1.5
Here's what I get when I run the test:
WebApi.Test.Integration.Settings.SettingsTests.SettingsRequest_ReturnsValidSettings
Source: SettingsTests.cs
Duration: 5 sec
Message:
Microsoft.Extensions.Configuration.AzureAppConfiguration.KeyVaultReferenceException : No key vault credential configured and no matching secret client could be found.. ErrorCode:, Key:my-keyvaultsecretvalue-v1, Label:, Etag:xxxxxxxxxxxxxxxxxxxxxxxxx, SecretIdentifier:https://my.keyvault.url.net/secrets/my-keyvaultsecretvalue-v1
---- System.UnauthorizedAccessException : No key vault credential configured and no matching secret client could be found.
Stack Trace:
AzureKeyVaultKeyValueAdapter.ProcessKeyValue(ConfigurationSetting setting, CancellationToken cancellationToken)
AzureAppConfigurationProvider.ProcessAdapters(ConfigurationSetting setting, CancellationToken cancellationToken)
AzureAppConfigurationProvider.SetData(IDictionary`2 data, CancellationToken cancellationToken)
AzureAppConfigurationProvider.LoadAll(Boolean ignoreFailures)
AzureAppConfigurationProvider.Load()
ConfigurationRoot.ctor(IList`1 providers)
ConfigurationBuilder.Build()
SettingsTests.GetConfiguration(String uri) line 91
SettingsTests.SettingsRequest_ReturnsValidSettings() line 60
----- Inner Stack Trace -----
AzureKeyVaultSecretProvider.GetSecretValue(Uri secretUri, CancellationToken cancellationToken)
AzureKeyVaultKeyValueAdapter.ProcessKeyValue(ConfigurationSetting setting, CancellationToken cancellationToken)
Key Vault access is not being configured.
Try calling:
builder.AddAzureAppConfiguration(options =>
{
options.Connect(new Uri(uri), chainedCred);
options.ConfigureKeyVault(kv => kv.SetCredential(chainedCred));
}, optional: true);
chainedCred
needs to be for a principal that has access to the referenced Key Vault.
Or, if the reason that you haven't configured Key Vault is because you do not want the secrets, then the AzureAppConfiguration options will need to be set up so that only settings which do not reference Key Vault are queried.