Issue
In local I need to connect to database using appsettings.json but in other environments like dev,staging and prod need to get connection string for db from azure key vault.In launchsettings.json I have set environment to local and when I run the project in local I am getting error in program.cs as 'The ConfigureServices method must either be parameterless or take only one parameter of type IServiceCollection.'Please let me know what is the issue here or how to fix it
appsettings.json
{
"KeyVault": {
"Vault": "Bookskv"
},
"MongoConnection": {
"ConnectionString": "<set by keyvault>",
"Database": "Books"
},
"MongoLocal": {
"ConnectionString": "mongodb:localhost:1230",
"Database": "Books"
}
}
Program.cs
public static IWebHost CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((ctx, builder) =>
{
var keyName = string.Empty;
if (ctx.HostingEnvironment.EnvironmentName!="Local")
{
var keyVaultEndpoint = GetKeyVaultEndpoint();
if (!string.IsNullOrEmpty(keyVaultEndpoint))
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
if(ctx.HostingEnvironment.EnvironmentName=="Development")
{
keyName = "BooksdevDb";
}
else if(ctx.HostingEnvironment.EnvironmentName == "Production")
{
keyName = "BooksprodDb";
}
var secretBundle = keyVaultClient.GetSecretAsync("https://Bookskv.vault.azure.net/secrets/{keyName}").Result;
var secret = secretBundle.Value;
builder.AddAzureKeyVault(
keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
}
}
}
).UseUrls("http://localhost:44315")
.UseKestrel()
.UseIISIntegration()
.UseIIS()
.UseStartup<Startup>()
.Build();
}
private static string GetKeyVaultEndpoint() => "https://Bookskv.vault.azure.net";
}
Startup.cs
services.Configure<Settings>(options =>
{
if (env.IsDevelopment() || env.IsStaging() || env.IsProduction())
{
options.ConnectionString = Configuration.GetSection("MongoConnection:ConnectionString").Value;
options.Database = Configuration.GetSection("MongoConnection:Database").Value;
}
else
{
options.ConnectionString = Configuration.GetSection("MongoLocal:ConnectionString").Value;
options.Database = Configuration.GetSection("MongoLocal:Database").Value;
}
});
Settings.cs
public class Settings
{
public string ConnectionString;
public string Database;
}
Solution
I have already implemented same thing in my project. Donot need to write too much code.
Before Implementing/Following below steps. DO THE STEPS WHICH I MENTIONED IN ANSWER OF THIS QUESTION
- Create Two AppSettings :- appsettings.Development.json and appsettings.Production.json
appsettings.Development.json
{
"DBConnection": "xyz"
}
appsettings.Production.json
{
"KeyVaultName": "keyvalutname"
}
- Add/Install Nuget Package for KeyVault
Azure.Security.KeyVault.Secrets
- 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($"https://{this._config["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential()) ;
}
}
}
- 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());
}
});
- Write the below where need to fetch secret.
var valueofSecret = configuration["DBConnection"];
configuration is IConfiguration
IF YOUR APPLICATION IS NOT APP SERVICE OR IT IS DEVELOPED IN .NET FRAMEWORK
Then Implement KEYVAULT using Certificate
Install Same Nuget Packages
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));
});
- 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";
}
- Write the below where need to fetch secret.
var valueofSecret = configuration["DBConnection"];
Answered By - Pradeep Kumar Answer Checked By - David Goodson (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.