A day with .Net

My day to day experince in .net

Archive for January, 2021

Integrate azure key vault secrets to your Asp.net core app

Posted by vivekcek on January 2, 2021

Provision an azure key vault resource in azure and ensure service identity is configured in access policy.

Add below dependencies.

Azure.Security.KeyVault.Secrets;
Azure.Identity;
Azure.Extensions.AspNetCore.Configuration.Secrets;

Write below code in Program.cs

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            if (context.HostingEnvironment.IsProduction())
            {
                var builtConfig = config.Build();
                var secretClient = new SecretClient(new Uri($"https://{builtConfig["KeyVaultName"]}.vault.azure.net/"),
                                                         new DefaultAzureCredential());
                config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());


            }
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Posted in Asp.net, ASP.NET Core, Azure, Azure key vault | Leave a Comment »

Validate appsettings configuration values at startup in ASP.NET Core – IStartupFilter

Posted by vivekcek on January 2, 2021

We can validate the configuration settings in appsettings.json during the startup of an asp.net core application. The advantage is your application won’t start, In case if a setting is missing or in bad format.

First we need to use the concept of strongly typed configuration in asp.net core.

My configuration is like below.

{
 "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "MyApi": {
    "MyUrl": "http://example.com/url",
    "Name": "Vivek",
    "Notify": true
  }
}

For the above configuration, i will create a class like below.

public class MyApiSettings
{
    public string MyUrl { get; set; }
    public string Name { get; set; }
    public bool Notify { get; set; }
}

Register the class in startup. So that the properties in json file is bind to the above class.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
 
    services.Configure<MyApiSettings>(Configuration.GetSection("MyApi")); 

    services.AddSingleton(resolver => 
        resolver.GetRequiredService<IOptions<MyApiSettings>>().Value);
}

Now you can use this settings in your controller as below.

public class MyController : Controller
{
    private readonly MyApiSettings _myApiSettings;
    public MyController(MyApiSettings settings)
    {
        _myApiSettings = settings;
    }

    public object Get()
    {
        return _myApiSettings;
    }
}

Now how can we validate the properties?. What will happen if “MyUrl” is null or it’s not in Url format.

Create an interface.

public interface IValidatable
{
    void Validate();
}

Now create a settings validator by extending IStartUpFilter.

public class SettingValidationStartupFilter : IStartupFilter
{
    readonly IEnumerable<IValidatable> _validatableObjects;
    public SettingValidationStartupFilter(IEnumerable<IValidatable> validatableObjects)
    {
        _validatableObjects = validatableObjects;
    }

    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        foreach (var validatableObject in _validatableObjects)
        {
            validatableObject.Validate();
        }

        return next;
    }
}

Now decorate our strongly typed class with data annotations.

public class MyApiSettings : IValidatable
{
    [Required, Url]
    public string MyUrl { get; set; }
    [Required]
    public string Name { get; set; }
    public bool Notify { get; set; }

    public void Validate()
    {
        Validator.ValidateObject(this, new ValidationContext(this), validateAllProperties: true);
    }
}

The final step is register the startup filter.

public void ConfigureServices(IServiceCollection services)  
{
    services.AddMvc();

    services.AddTransient<IStartupFilter, SettingValidationStartupFilter>()
    services.Configure<MyApiSettings>(Configuration.GetSection("MyApi")); 

    services.AddSingleton(resolver => 
        resolver.GetRequiredService<IOptions<MyApiSettings>>().Value);

    // Register as an IValidatable
    services.AddSingleton<IValidatable>(resolver => 
        resolver.GetRequiredService<IOptions<MyApiSettings>>().Value);
}

Now if any value is missing exception will be thrown at startup.

Posted in ASP.NET Core | Leave a Comment »