Quote of the Day

more Quotes

Categories

Buy me a coffee

Secure app settings in ASP.NET Core 2

Published August 20, 2018 in ASP.NET core , security - 0 Comments

Update: This post shows how to authenticate to azure key vault using app id/secret. However, this approach is less secure than using managed identity for azure resource and certificate for non-azure resource to grant the resource access to the key vault. For production environment, you should definitely consider using azure managed identity or certificate to authenticate and access azure key vault from your resource. Checkout my other post for more details.

In this blog post, I’ll show you the steps on  how to keep the credentials out of the source code of an ASP.NET Core app using Azure Key Vault.

If you want some convincing examples why leaving secrets in the source code is bad, check out this post. 

I assume you have some familiarity with developing an ASP.NET core 2 app. You also need an Azure subscription to register your application in Azure Active Directory and create an Azure key vault.

Basically the process involves these steps:

  1. Register your application in AAD and generate app secret.
  2. Set application id/secret using environment variables.
  3. Create an Azure Key Vault.
  4. Grant your app access to your key vault using access control.
  5. Specify URL to your vault in app settings.
  6. Load app id and secret from environment variables.
  7. Read secrets from Azure Key Vault.

Checkout the sample app for this post from my Git repo.

1. Register your app in AAD

Upon registering the application, you can generate an app id and secret which identify the application. Your app needs to authenticate using the application id and secret when accessing the vault.

  1. In Azure Portal, Select “Azure Active Directory” under “Favorites” menu on the left.
  2. Select “App registrations”.
  3. Click “New application registration”.
  4. Enter the name for your application. Pick the name carefully as you may not change it after creation.
  5. Select “Web app/api” for Application type.
  6. Enter a URL for Sign-on URL. The URL does not matter for our purpose since we don’t use the app for sign in. You can enter anything such as “https://loopback.com”
  7. Click “Create”
  8. Select “Settings”.
  9. Click on “Keys” under “Settings”.
  10. Create a secret by filling out key descriptions. As advised by the system, take note of the secret since you won’t be able to retrieve it again.

2. Set app id/secret using environment variables

Your app needs access to the app id and secret to authenticate with Azure and access the vault.



When setting the variables,  use double underscore to separate sections. As per Microsoft’s documentation,

For hierarchical config values specified in environment variables, a colon (:) may not work on all platforms. Double underscore (__) is supported by all platforms.

Other options exist. For instance, you may want to use Secret Manager to store the app credentials under the user account which the app runs. You may also want to Data Protection Apis to encrypt the app id/secret and decrypt them in the app for extra protection.

3. Create Azure Key Vault

Follow these steps to create the vault via the portal:

  1. In Azure Portal, click “Create a resource” on top left.
  2. In the search box, enter “Key Vault”.
  3. Select “Key Vault” from the result and click “Create”.
  4. Fill out the form to create the vault.
  5. Click “Create”.

When creating an Azure Key Vault, pay attention to the things below:

  1. Name of the key vault (or any resource) must be unique. Pick the name carefully since it is part of the URL to your vault, and you may not edit it after creation.
  2. Similarly, if you elect to create a new resource group, pick the name carefully as you may not able to edit it after creation.
  3. Use separate key vaults for different environments. On creating a key vault, the system generates a key to protect the secrets, and you don’t want to use the same key for different environments.
  4. Decide whether to use HSM – backed keys or software backed keys. As Dan Plastina mentions in this Microsoft blog,
[you] will need to consider the trade-off of having the highest security pattern, one where all crypto happens in the Vault boundary.  Or, go for reduced operational and latency costs often required for effective bulk data protection, where the Key Vault only provides protection of the ‘secret’ used for bulk data protection (most certainly an AES symmetric key).

For more information on the differences between software vs hardware backed keys, check out this post.

4. Grant App access to key vault

To retrieve the secrets from the vault, your app needs to have Get and List permissions.

  1. In Azure portal, go to your Azure Key Vault resource.
  2. Select “Access policies” on the left menu.
  3. Click on “Add New”.
  4. Click on “Select Principle”.
  5. Search for your app in the search bar.
  6.  Click “Select”.
  7. Under Secret Permissions, check “Get” and “List” permissions.
  8. Click “OK”.

5. Specify URL to key vault in appsettings.json

In your appsettings.json file, create a section to store the configurations for accessing your key vault. For example,

{
 "AllowedHosts": "*",
  "Vault":  {
    "Dns": "https://sampleappvault.vault.azure.net/", 
    "ClientId":  "This would get overriden by environment variables.",
    "ClientSecret":  "This would get overriden by environment variables"
  }
}

6. Load app id/secret from environment variables

The tricky part is naming the variables as described in step 2. However, loading the environment variables is straightforward, using the Microsoft.Extensions.Configuration.EnvironmentVariables package.

  1. Add the package from Nuget if needed. You may already have this as a dependency as it is part of the Microsoft.AspNetCore.App package.
  2. Register the provider to load the environment variables. Your configs may look something as below:
public Startup(IHostingEnvironment env)
       {
           var builder = new ConfigurationBuilder()
               .SetBasePath(env.ContentRootPath)
               .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
               .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
           builder.AddEnvironmentVariables("SECURE_APP_");
           Configuration = builder.Build();

       }

One thing to note here is the order of the providers. If two providers define a same configuration key, the ConfigurationBuilder() uses the value from the last provider registered. Since we want to use the ClientId and ClientSecret values from the environment variables, not from the Json file, we need to place the call AddEnvironmentVariables()after the calls to AddJsonFile()

In the code above, I use the prefix “SECURE_APP_” to selectively load the variables for the app. When not using the prefix, the ConfigurationBuilder() loads all the environment variables, and we don’t want this.

7. Read secrets from Azure Key Vault

This is similar to step 6 above. To retrieve values from the vault, you register the Microsoft provided’s provider.

  1. Add the Nuget dependency: Microsoft.Extensions.Configuration.AzureKeyVault.
  2. Register the provider. Continuing from the code snippet above, add these lines:
builder.AddAzureKeyVault(vault: Configuration["Vault:Dns"], clientId: Configuration["Vault:ClientId"], clientSecret: Configuration["Vault:ClientSecret"]);
Configuration = builder.Build();

In the above code, value of Vault:Dns comes from the json file. However, values of Vault:ClientId and Vault:ClientSecret are from the environment variables. The environment variables’ names are as follow: SECURE_APP_Vault__ClientId and SECURE_APP_Vault__ClientSecret.

Remarks

The cost of using Azure Key Vault is insignificant.  As of this writing, it’s about $1.03/month for the premium plan which includes HSM backed keys. The process of creating a key vault and reading secrets from the vault is also not that complex, thanks to the abstractions the libraries provide. If you have access to Azure, you should definitely consider securing your secrets using Key Vault. If you can’t use the cloud for some reasons, you may want to consider the Data Protection APIs which I’ll cover in another post.

It’s not worth the risks to store the app settings in the source code.

Additional Resources 

Tutorial: Configure an Azure web application to read a secret from Key Vault

Get started with Azure Key Vault

Azure Key Vault – Making the cloud safer

Software vs HSM protected keys in Azure Key Vault

Data Protection in ASP.NET core

No comments yet