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
{
"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:
namespace WCF.Common
{
using Microsoft.Extensions.Configuration.AzureKeyVault;
using System.Configuration;
using System.Web.Hosting;
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)
);
**
I read from web.config just
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.
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];
}
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