Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Hosted-services / Azure

How to: Implement Azure Key Vault in Legacy WCF Services using .NET Standard Library, .NET, C#, Azure, WCF, Architect, Design, Dev

2.33/5 (2 votes)
4 Oct 2019CPOL1 min read 4.5K  
WCF Key vault implementation using .NET Standard

Introduction

This tip will showcase how you can implement Azure key vault in legacy WCF services which involves storing plain text passwords, connection string or encrypted but not fully secure.

Background

ASP.NET Core advanced features are well supported for backward compatibility scenarios atleast for the important ones. For example, I was awestruck to see there were no or very limited articles around how to implement the key vault for old WCF based service endpoint.

.netstandard library was there to my rescue. I explored a bit and found it easy to get this implemented and it works very well.

Using the Code

Install the below .netstandard supportable nuget packages in your WCF projects, I installed v2.1.0 as I did not upgrade my project yet.

  • Microsoft.Extensions.Configuration.AzureKeyVault
  • Microsoft.Extensions.Configuration.Json

Add an appsettings.json to the root of the solution structure as below:

appsettings.json File Structure

JavaScript
{
  "AzureKeyVaultSettings": {
      "Credentials": {
         "UserName": "admin",
         "Password": "admin"
    }
  }
}

Design

Design your implementation based on your requirements, in my case, I had to call the key vault in multiple endpoints, hence as per DRY, I created a component based approach using Abstraction.

Here is my abstract class:

JavaScript
namespace WCF.Common 
{
using Microsoft.Extensions.Configuration.AzureKeyVault;
using System.Configuration;
using System.Web.Hosting;

    /// <summary>
    /// This Abstract Class will provide common functionality 
    /// to be used across all required clients
    /// </summary>
    public  abstract class AbstractCommon
    {
        #region Variables-Properties

        protected IConfiguration iconfiguration;
        public abstract IConfiguration Configuration { get; set; }

        #endregion

        #region Constructors

        protected AbstractCommon()
        {
            var azureServiceTokenProvider = new AzureServiceTokenProvider();

            var keyVaultClient = new KeyVaultClient(
              new KeyVaultClient.AuthenticationCallback(
                azureServiceTokenProvider.KeyVaultTokenCallback)
              );

        **//ConfigurationManager.AppSettings["KeyVaultName"]-- 
            I read from web.config just //for the key vault name**.
            iconfiguration = new ConfigurationBuilder()
                 .SetBasePath(HostingEnvironment.ApplicationPhysicalPath)
                      .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
             .AddAzureKeyVault(ConfigurationManager.AppSettings["KeyVaultName"], 
                               keyVaultClient, new DefaultKeyVaultSecretManager())
             .Build();  

            Configuration = iconfiguration;
        }
        #endregion
    }
}

Finally, I implement in the client classes which is my service class.

JavaScript
public class CRMProxyService : AbstractCommon, ICRMProxyService
    {
        #region Variables
       
        private string userName;
        private string password;
        #endregion

        #region Abstract Properties
        public override IConfiguration Configuration
        {
            get
            {
                return iconfiguration;
            }

            set
            {
                iconfiguration = value;
            }
        }
        #endregion

        #region Constructors and Init Methods

public CRMProxyService()
        {           
            InitialiseHelper();
        }

        private void InitialiseHelper()
        {           
                try
                {
                    string crmServiceURL = ConfigurationManager.AppSettings["CrmServiceURL"];

                    try
                    {
                        var passWord = 
                            Configuration["AzureKeyVaultSettings:Credentials:Password"];

                        userName = Configuration["AzureKeyVaultSettings:Credentials:UserName"];
                        password = Configuration[passWord];// accessing as a key value pair
                    }
                    catch(Exception ex)
                    {
                        throw new AccessCrmException("Error accessing Azure Key Vault", ex);
                    }

                    string domain = ConfigurationManager.AppSettings["Domain"];

                    crmSdkHelper = new CrmSdkHelper
                    (crmServiceURL, userName, password, domain);
                }
                catch (Exception ex)
                {
                    throw new AccessCrmException("Error connecting to CRM", ex);
                }
            }
        }
 #endregion

That’s It! Implement across all client functionality wherever you are required to consume secrets from key vaults as based on the requirement and scenario.

Points of Interest

  • Azure SaaS, PaaS, IaaS, Office 365, .NET Core & SharePoint

History

  • Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)