How to setup Azure App Configuration and Key Vault in a .Net Core project
This is a basic "how-to document" blog on configuring Azure App Configuration and Key Vault in a .Net Core project. Topics covered:
- Setup Azure App Configuration
- Setup Azure Key Vault
- Configuring a .Net Core project with sample code
- Setting up access policies in Key Vault
- Authenticating your application code to fetch secrets from Key Vault
Disclaimer: Probably, you could have seen this how-to information in the MSFT official documentation. But this blog will give you the curated steps removing all the clutters.
Prerequisites
Make sure you have access to do the below in Azure,
- Create Azure App Configuration
- Create Azure Key Vault
- Edit Access policy in the newly created Key Vault
- Enable System assigned managed identity for the Application hosted in Azure
- Register an app in Azure Active Directory (optional)
Intro on the said Azure jargons
Azure App Configuration lets you maintain the config details of your app in Azure so that your app can be free of any environment dependency. It has labels that can be used to maintain values of different environments for a single config property.
Key Vault is a resource in Azure to store secret information that can be accessed by your apps through managed identities or service principal authentication.
Managed Identities are used to authenticate across azure resources through an identity thereby eliminating the need to manage credentials. In this blog, we will use the System-assigned managed identity of an Azure App Service which we will enable in it to access the secrets in a Key Vault.
Create Azure App Configuration
Follow this to create a new Azure App Configuration resource and add your config properties to the store.
Configuration Explorer
under Operations
, is where the config properties can be seen and edited.
Every key has options to add more values with different labels which can be used for different environments. Here is a screenshot of the Configuration Explorer displaying 2 values for a single key with one having a label and another empty.
To retrieve these values in an application, Connection String
that is uniquely generated under Access Keys
is needed. Get the connection string from this page which will be used in our application to connect to the App Configuration store.
Create Azure Key Vault
Follow this to create a new Azure Key Vault resource. For this blog, we will look into secrets alone to store our passwords/client secrets. Check this on how to create a secret in the Key Vault.
Retrieving secrets' value from the Key Vault can be done using the Azure.Identity
package. But if you want to load the secrets in the ConfigurationSection
, then there is a way in the ConfigurationBuilder
to include both App Configuration key-values and Key Vault secrets.
To do this, the secrets are to be referenced in the App Configuration as a new key-value. Check this article on how to add a KV reference in the App Configuration.
App Configuration will use the identity that is used to load itself for accessing the secrets in the Key Vault. This is something we will set up in the next steps. As of now, your App Configuration should look something like the below screenshot,
Configuring a .Net Core project with sample code
Here is the sample app in GitHub.
github.com/venbacodes/AppConfigKVSample
To connect with the Azure App Configuration, you will need the package Microsoft.Extensions.Configuration.AzureAppConfiguration
which has the extension method AddAzureAppConfiguration
for the ConfigurationBuilder
. This extension method will get the Connection String of the App Configuration and can also configure the Key Vault using the ConfigureKeyVault
method in its options.
builder.Host.ConfigureAppConfiguration((webHostBuilderContext, config) =>
{
var isDevelopment = webHostBuilderContext.HostingEnvironment.IsDevelopment();
var environment = webHostBuilderContext.HostingEnvironment.EnvironmentName.ToLower();
config
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{webHostBuilderContext.HostingEnvironment.EnvironmentName}.json", true, true);
var settings = config.Build();
var appConfigConnectionString = settings.GetSection(AppConfigConnectionStringSection);
if (appConfigConnectionString != null && !string.IsNullOrWhiteSpace(appConfigConnectionString.Value))
{
config.AddAzureAppConfiguration(options =>
{
options
.Connect(appConfigConnectionString.Value)
.ConfigureKeyVault(kv =>
{
if (isDevelopment)
{
///You WON'T need this if you are logged into Visual Studio and your account has been setup
///with access policy in the Key Vault you are trying to connect. You can just use the DefaultAzureCredential
///that is set in the else part.
var cred = new ClientSecretCredential(
settings.GetSection("DevCredential:TenantId").Value,
settings.GetSection("DevCredential:ClientId").Value,
settings.GetSection("DevCredential:ClientSecret").Value);
kv.SetCredential(cred);
}
else
{
kv.SetCredential(new DefaultAzureCredential());
}
})
.Select(KeyFilter.Any, LabelFilter.Null)
.Select(KeyFilter.Any, environment ?? LabelFilter.Null);
});
}
});
OK, here are the explanations on the above code,
This reads the app config connection string we have in our appsettings.json file
var appConfigConnectionString = settings.GetSection(AppConfigConnectionStringSection);
We will now use this connection string in the AddAzureAppConfiguration method,
options
.Connect(appConfigConnectionString.Value)
Now, we are configuring the Key Vault in the config builder to load its secrets also as configuration into the application's Configuration.
.ConfigureKeyVault(kv => {
///Code removed for simplicity
})
We are trying to connect to the Key Vault using our registered identity in AD for development and the default credential when not in development. We will see about this more in the next section.
While getting the data from the app config, we are actually filtering the keys and values based on the environment.
.Select(KeyFilter.Any, LabelFilter.Null)
.Select(KeyFilter.Any, environment ?? LabelFilter.Null)
The above code tries to filter the values based on the label filter. Actually, this will include all keys without any labels and all keys with the specified label and finally will overwrite the values in the first filter. The order of filters is important here.
Access Policies in Key Vault
Access policies section in the Key Vault is where we will assign permissions for applications and users using the managed identities that are formed from the Azure Active Directory.
Here is a screenshot of this section,
Azure AD Identities
You can either use an Azure App Services' System-assigned managed identity or your azure account's identity to connect to the Key Vault. I recommend using your own azure account to authenticate and connect to the Key Vault by logging into Visual Studio and using kv.SetCredential(new DefaultAzureCredential());
If you don't want to use your azure account, there is another possibility to register an App in the Azure AD and use its identity in this Access Policy.
App Registration in Azure AD
Follow this to register an application in the Azure AD and get the below details from it to set the credentials while configuring the KV.
TenantId - This will be the common id for your azure tenant
ClientId - This will be the unique id for the registered app
ClientSecret - You have to create this secret after registering the app. This is covered in the below link
docs.microsoft.com/en-us/azure/active-direc..
Azure App Service System Assigned Managed Identity
To use the Azure App Services' identity, you would have to enable it as like below,
Once this is done, kv.SetCredential(new DefaultAzureCredential());
will automatically use the app's identity and try to authenticate and get values from the KV.
To complete a successful authentication, add this newly registered app in the access policy section under the KV as a principal and give access to read secrets.
Finally seeing the values from the app config
After completing the above steps, you can now access the Configuration with the key
name ACDemo
which I used in the App Configuration. For this demo, I have read the key during startup and added it to a singleton service so that I can get them injected in all places.
var acDemo = new ACDemo();
builder.Configuration.Bind("ACDemo", acDemo);
builder.Services.AddSingleton(acDemo);