azure-sdk-for-net: [BUG] Using Azure AppConfiguration and KeyVault as Configuration failes

Library name and version

Azure.Identity 1.5.0

Describe the bug

When using the libraries Microsoft.Azure.AppConfiguration.AspNetCore (4.5.1) and Azure.Extensions.AspNetCore.Configuration.Secrets (1.2.1) to built an .NET 6.0 Web Api with Azure App Configuration and Azure Key Vault as configuration providers. The Application startup failes either with

  • Access Token retrieval for Azure Key Vault failes, because the DefaultAzureCredential() instance is requesting a Token with scope for the whole Key Vault URI instead of only https://vault.azure.net/.
  • Access Token retrieval for the App Configuration failes with an HTTP 400 Bad Request error.

Expected behavior

Using both Configuration Providers should be working with the DefaultAzureCredential.

Actual behavior

Getting described errors in an Azure App Service Environment

Reproduction Steps

public static IHostBuilder ConfigureMyApplication(this IHostBuilder builder, string appName, TokenCredential? credential = null) => builder.ConfigureAppConfiguration((_, config) =>
  {
    config
      .AddEnvironmentVariables()
      .AddJsonFile("appsettings.json", optional: true)
      .AddInMemoryCollection(new Dictionary<string, string>()
      {
        [AppName] = appName
      });

    if (credential != null)
    {
      var built = config.Build();
      var endPoint = built[AppConfig];
      if (!string.IsNullOrEmpty(endPoint) && Uri.TryCreate(endPoint, UriKind.Absolute, out Uri? endpointUri))
      {
        config.AddAzureAppConfiguration(appCfg =>
          appCfg
            .Connect(endpointUri, credential)
            .Select(Microsoft.Extensions.Configuration.AzureAppConfiguration.KeyFilter.Any)
        );
      }

      endPoint = built[KeyVault];
      if (!string.IsNullOrEmpty(endPoint) && Uri.TryCreate(endPoint, UriKind.Absolute, out endpointUri))
      {
        var secretClient = new SecretClient(endpointUri, credential);
        config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
      }
    }
  });

Environment

  • Azure App Service Linux
  • .NET 6.0
  • System Assigned Managed Identity

For details see Support Case 2111300050001183

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 20 (11 by maintainers)

Commits related to this issue

Most upvoted comments

I’m glad you found it! I see where the variable was getting captured by reference and resolved later. Sorry I failed to see that initially, too. Good find!

As for why you needed to remove the dependency, I’m not sure. In one of my repro attempts I merely commented out any App Configuration-related code but kept he references the same. IF they don’t get called, they shouldn’t interfere.

I’ll go ahead and close this. We have talked about validating endpoints in the past but decided it was a slippery slope, causing problems when we add new cloud environments, for example, as well as support against Azure Stack which would have a entirely customer-driven endpoint domains. But this is a good lesson in watching out for reference captures in delegate-driven configuration I’ll pass along so we’ll remember to watch for it again if we see behavior like this. I suspected a static cache somewhere but wasn’t finding anything like that in the suspected code paths.

I am accessing some const string properties of the Program class (like AppName) - nothing else.

But you pointed on something… that the scope and the exception is coming from the App Config and that for the app config the scope is the complete url… and after trying that, I am totally sorry - this is a terrible mistake from my side.

For better understanding what is happening here: I am creating an Uri?-typed variable to hold the parsed Uri for the App Configuration which I am reusing later for the Key Vault. Despite it looks like it is stored and executed, the code is executed when the Configuration Provider is build, which means that the App Configuration config provider reads the variable endpoint after it is reused for holding the Key Vault endpoint. That is the reason, the App Configuration tries to get a token for the scope for the Key Vault endpoint.

Thanks for the offer to getting in direct contact. I just dropped you a message on Teams while I was working on the fix, to let you know I am still working on it today.

The only two things I do not understand are

  • that my previous test needed to remove the dependency to the App Config SDK (but maybe this was a timing issue… linux app service is a bit tricky with restarts sometimes)
  • that my local development setup worked… but maybe I missed something in the configuration and had the client secret from the key vault anywhere else (maybe user secrets). Unfortunately I had a windows reinstallation and can no longer clarify that.

Shall I close the issue or is this something that could be added as a feature to the App Configuration Library, that checks the validity of the given endpoint?