I have a full functioning website. Yesterday I have bound my secrets using Azure Key Vault Service.
In my secrets I'm only storing the SendGridKey and EmailKey.
The following dependencies have been added in my csproj
file:
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.0.2" />
<PackageReference Include="Azure.Identity" Version="1.3.0" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.1.0" />
My Program.cs
file has been automatically updated as follows:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var keyVaultEndpoint = new Uri(Environment.GetEnvironmentVariable("MyKeyVault"));
config.AddAzureKeyVault(
keyVaultEndpoint,
new DefaultAzureCredential());
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Publishing the website in Azure still works perfectly, but I'm not more able to start my website in Debug modus.
I'm getting the following error:
An error occurred while starting the application.
ArgumentNullException: Value cannot be null. (Parameter 'uriString')
System.Uri..ctor(string uriString)
ArgumentNullException: Value cannot be null. (Parameter 'uriString')
The problem is:
var keyVaultEndpoint = new Uri(Environment.GetEnvironmentVariable("MyKeyVault"));
because Environment.GetEnvironmentVariable("MyKeyVault")
is returning NULL
My Startup file is:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
var options = new RewriteOptions()
.AddRedirectToWwwPermanent()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Any suggestion?
Update
I have a similar project with the following code block:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var keyVaultEndpoint = GetKeyVaultEndpoint();
if (!string.IsNullOrEmpty(keyVaultEndpoint))
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
config.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
private static string GetKeyVaultEndpoint() => "https://mykeyvault.vault.azure.net/";
I've used the following packages:
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.0.0" />
<PackageReference Include="Azure.Identity" Version="1.1.1" />
<PackageReference Include="Microsoft.Azure.KeyVault.Core" Version="3.0.5" />
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.6.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.8" />
<PackageReference Include="SendGrid" Version="9.21.0" />
Microsoft.Azure.Services.AppAuthentication has been deprecated and the above code works no longer in my new project. It works indeed in my old one.
With this few lines of code, it works again both in development and production:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
if (context.HostingEnvironment.IsDevelopment())
{
// Do simply nothing
}
else
{
var keyVaultEndpoint = new Uri(Environment.GetEnvironmentVariable("MyKeyVault"));
config.AddAzureKeyVault(
keyVaultEndpoint,
new DefaultAzureCredential());
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
In development, the secrets are retrieved from secrets.json
, in production from Azure KeyVault.