0

I am using an appsettings files in my Azure Function using a Startup class. In my appsettings files, there are keyvault references. But I cant seem to get it to work as the keyvault references never get replaced by actual strings from the keyvault. What am I doing wrong? My sample uses a client id and secret since I needed to test locally but will get switched out to using the managed identity in Prod.

Startup has following function:

        public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
        {
            try
            {
                FunctionsHostBuilderContext context = builder.GetContext();

                var configurationBuilder = builder.ConfigurationBuilder
                    .SetBasePath(context.ApplicationRootPath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
                    .AddEnvironmentVariables()
                    .Build();

                builder.ConfigurationBuilder
                    .SetBasePath(context.ApplicationRootPath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
                    .AddEnvironmentVariables()
                    .AddAzureKeyVault(configurationBuilder["vaultUri"], "<clientid>", "<clientsecret>");
            } catch (Exception e)
            {
                throw new Exception(e.StackTrace + " " + e.Message);
            }
        }

However the configuration object still has the keyvault reference strings even after using the "AddAzureKeyVault" method. What am I doing wrong?

My appsettings file looks like this

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  },
  "MySection": {
    "MyUrl": "@Microsoft.KeyVault(SecretUri=https://mykv.vault.azure.net/secrets/MySection-MyUrl/)"
  },
  "vaultUri": "https://mykv.vault.azure.net/"
}

Shouldnt the MyUrl key get updated with actual values from the keyvault?

UPDATE: So I realized I was using the wrong nuget pacakge for Keyvault. So instead switched to Azure.Extensions.AspNetCore.Configuration.Secrets. Code is now changed to using Managed Identity. But somehow the values still dont update :(

        public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
        {
            try
            {
                FunctionsHostBuilderContext context = builder.GetContext();

                var configurationBuilder = builder.ConfigurationBuilder
                    .SetBasePath(context.ApplicationRootPath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
                    .AddEnvironmentVariables()
                    .Build();

                string userAssignedClientId = configurationBuilder["userAssignedClientId"];
                var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId });

                var options = new AzureKeyVaultConfigurationOptions { ReloadInterval = TimeSpan.FromHours(24) };

                builder.ConfigurationBuilder
                    .SetBasePath(context.ApplicationRootPath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
                    .AddAzureKeyVault(new Uri(configurationBuilder["vaultUri"]), credential, options)
                    .Build();
            } catch (Exception e)
            {
                throw new Exception(e.StackTrace + " " + e.Message);
            }
        }
1
  • I think I figured out the issue. The keyname in the Keyvault has to be of a specific format: <SectionName>--<KeyName>. So in my case the name needed to be MySection--MyUrl. Then it automaps. How convoluted and painful! Spent 10 hours today on this. Sheesh!! Commented Nov 24, 2022 at 6:45

1 Answer 1

0

This is because you are:

  1. Not using app setting keyvault references correctly -- they must be set in your App Service's app configuration section, not in a configuration file.
  2. Trying to combine app settings references with direct application keyvault integration. You only need one of the two, not both.

Basically, remove this:

  "MySection": {
    "MyUrl": "@Microsoft.KeyVault(SecretUri=https://mykv.vault.azure.net/secrets/MySection-MyUrl/)"
  }

It's not loading the secret from keyvault because you're already defining the value.

Also, for what it's worth, this code is not doing anything useful and should be removed:

catch (Exception e)
{
    throw new Exception(e.StackTrace + " " + e.Message);
}

The exception you're catching already has a stack trace and message. You're not accomplishing anything slightly reformatting the contents and throwing a new exception.

Sign up to request clarification or add additional context in comments.

1 Comment

Agreed on the Exception part. That was just my desperate attempt to catch anything that might have been flying under the radar. But was not needed in the code. On the first point though, I dont think it matters that there is a value entered. I was able to get it working using the right format MySection--MyUrl. Doing that mapped the values as expected. But you are right that the actual @Microsoft.KeyVaultblabblah could have been left out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.