Thursday, October 1, 2020

Azure Functions: Consuming Configuration Data from Azure App Configuration and Azure Key Vault

Azure App Configuration is a managed service to centrally manage application and feature settings. One of the nicest things about AAC is, it can consume secrets from AKV. In this post, let's see how we can consume Configuration Data from Azure App Configuration (AAC) and Azure Key Vault (AKV).

Before starting off, I am assuming that you have an understanding of how to set up AAC and AKV (here is a post I wrote a couple of months back about creating AAC: ASP.NET Core Application Reading Configuration from Azure App Configuration). And I am assuming you know how to set up dependency injection using FunctionsStartup in an Azure Function App (If you want to refresh your memories, may be this can help Dependency Injection in Azure Functions).

So consider that we have an AAC configured with AKV secrets (Here I have only 1 AKV Reference).

Azure App Configuration with AKV References
So consider I have an Azure Function App with DI setup.

Like 10 days back, Microsoft.Azure.Functions.Extensions version: 1.1.0 was released and with that, one of the new features that got available is Configuration source customization. Basically, that is, in the Startup class, now you can override the ConfigureAppConfiguration.

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

    builder.ConfigurationBuilder
        .AddJsonFile(Path.Combine(context.ApplicationRootPath, "appsettings.json"), optional: true, reloadOnChange: false)
        .AddJsonFile(Path.Combine(context.ApplicationRootPath, $"appsettings.{context.EnvironmentName}.json"), optional: true, reloadOnChange: false)
        .AddEnvironmentVariables();

    var aacEndpoint = Environment.GetEnvironmentVariable("AzureAppConfiguration_BaseUrl");
    if (!string.IsNullOrEmpty(aacEndpoint))
    {
        builder.ConfigurationBuilder
            .AddAzureAppConfiguration(options =>
            {
                var tokenCredential = new Azure.Identity.DefaultAzureCredential();
                options
                    .Connect(new Uri(aacEndpoint), tokenCredential)
                    .Select(KeyFilter.Any, LabelFilter.Null)
                    .Select(KeyFilter.Any, Environment.GetEnvironmentVariable("AzureAppConfiguration_Label"))
                    .ConfigureKeyVault(kv =>
                    {
                        kv.SetCredential(tokenCredential);
                    });
            });
    }
}

So in the above the code example, I have added appsettings.json, appsettings.{environment}.json as configuration sources (yes, you can do that). And if I have an AAC endpoint (something like https://something.azconfig.io), I have added AAC as a configuration source. You can notice that, instead of using AAC connection string, I have used the Connect overload that uses AAC endpoint Uri and TokenCredential. For TokenCredential, I have used DefaultAzureCredentialDefaultAzureCredential provides a default TokenCredential authentication flow for applications that will be deployed to Azure and it will be trying different credential types on a specific order (please go through the above link to find about the order).

Now let's have a look at how things are going to work on Local Development Environment using Visual Studio and when deployed to Azure (I am only covering running in Azure scenario here in this post).

Local Development Environment using Visual Studio

So in the local development environment using Visual Studio, for you to consume AAC configured with an AKV, you need to do the following steps.

  • Make sure, you have the latest Azure CLI installed
  • Correct account is set from Visual Studio: Tools -> Options -> Azure Service Authentication
    • This account needs to be given App Configuration Data Reader role in AAC (through Access control (IAM) in AAC)
    • In AKV, an access policy is defined for this Account
Tools -> Options -> Azure Service Authentication
AAC - IAM - App Configuration Data Reader role
AKV - Access Policies
Note: In AKV, here in my case, I have all the permissions. You might need to give only Get like I have given for Manage Identities above me.
  • For the Azure CLI logged in account, if you have access to multiple subscriptions in your tenant or in different tenants, make sure the subscription where your AAC lives, is selected as the default subscription.
// show the default subscription
az account show 

// list all the subscriptions
az account list;

//set default subscription
az account set --subscription [subscription-id]

With the above steps, you should be able to consume AAC with AKV when your Function App is running locally in Visual Studio. 

Note: It's better not to consume AAC when running locally, usually what I do is wrap adding AAC configuration in a #if condition or environment check condition and use AAC only in production. For the local development environment, we can have the configuration inside appsettings.Development.json or something like that.

Deployed to Azure

When the Azure Function app is deployed to Azure, you can use either System Assigned Managed Identity or User Assigned Managed Identity

System Assigned Managed Identity

For System Assigned Managed Identity, you can have a look at this post Consume Secrets in an Azure Key Vault from an Azure Function App on how you can setup System Assigned Managed Identity in Azure Function App. Then in addition to those steps in that post, you need to give your Managed Identity, App Configuration Data Reader role in your AAC (like we did for Visual Studio Account).

User Assigned Managed Identity

For User Assigned Managed Identity, you need to create an User Assigned Managed Identity in Azure which is another managed service.

Create User Assigned Managed Identity
Then inside your Function App, you need to assign that managed identity to the function app. You can do this by, going to Identity -> User Assigned -> Add.


Then again like previous scenarios, you need to give that identity App Configuration Data Reader role in your AAC and define an access policy in AKV.

And in the Configuration add an app setting, AZURE_CLIENT_ID with the value of ClientId in the created Managed Identity.

So that's it.

Hope this helps.

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment