1

I have the following approach to connect to the key vault in my code:

public static class ConfigurationBuilderExtension
{
    public static IConfigurationBuilder AddKeyVaultconfiguration(this IConfigurationBuilder builder)
    {
        var config = builder.Build();

        string name = config["KeyVault:Name"];
        string clientId = config["KeyVault:ClientId"];
        string clientSecret = config["KeyVault:ClientSecret"];

        Verify.NotNullOrEmpty(name, nameof(name));
        Verify.NotNullOrEmpty(name, nameof(clientId));
        Verify.NotNullOrEmpty(name, nameof(clientSecret));

        builder.AddAzureKeyVault($"https://{name}.vault.azure.net/", clientId, clientSecret);

        return builder;
    }
}

To run this locally, I just adding the user secrets to the project:

{
  "KeyVault": {
    "Name": "brajzorekeyvault",
    "ClientId": "xxxx",
    "ClientSecret": "xxxx"
  }
}

This works locally.

However, how do I use this approach when I publish this to a app service in Azure? I must in somehow inject the name, clientId and clientSecret? But I don't know which is the best practice approach to do this? Should I create a variable group in Azure devops that consists of these values, and then use these in the piplines?

Bryan
  • 3,421
  • 8
  • 37
  • 77
  • 2
    You should use a managed identity to access the key vault inside the web app to avoid having to inject a secret. See https://learn.microsoft.com/en-us/azure/key-vault/general/tutorial-net-create-vault-azure-web-app – Peter Bons Mar 09 '21 at 09:02
  • @PeterBons: if I add code for managed identity, how can i access the key vault locally? – Bryan Mar 09 '21 at 09:08
  • @PeterBons: If I add code to use managed identity, like in the link you provided, it will not work locally? The reason that i use user secrets is because I want to be able to run my project locally and still get access to the key vault. – Bryan Mar 09 '21 at 09:18
  • 1
    You can, see the explaination [here](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/identity/Azure.Identity/README.md). You can link an account in VS that will be used to authenticate against the key vault. – Peter Bons Mar 09 '21 at 09:27
  • And is this the best practices when working to App services and keyvault? – Bryan Mar 09 '21 at 09:29
  • In App Services you can also add the necessary parameters as "environment variables". – Tore Nestenius Mar 09 '21 at 09:38
  • 2
    @Bryan yes it is best practices, in fact you won't see any offical docs about connecting using the client secret withouth at least a warning to use managed identities – Peter Bons Mar 09 '21 at 09:42
  • @PeterBons Could you please post your suggestions as a solution? – Jim Xu Mar 10 '21 at 01:22
  • @JimXu done :-) – Peter Bons Mar 10 '21 at 07:18

2 Answers2

3

You should use a managed identity to access the key vault inside the web app to avoid having to inject a secret. See this tutorial

For local development you can link an account in VS that will be used to authenticate against the key vault. See the docs

Using managed identities is best practices, in fact you won't see any offical docs about connecting using the client secret withouth at least a warning to use managed identities.

Peter Bons
  • 26,826
  • 4
  • 50
  • 74
  • We're debating this at my work right now. I can support using managed identities when running locally, but what about when we're running as an Azure app service? Using a service account is an option I guess, but that's not very secure. It seems to me that using a certificate is less messy there. Any thoughts on that? – DeannaD Sep 27 '22 at 21:08
  • @DeannaD it's very easy, and not at all messy, to use a managed identity associated with an azure app service. – Vince Bowdren Oct 05 '22 at 15:09
1

When we are working with PAAS (Most of resources are PAAS in Azure like App service and KeyVault) in Azure. Most of the time, We do not need to write code or write very less code to access them such as in this case. Do not need to provide any detail like connection string or other details to access key vault in app service, Just do little configuration in azure portal and direct get secret from key vault.

In Azure , they are resources in same resource group which can communicate to each other or authenticate or authorize by just adding object id of app service to keyvault "Access policies". All the headache is on azure of validation. It is very easy, secure and good practice.

Steps are as Follows

  1. Enable Managed Service Identity for your Web App/App Service

    a. Select "Identity" from the left-side menu in the Azure Web App/App Service.

    b. In the System-assigned tab, Change the "Status" toggle to "On".

    c. After a few seconds, Object ID will be available then copy the "Object ID".

enter image description here

  1. Authorize the Web App/App Service to access Your Key Vault

    a. Select "Access policies" from the "Key Vault" screen.

    b. Click "Add Access Policy".

    c. Provide the "Get" and "List" permissions.

    d. In the “Select a Principal” option, specify the value for the "Object ID" you copied earlier for the Azure Web App/App Service.

    e. Paste, search and then select it from the list.

    f. Click "Add".

    g. Click "Save" to persist the changes and complete the process.

Provide Permissions

enter image description here

Copy object Id

enter image description here

  1. Read Azure Key Vault Secrets in .NET Core

    a. Install the NuGet Packages

    You may install these packages in one of two ways: Either via the NuGet Package Manager integrated into the Visual Studio 2019 IDE or by running the following command(s) in the Package Manager Console:

    Install-Package Microsoft.Extensions.Azure and Install-Package Azure.Security.KeyVault.Secrets

Note :- In My case , I did not need to install these packages.

b. Access Secrets from AzureKeyVault

  1. Specify the Vault Uri in AppSettings :- Create a section named "KeyVault" in the appsettings.json file and specify a key named "VaultUri" in there as shown below.

appsettings.Development.json

{
   "SecretName": "xyz"
}

appsettings.OtherEnv.json

       "KeyVault": {
         "VaultUri": "https://yourkeyvaulturl.vault.azure.net/"
         }
  1. Create KeyVaultManagement class
public class KeyVaultManagement
   {
      private readonly IConfiguration _config;

      public KeyVaultManagement(IConfiguration config)
      {
        _config= config;
      }

      public SecretClient SecretClient
      {
        get
         {
            return new SecretClient(
                             new Uri($"{this._config["KeyVault:VaultUri"]}"),
                             new DefaultAzureCredential()) ;
         }
       }
  }
  1. Write the below code in Program.cs
.ConfigureAppConfiguration((context, config) =>
{
   var builtConfig = config.Build();
   if (!context.HostingEnvironment.IsDevelopment())
   {
     config.AddAzureKeyVault(new KeyVaultManagement(builtConfig).SecretClient, new KeyVaultSecretManager());
   }
});
  1. Write the below where need to fetch secret.
var valueofSecret = configuration["SecretName"];

configuration is IConfiguration

Documentation of Microsoft for Access Policy of Azure Keyvault

IF YOUR APPLICATION IS NOT APP SERVICE OR IT IS DEVELOPED IN .NET FRAMEWORK

Then Implement KEYVAULT using Certificate

  1. Install Same Nuget Packages

  2. Write the below code in Program.cs. Might need to add package or namespace to use certificate classes

.ConfigureAppConfiguration((context, config) =>
{
   var root = config.Build();
   var KeyVaultName = root["KeyVaultName"];
   var Uri = new Uri($"https://{KeyVaultName}.vault.azure.net/");
   var x509Certifcate = CertifcateHelper.GetCertificate(root["Thumprint"],"KeyVaultCertificate");
   
     config.AddAzureKeyVault(Uri , new ClientCertificateCredential(root["ClientTenantId"], root["ClientAppId"], x509Certifcate));
});

  1. Add the below lines in APPSetting

appsettings.Development.json

{
   "KeyVaultName": "keyvalutname",
   "ClientTenantId": "Get from azure and paste here",
   "ClientAppId": "Get from azure and paste here",
   "Thumbprint": "Get from keyvalut certificate in azure and paste here";
}
  1. Write the below where need to fetch secret.
var valueofSecret = configuration["SecretName"];
Pradeep Kumar
  • 1,193
  • 1
  • 9
  • 21