I’m trying to use Azure Key Vault for storing my web api connection strings for Entity Framework. Ideally I’d like to avoid coupling the key vault nuget packages with my data access code. My dbContext class has two constructors:
public MyDbContext() : base("DefaultConnection")
{ . . . }
public MyDbContext(string connectionString) : base(connectionString)
{ . . . }
My code makes use of the parameterless constructor which gets the connection string from the web config. There are some places where I instantiate a new MyDbContext object, which prohibits a solution using injection.
The route I took is to set a static property on my dbcontext with a connection string locator:
public interface IConnectionStringLocator
{ string Get(); }
public class DefaultConnectionStringLocator : IConnectionStringLocator
{
public string Get()
{
return "DefaultConnection";
}
}
public static IConnectionStringLocator ConnectionStringLocator { get; set; } =
new DefaultConnectionStringLocator();
My web api project has the nuget packages for retrieving the key vault secrets. So in my Global.asax file I have this:
protected void Application_Start()
{
MyDbContext.ConnectionStringLocator = new ConnectionStringLocator("DefaultConnection");
}
public class ConnectionStringLocator : IConnectionStringLocator
{
private readonly string _connectionStringName;
public ConnectionStringLocator(string connectionStringName)
{
this._connectionStringName = connectionStringName;
}
public string Get()
{
var keyVaultName = WebConfigurationManager.AppSettings.Get("KeyVaultName");
if (keyVaultName == "develop")
return _connectionStringName;
else
{
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient =
new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var defaultConnectionSecret =
keyVaultClient.GetSecretAsync($"https://{keyVaultName}.vault.azure.net/secrets/{this._connectionStringName}");
return defaultConnectionSecret.Result.Value;
}
}
}
I published this and it works, but it doesn't "feel" right.
Another option would be to follow this article https://blog.falafel.com/keeping-secrets-with-azure-key-vault/ but it would require me to couple the KeyVault API packages with my data access.
I'm looking for feedback and direction. I should add that the reason I want to use key vault is because it will allow me to have azure administrators who can view the application settings online without having access to the sql database via connection string.
KeyVault resource with the new MSI implementation: https://github.com/Azure-Samples/app-service-msi-keyvault-dotnet/